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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

82#include

83#include

84#include

85

86using namespace llvm;

87

88#define DEBUG_TYPE "aarch64-condopt"

89

90STATISTIC(NumConditionsAdjusted, "Number of conditions adjusted");

91

92namespace {

93

98

99public:

100

101

102 using CmpInfo = std::tuple<int, unsigned, AArch64CC::CondCode>;

103

104 static char ID;

105

107

108 void getAnalysisUsage(AnalysisUsage &AU) const override;

109 MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);

111 void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);

112 bool adjustTo(MachineInstr *CmpMI, AArch64CC::CondCode Cmp, MachineInstr *To,

113 int ToImm);

114 bool runOnMachineFunction(MachineFunction &MF) override;

115

116 StringRef getPassName() const override {

117 return "AArch64 Condition Optimizer";

118 }

119};

120

121}

122

123char AArch64ConditionOptimizer::ID = 0;

124

126 "AArch64 CondOpt Pass", false, false)

130

132 return new AArch64ConditionOptimizer();

133}

134

135void AArch64ConditionOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {

139}

140

141

142

143

144MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(

145 MachineBasicBlock *MBB) {

147 if (Term == MBB->end())

148 return nullptr;

149

150 if (Term->getOpcode() != AArch64::Bcc)

151 return nullptr;

152

153

155 if (SuccBB->isLiveIn(AArch64::NZCV))

156 return nullptr;

157

158

161 MachineInstr &I = *It;

162 assert(I.isTerminator() && "Spurious terminator");

163

164 if (I.readsRegister(AArch64::NZCV, nullptr))

165 return nullptr;

166 switch (I.getOpcode()) {

167

168 case AArch64::SUBSWri:

169 case AArch64::SUBSXri:

170

171 case AArch64::ADDSWri:

172 case AArch64::ADDSXri: {

174 if (I.getOperand(2).isImm()) {

175 LLVM_DEBUG(dbgs() << "Immediate of cmp is symbolic, " << I << '\n');

176 return nullptr;

177 } else if (I.getOperand(2).getImm() << ShiftAmt >= 0xfff) {

178 LLVM_DEBUG(dbgs() << "Immediate of cmp may be out of range, " << I

179 << '\n');

180 return nullptr;

181 } else if (MRI->use_nodbg_empty(I.getOperand(0).getReg())) {

182 LLVM_DEBUG(dbgs() << "Destination of cmp is not dead, " << I << '\n');

183 return nullptr;

184 }

185 return &I;

186 }

187

188

189

190

191

192

193 case AArch64::FCMPDri:

194 case AArch64::FCMPSri:

195 case AArch64::FCMPESri:

196 case AArch64::FCMPEDri:

197

198 case AArch64::SUBSWrr:

199 case AArch64::SUBSXrr:

200 case AArch64::ADDSWrr:

201 case AArch64::ADDSXrr:

202 case AArch64::FCMPSrr:

203 case AArch64::FCMPDrr:

204 case AArch64::FCMPESrr:

205 case AArch64::FCMPEDrr:

206

207 return nullptr;

208 }

209 }

211 << '\n');

212 return nullptr;

213}

214

215

217 switch (Opc) {

218 case AArch64::ADDSWri: return AArch64::SUBSWri;

219 case AArch64::ADDSXri: return AArch64::SUBSXri;

220 case AArch64::SUBSWri: return AArch64::ADDSWri;

221 case AArch64::SUBSXri: return AArch64::ADDSXri;

222 default:

224 }

225}

226

227

229 switch (Cmp) {

234 default:

236 }

237}

238

239

240

241AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(

244

245

246

247 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);

248

250

251 if (Negative) {

252 Correction = -Correction;

253 }

254

256 const int NewImm = std::abs(OldImm + Correction);

257

258

259

260 if (OldImm == 0 && ((Negative && Correction == 1) ||

261 (!Negative && Correction == -1))) {

263 }

264

266}

267

268

