LLVM: lib/Target/ARC/ARCOptAddrMode.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15#define GET_INSTRMAP_INFO

29

30using namespace llvm;

31

32#define OPTADDRMODE_DESC "ARC load/store address mode"

33#define OPTADDRMODE_NAME "arc-addr-mode"

34#define DEBUG_TYPE "arc-addr-mode"

35

36namespace llvm {

37

40

41#define DUMP_BEFORE() ((ArcKillAddrMode & 0x0001) != 0)

42#define DUMP_AFTER() ((ArcKillAddrMode & 0x0002) != 0)

43#define VIEW_BEFORE() ((ArcKillAddrMode & 0x0004) != 0)

44#define VIEW_AFTER() ((ArcKillAddrMode & 0x0008) != 0)

45#define KILL_PASS() ((ArcKillAddrMode & 0x0010) != 0)

46

49}

50

51namespace {

53public:

54 static char ID;

55

57

58 StringRef getPassName() const override { return OPTADDRMODE_DESC; }

59

60 void getAnalysisUsage(AnalysisUsage &AU) const override {

63 AU.addRequired();

64 AU.addPreserved();

65 }

66

67 bool runOnMachineFunction(MachineFunction &MF) override;

68

69private:

70 const ARCSubtarget *AST = nullptr;

71 const ARCInstrInfo *AII = nullptr;

72 MachineRegisterInfo *MRI = nullptr;

73 MachineDominatorTree *MDT = nullptr;

74

75

76

77 MachineInstr *tryToCombine(MachineInstr &Ldst);

78

79

80 bool noUseOfAddBeforeLoadOrStore(const MachineInstr *Add,

81 const MachineInstr *Ldst);

82

83

84

85 bool canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To);

86

87

88

89

90

91

92

93

94

95 MachineInstr *canJoinInstructions(MachineInstr *Ldst, MachineInstr *Add,

96 SmallVectorImpl<MachineInstr *> *Uses);

97

98

99

101 MachineOperand &Incr, unsigned BaseReg);

102

103

104

107

108

109

110

111 void changeToAddrMode(MachineInstr &Ldst, unsigned NewOpcode,

112 unsigned NewBase, MachineOperand &NewOffset);

113

114 bool processBasicBlock(MachineBasicBlock &MBB);

115};

116

117}

118

119char ARCOptAddrMode::ID = 0;

121 false)

125

126

127

129

130

131

133

135 int64_t Sign = 1;

136 switch (MI.getOpcode()) {

137 case ARC::SUB_rru6:

138 Sign = -1;

139 [[fallthrough]];

140 case ARC::ADD_rru6:

141 assert(MI.getOperand(2).isImm() && "Expected immediate operand");

142 Amount = Sign * MI.getOperand(2).getImm();

143 return true;

144 default:

145 return false;

146 }

147}

148

149

153

155

158 if (User->isPHI()) {

161 if (MBB->empty()) {

163 assert(InstBB != MBB && "Instruction found in empty MBB");

165 return false;

166 continue;

167 }

169 }

170

172 return false;

173 }

174 return true;

175}

176

177

178

181 int64_t Disp) {

182 unsigned BasePos, OffPos;

183 if (TII->getBaseAndOffsetPosition(MI, BasePos, OffPos))

184 return false;

187 return false;

190}

191

192bool ARCOptAddrMode::noUseOfAddBeforeLoadOrStore(const MachineInstr *Add,

196}

197

198MachineInstr *ARCOptAddrMode::tryToCombine(MachineInstr &Ldst) {

200

201 unsigned BasePos, OffsetPos;

202

203 LLVM_DEBUG(dbgs() << "[ABAW] tryToCombine " << Ldst);

205 LLVM_DEBUG(dbgs() << "[ABAW] Not a recognized load/store\n");

206 return nullptr;

207 }

208

211

212 assert(Base.isReg() && "Base operand must be register");

213 if (Offset.isImm()) {

214 LLVM_DEBUG(dbgs() << "[ABAW] Offset is not immediate\n");

215 return nullptr;

216 }

217

219 if (!Register::isVirtualRegister(B)) {

221 return nullptr;

222 }

223

224

225 if (Offset.getImm() != 0) {

227 return nullptr;

228 }

229

230 for (auto &Add : MRI->use_nodbg_instructions(B)) {

231 int64_t Incr;

233 continue;

235 continue;

236

237 SmallVector<MachineInstr *, 8> Uses;

238 MachineInstr *MoveTo = canJoinInstructions(&Ldst, &Add, &Uses);

239

240 if (!MoveTo)

241 continue;

242

243 if (!canFixPastUses(Uses, Add.getOperand(2), B))

244 continue;

245

248 dbgs() << "[ABAW] Instructions " << *First << " and " << *Last

249 << " combined\n";

250

251 );

