LLVM: lib/Target/Hexagon/HexagonGenPredicate.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

29#include

30#include

31#include

32#include

33#include

34#include

35

36#define DEBUG_TYPE "gen-pred"

37

38using namespace llvm;

39

40namespace llvm {

41

44

45}

46

47namespace {

48

49

50 struct RegisterSubReg {

52 unsigned S;

53

54 RegisterSubReg(unsigned r = 0, unsigned s = 0) : R(r), S(s) {}

56 RegisterSubReg(const Register &Reg) : R(Reg), S(0) {}

57

58 bool operator== (const RegisterSubReg &Reg) const {

59 return R == Reg.R && S == Reg.S;

60 }

61

62 bool operator< (const RegisterSubReg &Reg) const {

63 return R < Reg.R || (R == Reg.R && S < Reg.S);

64 }

65 };

66

67 struct PrintRegister {

69

71

72 private:

73 RegisterSubReg Reg;

75 };

76

80 return OS << printReg(PR.Reg.R, &PR.TRI, PR.Reg.S);

81 }

82

84 public:

85 static char ID;

86

89 }

90

92 return "Hexagon generate predicate operations";

93 }

94

99 }

100

102

103 private:

105 using SetOfReg = std::set;

106 using RegToRegMap = std::map<RegisterSubReg, RegisterSubReg>;

107

111 SetOfReg PredGPRs;

112 VectOfInst PUsers;

113 RegToRegMap G2P;

114

117 void processPredicateGPR(const RegisterSubReg &Reg);

118 unsigned getPredForm(unsigned Opc);

119 bool isConvertibleToPredForm(const MachineInstr *MI);

120 bool isScalarCmp(unsigned Opc);

121 bool isScalarPred(RegisterSubReg PredReg);

122 RegisterSubReg getPredRegFor(const RegisterSubReg &Reg);

125 };

126

127}

128

129char HexagonGenPredicate::ID = 0;

130

132 "Hexagon generate predicate operations", false, false)

136

137bool HexagonGenPredicate::isPredReg(Register R) {

138 if (!R.isVirtual())

139 return false;

141 return RC == &Hexagon::PredRegsRegClass;

142}

143

144unsigned HexagonGenPredicate::getPredForm(unsigned Opc) {

145 using namespace Hexagon;

146

147 switch (Opc) {

148 case A2_and:

149 case A2_andp:

150 return C2_and;

151 case A4_andn:

152 case A4_andnp:

153 return C2_andn;

154 case M4_and_and:

155 return C4_and_and;

156 case M4_and_andn:

157 return C4_and_andn;

158 case M4_and_or:

159 return C4_and_or;

160

161 case A2_or:

162 case A2_orp:

163 return C2_or;

164 case A4_orn:

165 case A4_ornp:

166 return C2_orn;

167 case M4_or_and:

168 return C4_or_and;

169 case M4_or_andn:

170 return C4_or_andn;

171 case M4_or_or:

172 return C4_or_or;

173

174 case A2_xor:

175 case A2_xorp:

176 return C2_xor;

177

178 case C2_tfrrp:

179 return COPY;

180 }

181

182

183

184 static_assert(PHI == 0, "Use different value for ");

185 return 0;

186}

187

188bool HexagonGenPredicate::isConvertibleToPredForm(const MachineInstr *MI) {

189 unsigned Opc = MI->getOpcode();

190 if (getPredForm(Opc) != 0)

191 return true;

192

193

194

195

196

197 switch (Opc) {

198 case Hexagon::C2_cmpeqi:

199 case Hexagon::C4_cmpneqi:

200 if (MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0)

201 return true;

202 break;

203 }

204 return false;

205}

206

207void HexagonGenPredicate::collectPredicateGPR(MachineFunction &MF) {

210 unsigned Opc = MI.getOpcode();

211 switch (Opc) {

212 case Hexagon::C2_tfrpr:

213 case TargetOpcode::COPY:

214 if (isPredReg(MI.getOperand(1).getReg())) {

215 RegisterSubReg RD = MI.getOperand(0);

216 if (RD.R.isVirtual())

217 PredGPRs.insert(RD);

218 }

219 break;

220 }

221 }

222 }

223}

224

225void HexagonGenPredicate::processPredicateGPR(const RegisterSubReg &Reg) {

228

229 use_iterator I = MRI->use_begin(Reg.R), E = MRI->use_end();

230 if (I == E) {

234 return;

235 }

236

237 for (; I != E; ++I) {

239 if (isConvertibleToPredForm(UseI))

240 PUsers.insert(UseI);

241 }

242}

243

