LLVM: lib/Target/Sparc/DelaySlotFiller.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

24

25using namespace llvm;

26

27#define DEBUG_TYPE "delay-slot-filler"

28

29STATISTIC(FilledSlots, "Number of delay slots filled");

30

32 "disable-sparc-delay-filler",

34 cl::desc("Disable the Sparc delay slot filler."),

36

37namespace {

40

41 static char ID;

43

44 StringRef getPassName() const override { return "SPARC Delay Slot Filler"; }

45

46 bool runOnMachineBasicBlock(MachineBasicBlock &MBB);

47 bool runOnMachineFunction(MachineFunction &F) override {

49 Subtarget = &F.getSubtarget();

50

51

52

53 F.getRegInfo().invalidateLiveness();

54

55 for (MachineBasicBlock &MBB : F)

56 Changed |= runOnMachineBasicBlock(MBB);

58 }

59

60 MachineFunctionProperties getRequiredProperties() const override {

61 return MachineFunctionProperties().setNoVRegs();

62 }

63

65 SmallSet<unsigned, 32>& RegDefs,

66 SmallSet<unsigned, 32>& RegUses);

67

69 SmallSet<unsigned, 32>& RegDefs,

70 SmallSet<unsigned, 32>& RegUses);

71

72 bool IsRegInSet(SmallSet<unsigned, 32>& RegSet,

73 unsigned Reg);

74

76 bool &sawLoad, bool &sawStore,

77 SmallSet<unsigned, 32> &RegDefs,

78 SmallSet<unsigned, 32> &RegUses);

79

82

84

85 bool tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,

87

88 };

89 char Filler::ID = 0;

90}

91

92

93

94

96 return new Filler;

97}

98

99

100

101

102

107

110 ++I;

111

112

114 (MI->getOpcode() == SP::RESTORErr

115 || MI->getOpcode() == SP::RESTOREri)) {

116 Changed |= tryCombineRestoreWithPrevInst(MBB, MI);

117 continue;

118 }

119

120

121

122 if (!Subtarget->isV9() &&

123 (MI->getOpcode() == SP::FCMPS || MI->getOpcode() == SP::FCMPD

124 || MI->getOpcode() == SP::FCMPQ)) {

127 continue;

128 }

129

130

131 if (MI->hasDelaySlot())

132 continue;

133

135

137 D = findDelayInstr(MBB, MI);

138

139 ++FilledSlots;

141

144 else

146

147 unsigned structSize = 0;

148 if (needsUnimp(MI, structSize)) {

150 ++J;

151 assert (J != MBB.end() && "MI needs a delay instruction.");

154

156 } else {

158 }

159 }

161}

162

164Filler::findDelayInstr(MachineBasicBlock &MBB,

166{

167 SmallSet<unsigned, 32> RegDefs;

168 SmallSet<unsigned, 32> RegUses;

169 bool sawLoad = false;

170 bool sawStore = false;

171

174

175 unsigned Opc = slot->getOpcode();

176

177 if (Opc == SP::RET || Opc == SP::TLS_CALL)

179

180 if (Opc == SP::RETL || Opc == SP::TAIL_CALL || Opc == SP::TAIL_CALLri) {

182 --J;

183

184 if (J->getOpcode() == SP::RESTORErr

185 || J->getOpcode() == SP::RESTOREri) {

186

187 if (Opc == SP::RETL)

188 slot->setDesc(Subtarget->getInstrInfo()->get(SP::RET));

189 return J;

190 }

191 }

192

193

194 if (slot->isCall())

195 insertCallDefsUses(slot, RegDefs, RegUses);

196 else

197 insertDefsUses(slot, RegDefs, RegUses);

198

199 bool done = false;

200

202

203 while (!done) {

205

206 if (!done)

207 --I;

208

209

210 if (I->isMetaInstruction())

211 continue;

212

213 if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||

214 I->hasDelaySlot() || I->isBundledWithSucc())

215 break;

216

217 if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {

218 insertDefsUses(I, RegDefs, RegUses);

219 continue;

220 }

221

222 return I;

223 }

225}

226

228 bool &sawLoad,

229 bool &sawStore,

230 SmallSet<unsigned, 32> &RegDefs,

231 SmallSet<unsigned, 32> &RegUses)