252

254 if (MoveTo == &Add) {

257 }

258 if (Result == &Add)

260

261 fixPastUses(Uses, B, Incr);

262

263 int NewOpcode = ARC::getPostIncOpcode(Ldst.getOpcode());

264 assert(NewOpcode > 0 && "No postincrement form found");

265 unsigned NewBaseReg = Add.getOperand(0).getReg();

266 changeToAddrMode(Ldst, NewOpcode, NewBaseReg, Add.getOperand(2));

267 Add.eraseFromParent();

268

270 }

271 return nullptr;

272}

273

274MachineInstr *

275ARCOptAddrMode::canJoinInstructions(MachineInstr *Ldst, MachineInstr *Add,

276 SmallVectorImpl<MachineInstr *> *Uses) {

277 assert(Ldst && Add && "NULL instruction passed");

278

280 MachineInstr *Last = Ldst;

284 return nullptr;

285

287

288 unsigned BasePos, OffPos;

289

293 << "[canJoinInstructions] Cannot determine base/offset position\n");

294 return nullptr;

295 }

296

298

299

300

301

302

303

304

307 if (Add->getOperand(0).getReg() == StReg || BaseReg == StReg) {

308 LLVM_DEBUG(dbgs() << "[canJoinInstructions] Store uses result of Add\n");

309 return nullptr;

310 }

311 }

312

313 SmallVector<MachineInstr *, 4> UsesAfterLdst;

314 SmallVector<MachineInstr *, 4> UsesAfterAdd;

315 for (MachineInstr &MI : MRI->use_nodbg_instructions(BaseReg)) {

316 if (&MI == Ldst || &MI == Add)

317 continue;

321 return nullptr;

324 }

325

326 MachineInstr *Result = nullptr;

327

329

330

331

332

333 if (noUseOfAddBeforeLoadOrStore(First, Last)) {

335 LLVM_DEBUG(dbgs() << "[canJoinInstructions] Can sink Add down to Ldst\n");

336 } else if (canHoistLoadStoreTo(Ldst, Add)) {

338 LLVM_DEBUG(dbgs() << "[canJoinInstructions] Can hoist Ldst to Add\n");

339 }

340 } else {

341

342

343

345 LLVM_DEBUG(dbgs() << "[canJoinInstructions] Can hoist Add to Ldst\n");

346 }

347 if (Result && Uses)

348 *Uses = (Result == Ldst) ? UsesAfterLdst : UsesAfterAdd;

350}

351

353 MachineOperand &Incr, unsigned BaseReg) {

354

355 assert(Incr.isImm() && "Expected immediate increment");

356 int64_t NewOffset = Incr.getImm();

357 for (MachineInstr *MI : Uses) {

358 int64_t Dummy;

361 continue;

362 return false;

363 }

365 continue;

366 LLVM_DEBUG(dbgs() << "Instruction cannot handle displacement " << -NewOffset

367 << ": " << *MI);

368 return false;

369 }

370 return true;

371}

372

374 unsigned NewBase, int64_t NewOffset) {

375

376 for (MachineInstr *MI : Uses) {

377 int64_t Amount;

378 unsigned BasePos, OffPos;

380 NewOffset += Amount;

382 "New offset won't fit into ADD instr");

383 BasePos = 1;

384 OffPos = 2;

386 MachineOperand &MO = MI->getOperand(OffPos);

387 assert(MO.isImm() && "expected immediate operand");

388 NewOffset += MO.getImm();

390 "New offset won't fit into LD/ST");

391 } else

393

394 MI->getOperand(BasePos).setReg(NewBase);

395 MI->getOperand(OffPos).setImm(NewOffset);

396 }

397}

398

399bool ARCOptAddrMode::canHoistLoadStoreTo(MachineInstr *Ldst, MachineInstr *To) {

401 return false;

404

405 bool IsStore = Ldst->mayStore();

406 for (; MI != ME && MI != End; ++MI) {

407 if (MI->isDebugValue())

408 continue;

409 if (MI->mayStore() || MI->isCall() || MI->isInlineAsm() ||

410 MI->hasUnmodeledSideEffects())

411 return false;

412 if (IsStore && MI->mayLoad())

413 return false;

414 }

415

417 if (O.isReg() || O.isUse())

418 continue;

419 MachineInstr *OpDef = MRI->getVRegDef(O.getReg());

420 if (!OpDef || !MDT->dominates(OpDef, To))

421 return false;

422 }

423 return true;

424}

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451void ARCOptAddrMode::changeToAddrMode(MachineInstr &Ldst, unsigned NewOpcode,

452 unsigned NewBase,

453 MachineOperand &NewOffset) {

454 bool IsStore = Ldst.mayStore();

455 unsigned BasePos, OffPos;

458

460

463

464 if (IsStore) {

467 }

468

471 if (IsStore)

476}

