LLVM: lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

26

27#define DEBUG_TYPE "aarch64-post-select-optimize"

28

29using namespace llvm;

30

31namespace {

33public:

34 static char ID;

35

37

38 StringRef getPassName() const override {

39 return "AArch64 Post Select Optimizer";

40 }

41

43

44 void getAnalysisUsage(AnalysisUsage &AU) const override;

45

46private:

49

52};

53}

54

55void AArch64PostSelectOptimize::getAnalysisUsage(AnalysisUsage &AU) const {

60}

61

63 switch (Opc) {

64 default:

65 return 0;

66 case AArch64::SUBSXrr:

67 return AArch64::SUBXrr;

68 case AArch64::SUBSWrr:

69 return AArch64::SUBWrr;

70 case AArch64::SUBSXrs:

71 return AArch64::SUBXrs;

72 case AArch64::SUBSWrs:

73 return AArch64::SUBWrs;

74 case AArch64::SUBSXri:

75 return AArch64::SUBXri;

76 case AArch64::SUBSWri:

77 return AArch64::SUBWri;

78 case AArch64::ADDSXrr:

79 return AArch64::ADDXrr;

80 case AArch64::ADDSWrr:

81 return AArch64::ADDWrr;

82 case AArch64::ADDSXrs:

83 return AArch64::ADDXrs;

84 case AArch64::ADDSWrs:

85 return AArch64::ADDWrs;

86 case AArch64::ADDSXri:

87 return AArch64::ADDXri;

88 case AArch64::ADDSWri:

89 return AArch64::ADDWri;

90 case AArch64::SBCSXr:

91 return AArch64::SBCXr;

92 case AArch64::SBCSWr:

93 return AArch64::SBCWr;

94 case AArch64::ADCSXr:

95 return AArch64::ADCXr;

96 case AArch64::ADCSWr:

97 return AArch64::ADCWr;

98 }

99}

100

101bool AArch64PostSelectOptimize::doPeepholeOpts(MachineBasicBlock &MBB) {

104 bool CurrentIterChanged = foldSimpleCrossClassCopies(MI);

105 if (!CurrentIterChanged)

106 CurrentIterChanged |= foldCopyDup(MI);

107 Changed |= CurrentIterChanged;

108 }

110}

111

112bool AArch64PostSelectOptimize::foldSimpleCrossClassCopies(MachineInstr &MI) {

113 auto *MF = MI.getMF();

114 auto &MRI = MF->getRegInfo();

115

116 if (MI.isCopy())

117 return false;

118

119 if (MI.getOperand(1).getSubReg())

120 return false;

121

122 Register Src = MI.getOperand(1).getReg();

123 Register Dst = MI.getOperand(0).getReg();

124

125 if (Src.isPhysical() || Dst.isPhysical())

126 return false;

127

128 const TargetRegisterClass *SrcRC = MRI.getRegClass(Src);

129 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);

130

131 if (SrcRC == DstRC)

132 return false;

133

134

136

137

138

139

140 if (MRI.hasOneNonDBGUse(Src))

141 return false;

142

143

144

145 if (MRI.constrainRegClass(Src, DstRC, 25))

146 return false;

148

149

150

151 } else {

152 return false;

153 }

154

155 MRI.replaceRegWith(Dst, Src);

156 MI.eraseFromParent();

157 return true;

158}

159