232{

233

234 if (candidate->isImplicitDef() || candidate->isKill())

235 return true;

236

237 if (candidate->mayLoad()) {

238 sawLoad = true;

239 if (sawStore)

240 return true;

241 }

242

243 if (candidate->mayStore()) {

244 if (sawStore)

245 return true;

246 sawStore = true;

247 if (sawLoad)

248 return true;

249 }

250

251 for (const MachineOperand &MO : candidate->operands()) {

252 if (!MO.isReg())

253 continue;

254

256

257 if (MO.isDef()) {

258

259 if (IsRegInSet(RegDefs, Reg) || IsRegInSet(RegUses, Reg))

260 return true;

261 }

262 if (MO.isUse()) {

263

264 if (IsRegInSet(RegDefs, Reg))

265 return true;

266 }

267 }

268

269 unsigned Opcode = candidate->getOpcode();

270

271

272 if (Subtarget->insertNOPLoad()

273 &&

274 Opcode >= SP::LDDArr && Opcode <= SP::LDrr)

275 return true;

276

277

278 if (Subtarget->fixAllFDIVSQRT()

279 &&

280 Opcode >= SP::FDIVD && Opcode <= SP::FSQRTD)

281 return true;

282

283 if (Subtarget->fixTN0009() && candidate->mayStore())

284 return true;

285

286 if (Subtarget->fixTN0013()) {

287 switch (Opcode) {

288 case SP::FDIVS:

289 case SP::FDIVD:

290 case SP::FSQRTS:

291 case SP::FSQRTD:

292 return true;

293 default:

294 break;

295 }

296 }

297

298 return false;

299}

300

301

303 SmallSet<unsigned, 32>& RegDefs,

304 SmallSet<unsigned, 32>& RegUses)

305{

306

307 RegDefs.insert(SP::O7);

308

309 switch(MI->getOpcode()) {

311 case SP::CALL:

312 break;

313 case SP::CALLrr:

314 case SP::CALLri:

315 assert(MI->getNumOperands() >= 2);

316 const MachineOperand &Reg = MI->getOperand(0);

317 assert(Reg.isReg() && "CALL first operand is not a register.");

318 assert(Reg.isUse() && "CALL first operand is not a use.");

320

321 const MachineOperand &Operand1 = MI->getOperand(1);

323 break;

324 assert(Operand1.isReg() && "CALLrr second operand is not a register.");

325 assert(Operand1.isUse() && "CALLrr second operand is not a use.");

327 break;

328 }

329}

330

331

333 SmallSet<unsigned, 32>& RegDefs,

334 SmallSet<unsigned, 32>& RegUses)

335{

336 for (const MachineOperand &MO : MI->operands()) {

337 if (!MO.isReg())

338 continue;

339

341 if (Reg == 0)

342 continue;

343 if (MO.isDef())

345 if (MO.isUse()) {

346

347

348 if (MO.isImplicit() && MI->getOpcode() == SP::RETL)

349 continue;

351 }

352 }

353}

354

355

356bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg)

357{

358

360 AI.isValid(); ++AI)

361 if (RegSet.count(*AI))

362 return true;

363 return false;

364}

365

367{

368 if (I->isCall())

369 return false;

370

371 unsigned structSizeOpNum = 0;

372 switch (I->getOpcode()) {

374 case SP::CALL:

375 structSizeOpNum = 1;

376 break;

377 case SP::CALLrr:

378 case SP::CALLri:

379 structSizeOpNum = 2;

380 break;

381 case SP::TLS_CALL: return false;

382 case SP::TAIL_CALLri:

383 case SP::TAIL_CALL: return false;

384 }

385

386 const MachineOperand &MO = I->getOperand(structSizeOpNum);

388 return false;

389 StructSize = MO.getImm();

390 return true;

391}

392

396{

397

398

399

400

401

402 Register reg = AddMI->getOperand(0).getReg();

403 if (reg < SP::I0 || reg > SP::I7)

404 return false;

405

406

407 RestoreMI->eraseFromParent();

408

409

410 AddMI->setDesc(TII->get((AddMI->getOpcode() == SP::ADDrr)

411 ? SP::RESTORErr

412 : SP::RESTOREri));

413

414

415 AddMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);

416

