LLVM: lib/Target/PowerPC/PPCVSXFMAMutate.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

33

34using namespace llvm;

35

36

37

38

39

41 "disable-ppc-vsx-fma-mutation",

42 cl::desc("Disable VSX FMA instruction mutation"), cl::init(true),

44

45#define DEBUG_TYPE "ppc-vsx-fma-mutate"

46

47namespace llvm { namespace PPC {

49} }

50

51namespace {

52

53

54

56 static char ID;

58

59 LiveIntervals *LIS;

60 const PPCInstrInfo *TII;

61

62protected:

63 bool processBlock(MachineBasicBlock &MBB) {

65

67 const TargetRegisterInfo *TRI = &TII->getRegisterInfo();

69 I != IE; ++I) {

70 MachineInstr &MI = *I;

71

72

73

74

75

76

77

79 if (AltOpc == -1)

80 continue;

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101 SlotIndex FMAIdx = LIS->getInstructionIndex(MI);

102

103 VNInfo *AddendValNo =

104 LIS->getInterval(MI.getOperand(1).getReg()).Query(FMAIdx).valueIn();

105

106

107 if (!AddendValNo)

108 continue;

109

110 MachineInstr *AddendMI = LIS->getInstructionFromIndex(AddendValNo->def);

111

112

113

114 if (!AddendMI || AddendMI->getParent() != MI.getParent())

115 continue;

116

117

118

120 continue;

121

125 MRI.getRegClass(AddendSrcReg))

126 continue;

127 } else {

128

129

131 ->contains(AddendSrcReg))

132 continue;

133 }

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153 bool OtherUsers = false, KillsAddendSrc = false;

155 J != JE; --J) {

156 if (J->readsVirtualRegister(AddendMI->getOperand(0).getReg())) {

157 OtherUsers = true;

158 break;

159 }

160 if (J->modifiesRegister(AddendSrcReg, TRI) ||

161 J->killsRegister(AddendSrcReg, TRI)) {

162 KillsAddendSrc = true;

163 break;

164 }

165 }

166

167 if (OtherUsers || KillsAddendSrc)

168 continue;

169

170

171

172

173

174

175

176

177

178 Register OldFMAReg = MI.getOperand(0).getReg();

179

180

181 unsigned KilledProdOp = 0, OtherProdOp = 0;

182 Register Reg2 = MI.getOperand(2).getReg();

183 Register Reg3 = MI.getOperand(3).getReg();

184 if (LIS->getInterval(Reg2).Query(FMAIdx).isKill()

185 && Reg2 != OldFMAReg) {

186 KilledProdOp = 2;

187 OtherProdOp = 3;

188 } else if (LIS->getInterval(Reg3).Query(FMAIdx).isKill()

189 && Reg3 != OldFMAReg) {

190 KilledProdOp = 3;

191 OtherProdOp = 2;

192 }

193

194

195

196 if (!KilledProdOp)

197 continue;

198

199

200

201

202

203

205 !LIS->getInterval(AddendSrcReg).liveAt(FMAIdx))

206 continue;

207

208

209

210 Register KilledProdReg = MI.getOperand(KilledProdOp).getReg();

211 Register OtherProdReg = MI.getOperand(OtherProdOp).getReg();

212

214 unsigned KilledProdSubReg = MI.getOperand(KilledProdOp).getSubReg();

215 unsigned OtherProdSubReg = MI.getOperand(OtherProdOp).getSubReg();

216

218 bool KilledProdRegKill = MI.getOperand(KilledProdOp).isKill();

219 bool OtherProdRegKill = MI.getOperand(OtherProdOp).isKill();

220

222 bool KilledProdRegUndef = MI.getOperand(KilledProdOp).isUndef();

223 bool OtherProdRegUndef = MI.getOperand(OtherProdOp).isUndef();

224

225

226

227

228

229 if (MRI.constrainRegClass(KilledProdReg,

230 MRI.getRegClass(OldFMAReg)))

231 continue;

232

234 "Addend copy not tied to old FMA output!");

235

237

238 MI.getOperand(0).setReg(KilledProdReg);

239 MI.getOperand(1).setReg(KilledProdReg);

240 MI.getOperand(3).setReg(AddendSrcReg);

241

242 MI.getOperand(0).setSubReg(KilledProdSubReg);

243 MI.getOperand(1).setSubReg(KilledProdSubReg);

245

246 MI.getOperand(1).setIsKill(KilledProdRegKill);

247 MI.getOperand(3).setIsKill(AddRegKill);

248

249 MI.getOperand(1).setIsUndef(KilledProdRegUndef);

250 MI.getOperand(3).setIsUndef(AddRegUndef);