160bool AArch64PostSelectOptimize::foldCopyDup(MachineInstr &MI) {

161 if (MI.isCopy())

162 return false;

163

164 auto *MF = MI.getMF();

165 auto &MRI = MF->getRegInfo();

166 auto *TII = MF->getSubtarget().getInstrInfo();

167

168

169

170 Register Dst = MI.getOperand(0).getReg();

171 Register Src = MI.getOperand(1).getReg();

172

173 if (!Dst.isVirtual() || !Src.isVirtual())

174 return false;

175

176 auto TryMatchDUP = [&](const TargetRegisterClass *GPRRegClass,

177 const TargetRegisterClass *FPRRegClass, unsigned DUP,

178 unsigned UMOV) {

179 if (MRI.getRegClassOrNull(Dst) != GPRRegClass ||

180 MRI.getRegClassOrNull(Src) != FPRRegClass)

181 return false;

182

183

184

185

186

187 for (auto &Use : MRI.use_nodbg_instructions(Dst)) {

188 if (Use.isCopy())

189 continue;

190

191 Register UseOp0 = Use.getOperand(0).getReg();

192 Register UseOp1 = Use.getOperand(1).getReg();

194 return false;

195

196 if (MRI.getRegClassOrNull(UseOp0) == FPRRegClass &&

197 MRI.getRegClassOrNull(UseOp1) == GPRRegClass)

198 return false;

199 }

200

201 MachineInstr *SrcMI = MRI.getUniqueVRegDef(Src);

202 if (!SrcMI || SrcMI->getOpcode() != DUP || MRI.hasOneNonDBGUse(Src))

203 return false;

204

207

212 MI.eraseFromParent();

213 return true;

214 };

215

216 return TryMatchDUP(&AArch64::GPR32RegClass, &AArch64::FPR32RegClass,

217 AArch64::DUPi32, AArch64::UMOVvi32) ||

218 TryMatchDUP(&AArch64::GPR64RegClass, &AArch64::FPR64RegClass,

219 AArch64::DUPi64, AArch64::UMOVvi64);

220}

221

222bool AArch64PostSelectOptimize::optimizeNZCVDefs(MachineBasicBlock &MBB) {

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

253 const auto &TII = Subtarget.getInstrInfo();

254 auto TRI = Subtarget.getRegisterInfo();

255 auto RBI = Subtarget.getRegBankInfo();

256 auto &MRI = MF.getRegInfo();

257

259 LRU.addLiveOuts(MBB);

260

262 bool NZCVDead = LRU.available(AArch64::NZCV);

263 if (NZCVDead && II.definesRegister(AArch64::NZCV, nullptr)) {

264

266 int DeadNZCVIdx =

267 II.findRegisterDefOperandIdx(AArch64::NZCV, nullptr);

268 if (DeadNZCVIdx != -1) {

269 if (NewOpc) {

270

271 LLVM_DEBUG(dbgs() << "Post-select optimizer: converting flag-setting "

272 "op: "

273 << II);

274 II.setDesc(TII->get(NewOpc));

275 II.removeOperand(DeadNZCVIdx);

276

277

278

280 II.getOperand(0), 0);

282 } else {

283

284

285 II.getOperand(DeadNZCVIdx).setIsDead();

286 }

287 }

288 }

289 LRU.stepBackward(II);

290 }

292}

293

294bool AArch64PostSelectOptimize::runOnMachineFunction(MachineFunction &MF) {

296 return false;

298

300 for (auto &BB : MF) {

301 Changed |= optimizeNZCVDefs(BB);

302 Changed |= doPeepholeOpts(BB);

303 }

305}

306

307char AArch64PostSelectOptimize::ID = 0;

309 "Optimize AArch64 selected instructions",

310 false, false)

312 "Optimize AArch64 selected instructions", false,

314

315namespace llvm {

317 return new AArch64PostSelectOptimize();

318}

319}

unsigned const MachineRegisterInfo * MRI

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

unsigned getNonFlagSettingVariant(unsigned Opc)

Definition AArch64PostSelectOptimize.cpp:62

const TargetInstrInfo & TII

Register const TargetRegisterInfo * TRI

Promote Memory to Register

uint64_t IntrinsicInst * II

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

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

Target-Independent Code Generator Pass Configuration Options pass.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

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

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

reverse_iterator rbegin()

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.

const MachineFunctionProperties & getProperties() const

Get the function properties.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void eraseFromParent()

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

const MachineOperand & getOperand(unsigned i) const

Register getReg() const

getReg - Returns the register number.

constexpr bool isPhysical() const

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

StringRef - Represent a constant reference to a string, i.e.

bool hasSubClass(const TargetRegisterClass *RC) const

Return true if the specified TargetRegisterClass is a proper sub-class of this TargetRegisterClass.

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

unsigned ID

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

NodeAddr< UseNode * > Use

This is an optimization pass for GlobalISel generic memory operations.

FunctionPass * createAArch64PostSelectOptimize()

Definition AArch64PostSelectOptimize.cpp:316

LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)

Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

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.

auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)

Construct a range iterator which begins at It and moves forwards until End is reached,...

LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)

Modify analysis usage so it preserves passes required for the SelectionDAG fallback.