417 return true;

418}

419

423{

424

425

426

427

428

429

430 Register reg = OrMI->getOperand(0).getReg();

431 if (reg < SP::I0 || reg > SP::I7)

432 return false;

433

434

435 if (OrMI->getOpcode() == SP::ORrr

436 && OrMI->getOperand(1).getReg() != SP::G0

437 && OrMI->getOperand(2).getReg() != SP::G0)

438 return false;

439

440 if (OrMI->getOpcode() == SP::ORri

441 && OrMI->getOperand(1).getReg() != SP::G0

442 && (!OrMI->getOperand(2).isImm() || OrMI->getOperand(2).getImm() != 0))

443 return false;

444

445

446 RestoreMI->eraseFromParent();

447

448

449 OrMI->setDesc(TII->get((OrMI->getOpcode() == SP::ORrr)

450 ? SP::RESTORErr

451 : SP::RESTOREri));

452

453

454 OrMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);

455

456 return true;

457}

458

462{

463

464

465

466

467

468 Register reg = SetHiMI->getOperand(0).getReg();

469 if (reg < SP::I0 || reg > SP::I7)

470 return false;

471

472 if (!SetHiMI->getOperand(1).isImm())

473 return false;

474

475 int64_t imm = SetHiMI->getOperand(1).getImm();

476

477

479 return false;

480

481

482 imm = (imm << 10) & 0x1FFF;

483

484 assert(RestoreMI->getOpcode() == SP::RESTORErr);

485

486 RestoreMI->setDesc(TII->get(SP::RESTOREri));

487

488 RestoreMI->getOperand(0).setReg(reg - SP::I0 + SP::O0);

489 RestoreMI->getOperand(1).setReg(SP::G0);

490 RestoreMI->getOperand(2).ChangeToImmediate(imm);

491

492

493

494 SetHiMI->eraseFromParent();

495

496 return true;

497}

498

499bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,

501{

502

504 return false;

505

506

507 assert(MBBI->getOpcode() == SP::RESTORErr

508 && MBBI->getOperand(0).getReg() == SP::G0

509 && MBBI->getOperand(1).getReg() == SP::G0

510 && MBBI->getOperand(2).getReg() == SP::G0);

511

513

514

515 if (PrevInst->isBundledWithSucc())

516 return false;

517

519

520 switch (PrevInst->getOpcode()) {

521 default: break;

522 case SP::ADDrr:

524 case SP::ORrr:

527 }

528

529 return false;

530}

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

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator MBBI

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static bool combineRestoreSETHIi(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator SetHiMI, const TargetInstrInfo *TII)

Definition DelaySlotFiller.cpp:459

static bool combineRestoreOR(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator OrMI, const TargetInstrInfo *TII)

Definition DelaySlotFiller.cpp:420

static cl::opt< bool > DisableDelaySlotFiller("disable-sparc-delay-filler", cl::init(false), cl::desc("Disable the Sparc delay slot filler."), cl::Hidden)

static bool combineRestoreADD(MachineBasicBlock::iterator RestoreMI, MachineBasicBlock::iterator AddMI, const TargetInstrInfo *TII)

Definition DelaySlotFiller.cpp:393

Promote Memory to Register

static cl::opt< bool > DisableDelaySlotFiller("disable-mips-delay-filler", cl::init(false), cl::desc("Fill all delay slots with NOPs."), cl::Hidden)

This file defines the SmallSet class.

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

#define STATISTIC(VARNAME, DESC)

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.

void splice(iterator Where, MachineBasicBlock *Other, iterator From)

Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...

MachineInstrBundleIterator< MachineInstr > iterator

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

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate 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.

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

Register getReg() const

getReg - Returns the register number.

Wrapper class representing virtual and physical registers.

size_type count(const T &V) const

count - Return 1 if the element is in the set, 0 otherwise.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

const SparcRegisterInfo * getRegisterInfo() const override

const SparcInstrInfo * getInstrInfo() const override

TargetInstrInfo - Interface to description of machine instruction set.

#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)

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.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

FunctionPass * createSparcDelaySlotFillerPass()

createSparcDelaySlotFillerPass - Returns a pass that fills in delay slots in Sparc MachineFunctions

Definition DelaySlotFiller.cpp:95