244RegisterSubReg HexagonGenPredicate::getPredRegFor(const RegisterSubReg &Reg) {

245

246

247

249 RegToRegMap::iterator F = G2P.find(Reg);

250 if (F != G2P.end())

251 return F->second;

252

253 LLVM_DEBUG(dbgs() << __func__ << ": " << PrintRegister(Reg, *TRI));

256 unsigned Opc = DefI->getOpcode();

257 if (Opc == Hexagon::C2_tfrpr || Opc == TargetOpcode::COPY) {

259 RegisterSubReg PR = DefI->getOperand(1);

260 G2P.insert(std::make_pair(Reg, PR));

262 return PR;

263 }

264

268 Register NewPR = MRI->createVirtualRegister(PredRC);

269

270

271

272 if (isConvertibleToPredForm(DefI)) {

274 BuildMI(B, std::next(DefIt), DL, TII->get(TargetOpcode::COPY), NewPR)

276 G2P.insert(std::make_pair(Reg, RegisterSubReg(NewPR)));

277 LLVM_DEBUG(dbgs() << " -> !" << PrintRegister(RegisterSubReg(NewPR), *TRI)

278 << '\n');

279 return RegisterSubReg(NewPR);

280 }

281

283}

284

285bool HexagonGenPredicate::isScalarCmp(unsigned Opc) {

286 switch (Opc) {

287 case Hexagon::C2_cmpeq:

288 case Hexagon::C2_cmpgt:

289 case Hexagon::C2_cmpgtu:

290 case Hexagon::C2_cmpeqp:

291 case Hexagon::C2_cmpgtp:

292 case Hexagon::C2_cmpgtup:

293 case Hexagon::C2_cmpeqi:

294 case Hexagon::C2_cmpgti:

295 case Hexagon::C2_cmpgtui:

296 case Hexagon::C2_cmpgei:

297 case Hexagon::C2_cmpgeui:

298 case Hexagon::C4_cmpneqi:

299 case Hexagon::C4_cmpltei:

300 case Hexagon::C4_cmplteui:

301 case Hexagon::C4_cmpneq:

302 case Hexagon::C4_cmplte:

303 case Hexagon::C4_cmplteu:

304 case Hexagon::A4_cmpbeq:

305 case Hexagon::A4_cmpbeqi:

306 case Hexagon::A4_cmpbgtu:

307 case Hexagon::A4_cmpbgtui:

308 case Hexagon::A4_cmpbgt:

309 case Hexagon::A4_cmpbgti:

310 case Hexagon::A4_cmpheq:

311 case Hexagon::A4_cmphgt:

312 case Hexagon::A4_cmphgtu:

313 case Hexagon::A4_cmpheqi:

314 case Hexagon::A4_cmphgti:

315 case Hexagon::A4_cmphgtui:

316 return true;

317 }

318 return false;

319}

320

321bool HexagonGenPredicate::isScalarPred(RegisterSubReg PredReg) {

322 std::queue WorkQ;

323 WorkQ.push(PredReg);

324

325 while (!WorkQ.empty()) {

326 RegisterSubReg PR = WorkQ.front();

327 WorkQ.pop();

329 if (!DefI)

330 return false;

331 unsigned DefOpc = DefI->getOpcode();

332 switch (DefOpc) {

333 case TargetOpcode::COPY: {

335 if (MRI->getRegClass(PR.R) != PredRC)

336 return false;

337

338 [[fallthrough]];

339 }

340 case Hexagon::C2_and:

341 case Hexagon::C2_andn:

342 case Hexagon::C4_and_and:

343 case Hexagon::C4_and_andn:

344 case Hexagon::C4_and_or:

345 case Hexagon::C2_or:

346 case Hexagon::C2_orn:

347 case Hexagon::C4_or_and:

348 case Hexagon::C4_or_andn:

349 case Hexagon::C4_or_or:

350 case Hexagon::C4_or_orn:

351 case Hexagon::C2_xor:

352

354 if (MO.isReg() && MO.isUse())

355 WorkQ.push(RegisterSubReg(MO.getReg()));

356 break;

357

358

359 default:

360 return isScalarCmp(DefOpc);

361 }

362 }

363

364 return true;

365}

366