269void AArch64ConditionOptimizer::modifyCmp(MachineInstr *CmpMI,

270 const CmpInfo &Info) {

272 unsigned Opc;

274 std::tie(Imm, Opc, Cmp) = Info;

275

276 MachineBasicBlock *const MBB = CmpMI->getParent();

277

278

285

286

287

289

290

295

296 ++NumConditionsAdjusted;

297}

298

299

300

301

303

305 assert(Cond.size() == 1 && "Unknown Cond array format");

307 return true;

308 }

309 return false;

310}

311

312

313

314

315bool AArch64ConditionOptimizer::adjustTo(MachineInstr *CmpMI,

317{

318 CmpInfo Info = adjustCmp(CmpMI, Cmp);

319 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->getOpcode()) {

320 modifyCmp(CmpMI, Info);

321 return true;

322 }

323 return false;

324}

325

326bool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {

327 LLVM_DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n"

328 << "********** Function: " << MF.getName() << '\n');

330 return false;

331

333 DomTree = &getAnalysis().getDomTree();

335

337

338

339

340

341

342

344 MachineBasicBlock *HBB = I->getBlock();

345

347 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;

349 continue;

350 }

351

352

353 if (TBB || TBB == HBB) {

354 continue;

355 }

356

358 MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;

360 continue;

361 }

362

363 MachineInstr *HeadCmpMI = findSuitableCompare(HBB);

364 if (!HeadCmpMI) {

365 continue;

366 }

367

368 MachineInstr *TrueCmpMI = findSuitableCompare(TBB);

369 if (!TrueCmpMI) {

370 continue;

371 }

372

374 if (HeadCond.empty() || parseCond(HeadCond, HeadCmp)) {

375 continue;

376 }

377

379 if (TrueCond.empty() || parseCond(TrueCond, TrueCmp)) {

380 continue;

381 }

382

385

388 << '\n');

389 LLVM_DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n');

390

393 << '\n');

394 LLVM_DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n');

395

398 std::abs(TrueImm - HeadImm) == 2) {

399

400

401

402

403

404

405

406

407

408

409 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);

410 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);

411 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&

412 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {

413 modifyCmp(HeadCmpMI, HeadCmpInfo);

414 modifyCmp(TrueCmpMI, TrueCmpInfo);

416 }

419 std::abs(TrueImm - HeadImm) == 1) {

420

421

422

423

424

425

426

427

428

429

430

431

432 bool adjustHeadCond = (HeadImm < TrueImm);

434 adjustHeadCond = !adjustHeadCond;

435 }

436

437 if (adjustHeadCond) {

438 Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);

439 } else {

440 Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);

441 }

442 }

443

444

445 }

446

448}

unsigned const MachineRegisterInfo * MRI

static int getComplementOpc(int Opc)

Definition AArch64ConditionOptimizer.cpp:216

static AArch64CC::CondCode getAdjustedCmp(AArch64CC::CondCode Cmp)

Definition AArch64ConditionOptimizer.cpp:228

static bool parseCond(ArrayRef< MachineOperand > Cond, AArch64CC::CondCode &CC)

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

const TargetInstrInfo & TII

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

Analysis containing CSE Info

This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

const SmallVectorImpl< MachineOperand > & Cond

This file defines the SmallVector class.

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

#define STATISTIC(VARNAME, DESC)

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

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.

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

iterator_range< succ_iterator > successors()

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

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.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void eraseFromParent()

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

const MachineOperand & getOperand(unsigned i) const

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

TargetInstrInfo - Interface to description of machine instruction set.

virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const

Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....

virtual const TargetInstrInfo * getInstrInfo() const

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

static const char * getCondCodeName(CondCode Code)

static unsigned getShiftValue(unsigned Imm)

getShiftValue - Extract the shift value.

unsigned ID

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

This is an optimization pass for GlobalISel generic memory operations.

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

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

MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)

LLVM_ABI raw_ostream & dbgs()

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

FunctionPass * createAArch64ConditionOptimizerPass()

Definition AArch64ConditionOptimizer.cpp:131

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode

iterator_range< df_iterator< T > > depth_first(const T &G)

IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)

Decrement It, then continue decrementing it while it points to a debug instruction.

LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.