477

478bool ARCOptAddrMode::processBasicBlock(MachineBasicBlock &MBB) {

481 if (MI->isDebugValue())

482 continue;

483 if (MI->mayLoad() && MI->mayStore())

484 continue;

485 if (ARC::getPostIncOpcode(MI->getOpcode()) < 0)

486 continue;

487 MachineInstr *Res = tryToCombine(*MI);

488 if (Res) {

490

492 }

493 }

495}

496

497bool ARCOptAddrMode::runOnMachineFunction(MachineFunction &MF) {

499 return false;

500

501#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

504#endif

507

511 MDT = &getAnalysis().getDomTree();

512

514 for (auto &MBB : MF)

516

517#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

519 MF.dump();

520#endif

522 MF.viewCFG();

524}

525

526

527

528

529

unsigned const MachineRegisterInfo * MRI

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

const TargetInstrInfo & TII

#define VIEW_BEFORE()

Definition ARCOptAddrMode.cpp:43

static bool isLoadStoreThatCanHandleDisplacement(const TargetInstrInfo *TII, const MachineInstr &MI, int64_t Disp)

Definition ARCOptAddrMode.cpp:179

static bool dominatesAllUsesOf(const MachineInstr *MI, unsigned VReg, MachineDominatorTree *MDT, MachineRegisterInfo *MRI)

Definition ARCOptAddrMode.cpp:150

static bool isValidIncrementOffset(int64_t Off)

Definition ARCOptAddrMode.cpp:132

static false bool isValidLoadStoreOffset(int64_t Off)

Definition ARCOptAddrMode.cpp:128

#define DUMP_AFTER()

Definition ARCOptAddrMode.cpp:42

#define OPTADDRMODE_NAME

Definition ARCOptAddrMode.cpp:33

#define KILL_PASS()

Definition ARCOptAddrMode.cpp:45

#define OPTADDRMODE_DESC

Definition ARCOptAddrMode.cpp:32

static bool isAddConstantOp(const MachineInstr &MI, int64_t &Amount)

Definition ARCOptAddrMode.cpp:134

#define VIEW_AFTER()

Definition ARCOptAddrMode.cpp:44

#define DUMP_BEFORE()

Definition ARCOptAddrMode.cpp:41

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

Promote Memory to Register

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

Remove Loads Into Fake Uses

virtual bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override

const ARCInstrInfo * getInstrInfo() const override

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

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.

MachineInstrBundleIterator< const MachineInstr > const_iterator

iterator insertAfter(iterator I, MachineInstr *MI)

Insert MI into the instruction list after I.

Analysis pass which computes a MachineDominatorTree.

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

bool dominates(const MachineInstr *A, const MachineInstr *B) const

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.

void dump() const

dump - Print the current MachineFunction to cerr, useful for debugger use.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

void viewCFG() const

viewCFG - This function is meant for use from the debugger.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

bool mayLoadOrStore(QueryType Type=AnyInBundle) const

Return true if this instruction could possibly read or modify memory.

LLVM_ABI MachineInstr * removeFromParent()

Unlink 'this' from the containing basic block, and return it without deleting it.

const MachineBasicBlock * getParent() const

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

LLVM_ABI void setDesc(const MCInstrDesc &TID)

Replace the instruction descriptor (thus opcode) of the current instruction with a new one.

mop_range explicit_operands()

bool mayStore(QueryType Type=AnyInBundle) const

Return true if this instruction could possibly modify memory.

LLVM_ABI void removeOperand(unsigned OpNo)

Erase an operand from an instruction, leaving it with one fewer operand than it started with.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

static MachineOperand CreateImm(int64_t Val)

Register getReg() const

getReg - Returns the register number.

static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)

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

PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...

static constexpr bool isVirtualRegister(unsigned Reg)

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

void push_back(const T &Elt)

TargetInstrInfo - Interface to description of machine instruction set.

A Use represents the edge between a Value definition and its users.

LLVM_ABI unsigned getOperandNo() const

Return the operand # of this use in its User.

Value * getOperand(unsigned i) const

self_iterator getIterator()

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

#define llvm_unreachable(msg)

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

unsigned ID

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

initializer< Ty > init(const Ty &Val)

BaseReg

Stack frame base register. Bit 0 of FREInfo.Info.

This is an optimization pass for GlobalISel generic memory operations.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

void initializeARCOptAddrModePass(PassRegistry &)

static cl::opt< unsigned > ArcKillAddrMode("arc-kill-addr-mode", cl::init(0), cl::ReallyHidden)

LLVM_ABI raw_ostream & dbgs()

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

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

ArrayRef(const T &OneElt) -> ArrayRef< T >

FunctionPass * createARCOptAddrMode()

Definition ARCOptAddrMode.cpp:530

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.