367bool HexagonGenPredicate::convertToPredForm(MachineInstr *MI) {

369

370 unsigned Opc = MI->getOpcode();

371 assert(isConvertibleToPredForm(MI));

372 unsigned NumOps = MI->getNumOperands();

373 for (unsigned i = 0; i < NumOps; ++i) {

376 continue;

377 RegisterSubReg Reg(MO);

378 if (Reg.S && Reg.S != Hexagon::isub_lo)

379 return false;

380 if (!PredGPRs.count(Reg))

381 return false;

382 }

383

386

387 unsigned NewOpc = getPredForm(Opc);

388

389 if (NewOpc == 0) {

390 switch (Opc) {

391 case Hexagon::C2_cmpeqi:

392 NewOpc = Hexagon::C2_not;

393 break;

394 case Hexagon::C4_cmpneqi:

395 NewOpc = TargetOpcode::COPY;

396 break;

397 default:

398 return false;

399 }

400

401

402

403

404 RegisterSubReg PR = getPredRegFor(MI->getOperand(1));

405 if (!isScalarPred(PR))

406 return false;

407

408

409 NumOps = 2;

410 }

411

412

415 RegisterSubReg OutR(Op0);

416

417

418

419

421 RegisterSubReg NewPR = MRI->createVirtualRegister(PredRC);

423

424

425 for (unsigned i = 1; i < NumOps; ++i) {

426 RegisterSubReg GPR = MI->getOperand(i);

427 RegisterSubReg Pred = getPredRegFor(GPR);

428 MIB.addReg(Pred.R, 0, Pred.S);

429 }

431

432

433

435 Register NewOutR = MRI->createVirtualRegister(RC);

436 BuildMI(B, MI, DL, TII->get(TargetOpcode::COPY), NewOutR)

437 .addReg(NewPR.R, 0, NewPR.S);

438 MRI->replaceRegWith(OutR.R, NewOutR);

439 MI->eraseFromParent();

440

441

442

443

445 RegisterSubReg R(NewOutR);

446 PredGPRs.insert(R);

447 processPredicateGPR(R);

448 }

449 return true;

450}

451

452bool HexagonGenPredicate::eliminatePredCopies(MachineFunction &MF) {

455 bool Changed = false;

456 VectOfInst Erase;

457

458

459

460

461

462

463

464

465

466

467

470 if (MI.getOpcode() != TargetOpcode::COPY)

471 continue;

472 RegisterSubReg DR = MI.getOperand(0);

473 RegisterSubReg SR = MI.getOperand(1);

474 if (!DR.R.isVirtual())

475 continue;

476 if (!SR.R.isVirtual())

477 continue;

478 if (MRI->getRegClass(DR.R) != PredRC)

479 continue;

480 if (MRI->getRegClass(SR.R) != PredRC)

481 continue;

482 assert(!DR.S && !SR.S && "Unexpected subregister");

483 MRI->replaceRegWith(DR.R, SR.R);

484 Erase.insert(&MI);

485 Changed = true;

486 }

487 }

488

490 MI->eraseFromParent();

491

492 return Changed;

493}

494

495bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {

497 return false;

498

502 PredGPRs.clear();

503 PUsers.clear();

504 G2P.clear();

505

506 bool Changed = false;

507 collectPredicateGPR(MF);

508 for (const RegisterSubReg &R : PredGPRs)

509 processPredicateGPR(R);

510

511 bool Again;

512 do {

513 Again = false;

514 VectOfInst Processed, Copy;

515

516 Copy = PUsers;

518 bool Done = convertToPredForm(MI);

520 Processed.insert(MI);

521 Again = true;

522 }

523 }

524 Changed |= Again;

525

527 return Processed.count(MI);

528 };

529 PUsers.remove_if(Done);

530 } while (Again);

531

532 Changed |= eliminatePredCopies(MF);

533 return Changed;

534}

535

537 return new HexagonGenPredicate();

538}

unsigned const MachineRegisterInfo * MRI

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

#define LLVM_ATTRIBUTE_UNUSED

const HexagonInstrInfo * TII

hexagon gen Hexagon generate predicate operations

unsigned const TargetRegisterInfo * TRI

static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file implements a set that has insertion order iteration characteristics.

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.

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

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.

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

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 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.

const MachineBasicBlock * getParent() const

iterator_range< mop_iterator > operands()

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

void eraseFromParent()

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

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.

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

defusechain_iterator< true, false, false, true, false, false > use_iterator

use_iterator/use_begin/use_end - Walk all uses of the specified register.

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

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

Wrapper class representing virtual and physical registers.

A global registry used in conjunction with static constructors to make pluggable components (like tar...

A vector that has set insertion semantics.

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

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

This class implements an extremely fast bulk output stream that can only output to a stream.

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

bool isPredReg(MCRegisterInfo const &MRI, MCRegister Reg)

Reg

All possible values of the reg field in the ModR/M byte.

This is an optimization pass for GlobalISel generic memory operations.

bool operator<(int64_t V1, const APSInt &V2)

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

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

void initializeHexagonGenPredicatePass(PassRegistry &Registry)

raw_ostream & dbgs()

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

FunctionPass * createHexagonGenPredicate()

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.