251

252 MI.setDesc(TII->get(AltOpc));

253

254

255

257 MI.getOperand(2).setReg(AddendSrcReg);

259 MI.getOperand(2).setIsKill(AddRegKill);

260 MI.getOperand(2).setIsUndef(AddRegUndef);

261 } else {

262 MI.getOperand(2).setReg(OtherProdReg);

263 MI.getOperand(2).setSubReg(OtherProdSubReg);

264 MI.getOperand(2).setIsKill(OtherProdRegKill);

265 MI.getOperand(2).setIsUndef(OtherProdRegUndef);

266 }

267

269

270

271

272

273 LiveInterval &FMAInt = LIS->getInterval(OldFMAReg);

275 for (auto UI = MRI.reg_nodbg_begin(OldFMAReg), UE = MRI.reg_nodbg_end();

276 UI != UE;) {

277 MachineOperand &UseMO = *UI;

279 ++UI;

280

281

282 if (UseMI == AddendMI)

283 continue;

284

285 UseMO.substVirtReg(KilledProdReg, KilledProdSubReg, *TRI);

286 }

287

288

289 LIS->removeInterval(KilledProdReg);

290 LiveInterval &NewFMAInt =

291 LIS->createAndComputeVirtRegInterval(KilledProdReg);

292

293 LLVM_DEBUG(dbgs() << " extended: " << NewFMAInt << '\n');

294 (void)NewFMAInt;

295

296

297

298

300 for (MCRegUnit Unit : TRI->regunits(AddendSrcReg.asMCReg())) {

301 LiveRange &AddendSrcRange = LIS->getRegUnit(Unit);

304 LLVM_DEBUG(dbgs() << " extended: " << AddendSrcRange << '\n');

305 }

306

308 LLVM_DEBUG(dbgs() << " trimmed: " << FMAInt << '\n');

309

310

311

312 LLVM_DEBUG(dbgs() << " removing: " << *AddendMI << '\n');

313 LIS->RemoveMachineInstrFromMaps(*AddendMI);

315

317 }

318

320 }

321

322public:

323 bool runOnMachineFunction(MachineFunction &MF) override {

325 return false;

326

327

328

329 const PPCSubtarget &STI = MF.getSubtarget();

330 if (!STI.hasVSX())

331 return false;

332

333 LIS = &getAnalysis().getLIS();

334

336

338

341

343 if (processBlock(B))

345

347 }

348

349 void getAnalysisUsage(AnalysisUsage &AU) const override {

350 AU.addRequired();

352 AU.addRequired();

354 AU.addRequired();

355 AU.addPreserved();

357 }

358 };

359}

360

362 "PowerPC VSX FMA Mutation", false, false)

368

370

371char PPCVSXFMAMutate::ID = 0;

373 return new PPCVSXFMAMutate();

374}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, unsigned State, const TargetRegisterInfo *TRI)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static cl::opt< bool > DisableVSXFMAMutate("disable-ppc-vsx-fma-mutation", cl::desc("Disable VSX FMA instruction mutation"), cl::init(true), cl::Hidden)

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

SI Optimize VGPR LiveRange

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

FunctionPass class - This class is used to implement most global optimizations.

LLVM_ABI void removeValNo(VNInfo *ValNo)

removeValNo - Remove all the segments defined by the specified value#.

LLVM_ABI std::pair< VNInfo *, bool > extendInBlock(ArrayRef< SlotIndex > Undefs, SlotIndex StartIdx, SlotIndex Kill)

Attempt to extend a value defined after StartIdx to include Use.

VNInfo * getVNInfoAt(SlotIndex Idx) const

getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineBasicBlock * getParent() const

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

const MachineOperand & getOperand(unsigned i) const

unsigned getSubReg() const

LLVM_ABI void substVirtReg(Register Reg, unsigned SubIdx, const TargetRegisterInfo &)

substVirtReg - Substitute the current register with the virtual subregister Reg:SubReg.

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

Register getReg() const

getReg - Returns the register number.

const PPCInstrInfo * getInstrInfo() const override

MCRegister asMCReg() const

Utility to check-convert this value to a MCRegister.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

SlotIndex getRegSlot(bool EC=false) const

Returns the register use/def slot in the current instruction for a normal or early-clobber def.

SlotIndex def

The index of the defining instruction.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

Define some predicates that are used for node matching.

int getAltVSXFMAOpcode(uint16_t Opcode)

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

FunctionPass * createPPCVSXFMAMutatePass()

Definition PPCVSXFMAMutate.cpp:372

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

char & PPCVSXFMAMutateID

Definition PPCVSXFMAMutate.cpp:369