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

1

2

3

4

5

6

7

8

9

10

11

12

13

19

28#include

29

30using namespace llvm;

31

34 cl::desc("Relax checks of new-value validity"));

35

36const HexagonMCChecker::PredSense

37 HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);

38

39void HexagonMCChecker::init() {

40

41 ReadOnly.insert(Hexagon::PC);

42 ReadOnly.insert(Hexagon::C9_8);

43

44

46 Defs[Hexagon::SA0].insert(Unconditional);

47 Defs[Hexagon::LC0].insert(Unconditional);

48 }

50 Defs[Hexagon::SA1].insert(Unconditional);

51 Defs[Hexagon::LC1].insert(Unconditional);

52 }

53

55

57 MCInst const &Inst = *I.getInst();

61 } else

62 init(Inst);

63 }

64 else

65 init(MCB);

66}

67

68void HexagonMCChecker::initReg(MCInst const &MCI, MCRegister R,

72

73 PredReg = R;

75

76

78 NewPreds.insert(PredReg);

79 } else

80

81

82 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();

83 ++SRI)

84 if (RI.subregs(*SRI).empty())

85

86 Uses.insert(*SRI);

87

89 ReversePairs.insert(R);

90}

91

92void HexagonMCChecker::init(MCInst const &MCI) {

94 MCRegister PredReg;

95 bool isTrue = false;

96

97

102 initReg(MCI, ImpUse, PredReg, isTrue);

103

106 STI.hasFeature(Hexagon::ArchV69);

107

108

110 if (Hexagon::R31 != R && MCID.isCall())

111

112

113 continue;

114 if (Hexagon::PC == R)

115

116

117 continue;

118

119 if (Hexagon::USR_OVF == R)

120

121

122

123

124

125 SoftDefs.insert(R);

128

129 LatePreds.insert(R);

130 else if (!IgnoreTmpDst)

131 Defs[R].insert(PredSense(PredReg, isTrue));

132 }

133

134

135 for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {

137

138

139

140 if (R == Hexagon::C8)

141 R = Hexagon::USR;

142

144 ReversePairs.insert(R);

145

146

147

148 for (MCRegAliasIterator SRI(R, &RI, RI.subregs(R).empty()); SRI.isValid();

149 ++SRI) {

150 if (!RI.subregs(*SRI).empty())

151

152 continue;

153

154 if (R == *SRI) {

155 if (S == R)

156

157 continue;

158 else

159

160 S = R;

161 }

162

163 if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI)

164

165

166

167

168 SoftDefs.insert(*SRI);

171

172 LatePreds.insert(*SRI);

175

176

177

178

179

180 TmpDefs.insert(*SRI);

181 else if (!IgnoreTmpDst)

182 Defs[*SRI].insert(PredSense(PredReg, isTrue));

183 }

184 }

185

186

191

193 NewPreds.insert(P);

194 }

195}

196

200 : Context(Context), MCB(mcb), RI(ri), MCII(MCII), STI(STI),

201 ReportErrors(ReportErrors) {

202 init();

203}

204

207 bool CopyReportErrors)

209 STI(STI), ReportErrors(CopyReportErrors ? Other.ReportErrors : false) {

210 init();

211}

212

214 bool chkP = checkPredicates();

215 bool chkNV = checkNewValues();

216 bool chkR = checkRegisters();

217 bool chkRRO = checkRegistersReadOnly();

218 checkRegisterCurDefs();

219 bool chkS = checkSolo();

220 bool chkSh = true;

221 if (FullCheck)

222 chkSh = checkShuffle();

223 bool chkSl = true;

224 if (FullCheck)

225 chkSl = checkSlots();

226 bool chkAXOK = checkAXOK();

227 bool chkCofMax1 = checkCOFMax1();

228 bool chkHWLoop = checkHWLoop();

229 bool chkValidTmpDst = FullCheck ? checkValidTmpDst() : true;

230 bool chkLegalVecRegPair = checkLegalVecRegPair();

231 bool ChkHVXAccum = checkHVXAccum();

232 bool chk = chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl &&

233 chkAXOK && chkCofMax1 && chkHWLoop && chkValidTmpDst &&

234 chkLegalVecRegPair && ChkHVXAccum;

235

236 return chk;

237}

238

240 switch (Opcode) {

241 case Hexagon::SA1_addi:

242 case Hexagon::SA1_addrx:

243 case Hexagon::SA1_addsp:

244 case Hexagon::SA1_and1:

245 case Hexagon::SA1_clrf:

246 case Hexagon::SA1_clrfnew:

247 case Hexagon::SA1_clrt:

248 case Hexagon::SA1_clrtnew:

249 case Hexagon::SA1_cmpeqi:

250 case Hexagon::SA1_combine0i:

251 case Hexagon::SA1_combine1i:

252 case Hexagon::SA1_combine2i:

253 case Hexagon::SA1_combine3i:

254 case Hexagon::SA1_combinerz:

255 case Hexagon::SA1_combinezr:

256 case Hexagon::SA1_dec:

257 case Hexagon::SA1_inc:

258 case Hexagon::SA1_seti:

259 case Hexagon::SA1_setin1:

260 case Hexagon::SA1_sxtb:

261 case Hexagon::SA1_sxth:

262 case Hexagon::SA1_tfr:

263 case Hexagon::SA1_zxtb:

264 case Hexagon::SA1_zxth:

265 return true;

266 break;

267 default:

268 return false;

269 }

270}

271

274 return true;

276 switch (Type) {

285 return false;

288 }

291 default:

292 return true;

293 }

294}

295

296bool HexagonMCChecker::checkAXOK() {

297 MCInst const *HasSoloAXInst = nullptr;

300 HasSoloAXInst = &I;

301 }

302 }

303 if (!HasSoloAXInst)

304 return true;

308 HasSoloAXInst->getLoc(),

309 Twine("Instruction can only be in a packet with ALU or non-FPU XTYPE "

310 "instructions"));

312 Twine("Not an ALU or non-FPU XTYPE instruction"));

313 return false;

314 }

315 }

316 return true;

317}

318

322 reportNote(I.getLoc(), "Branching instruction");

323 }

324}

325

326bool HexagonMCChecker::checkHWLoop() {

329 return true;

333 "Branches cannot be in a packet with hardware loops");

335 return false;

336 }

337 }

338 return true;

339}

340

341bool HexagonMCChecker::checkCOFMax1() {

346 }

347 for (unsigned J = 0, N = BranchLocations.size(); J < N; ++J) {

348 MCInst const &I = *BranchLocations[J];

352 if (N > 1 && !Relax1 && !Relax2) {

354 "Instruction may not be in a packet with other branches");

356 return false;

357 }

358 if (N > 1 && J == 0 && !Relax1) {

360 "Instruction may not be the first branch in packet");

362 return false;

363 }

364 if (N > 1 && J == 1 && !Relax2) {

366 "Instruction may not be the second branch in packet");

368 return false;

369 }

370 }

371 }

372 return true;

373}

374

375bool HexagonMCChecker::checkSlots() {

378 reportError("invalid instruction packet: out of slots");

379 return false;

380 }

381 return true;

382}

383

384

385bool HexagonMCChecker::checkPredicates() {

386

387 for (const auto &I : NewPreds) {

388 MCRegister P = I;

389

390 if (!Defs.count(P) || LatePreds.count(P) || Defs.count(Hexagon::P3_0)) {

391

392

393

395 return false;

396 }

397 }

398

399

400 for (const auto &I : LatePreds) {

401 MCRegister P = I;

402

403 if (LatePreds.count(P) > 1 || Defs.count(P)) {

404

405

406

408 return false;

409 }

410 }

411

412 return true;

413}

414

415

416bool HexagonMCChecker::checkNewValues() {

417 for (auto const &ConsumerInst :

420 continue;

421

422 const HexagonMCInstrInfo::PredicateInfo ConsumerPredInfo =

424

426 MCOperand const &Op =

429

430 auto Producer = registerProducer(Op.getReg(), ConsumerPredInfo);

431 const MCInst *const ProducerInst = std::get<0>(Producer);

432 const HexagonMCInstrInfo::PredicateInfo ProducerPredInfo =

433 std::get<2>(Producer);

434

435 if (ProducerInst == nullptr) {

437 "New value register consumer has no producer");

438 return false;

439 }

441

447 ProducerInst->getLoc(),

448 "Register producer is predicated and consumer is unconditional");

450 "Instruction does not have a valid new register producer");

451 return false;

452 }

453 if (ProducerPredInfo.Register != Hexagon::NoRegister &&

456 "Register producer does not use the same predicate "

457 "register as the consumer");

459 "Instruction does not have a valid new register producer");

460 return false;

461 }

462 }

463 if (ProducerPredInfo.Register == ConsumerPredInfo.Register &&

466 ProducerInst->getLoc(),

467 "Register producer has the opposite predicate sense as consumer");

469 "Instruction does not have a valid new register producer");

470 return false;

471 }

472

474 const unsigned ProducerOpIndex = std::get<1>(Producer);

475

476 if (Desc.operands()[ProducerOpIndex].RegClass ==

477 Hexagon::DoubleRegsRegClassID) {

479 "Double registers cannot be new-value producers");

481 "Instruction does not have a valid new register producer");

482 return false;

483 }

484

485

486

487

488

489 const unsigned ProducerOpSearchIndex =

492 ? 0

493 : 1;

494

495 const bool ProducerOpIsMemIndex =

496 ((Desc.mayLoad() && ProducerOpIndex == ProducerOpSearchIndex) ||

497 (Desc.mayStore() && ProducerOpIndex == 0));

498

499 if (ProducerOpIsMemIndex) {

501

502 StringRef ModeError;

504 ModeError = "Absolute-set";

506 ModeError = "Auto-increment";

507 if (!ModeError.empty()) {

509 ModeError + " registers cannot be a new-value "

510 "producer");

512 "Instruction does not have a valid new register producer");

513 return false;

514 }

515 }

518 "FPU instructions cannot be new-value producers for jumps");

520 "Instruction does not have a valid new register producer");

521 return false;

522 }

523 }

524 return true;

525}

526

527bool HexagonMCChecker::checkRegistersReadOnly() {

529 MCInst const &Inst = *I.getInst();

531 for (unsigned j = 0; j < Defs; ++j) {

532 MCOperand const &Operand = Inst.getOperand(j);

533 assert(Operand.isReg() && "Def is not a register");

535 if (ReadOnly.find(Register) != ReadOnly.end()) {

536 reportError(Inst.getLoc(), "Cannot write to read-only register `" +

537 Twine(RI.getName(Register)) + "'");

538 return false;

539 }

540 }

541 }

542 return true;

543}

544

549 j < n; ++j) {

550 MCOperand const &Operand = I.getOperand(j);

552 return true;

553 }

554 return false;

555}

556

557std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>

558HexagonMCChecker::registerProducer(

560 std::tuple<MCInst const *, unsigned, HexagonMCInstrInfo::PredicateInfo>

561 WrongSense;

562

566

567 for (unsigned J = 0, N = Desc.getNumDefs(); J < N; ++J)

568 for (auto K = MCRegAliasIterator(I.getOperand(J).getReg(), &RI, true);

569 K.isValid(); ++K)

572 (ProducerPredicate.Register == ConsumerPredicate.Register &&

573 (ProducerPredicate.Register == Hexagon::NoRegister ||

574 ProducerPredicate.PredicatedTrue ==

576 return std::make_tuple(&I, J, ProducerPredicate);

577 std::get<0>(WrongSense) = &I;

578 std::get<1>(WrongSense) = J;

579 std::get<2>(WrongSense) = ProducerPredicate;

580 }

582 return std::make_tuple(&I, 0, HexagonMCInstrInfo::PredicateInfo());

583 }

584 return WrongSense;

585}

586

587void HexagonMCChecker::checkRegisterCurDefs() {

591 const MCRegister RegDef = I.getOperand(0).getReg();

592

593 bool HasRegDefUse = false;

594 for (MCRegAliasIterator Alias(RegDef, &RI, true); Alias.isValid();

595 ++Alias)

596 HasRegDefUse = HasRegDefUse || registerUsed(*Alias);

597

598 if (!HasRegDefUse)

599 reportWarning("Register `" + Twine(RI.getName(RegDef)) +

600 "' used with `.cur' "

601 "but not used in the same packet");

602 }

603 }

604}

605

606

607bool HexagonMCChecker::checkRegisters() {

608

609 for (const auto &I : Defs) {

610 MCRegister R = I.first;

611

612 if (isLoopRegister(R) && Defs.count(R) > 1 &&

615

616 reportError("loop-setup and some branch instructions "

617 "cannot be in the same packet");

618 return false;

619 }

620 if (SoftDefs.count(R)) {

621

622

623 MCRegister UsrR = Hexagon::USR;

624 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;

626 return false;

627 }

629

630 PredSet &PM = Defs[R];

631

632

633 if (PM.count(Unconditional)) {

634

635

636 MCRegister UsrR = Hexagon::USR;

637 MCRegister BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;

639 return false;

640 }

641

642 for (const auto &J : PM) {

643 PredSense P = J;

644

645

646 if (PM.count(P) > 1) {

647

648

650 return false;

651 }

652

653 P.second = P.second;

654 if (PM.count(P) && PM.size() > 2) {

655

656

657

659 return false;

660 }

661 }

662 }

663 }

664

665

666 for (const auto &I : TmpDefs) {

667 MCRegister R = I;

668

669 if (!Uses.count(R)) {

670

671 bool vHistFound = false;

675 vHistFound = true;

676 break;

677 }

678 }

679

680 if (!vHistFound) {

681 reportWarning("register `" + Twine(RI.getName(R)) +

682 "' used with `.tmp' but not used in the same packet");

683 return true;

684 }

685 }

686 }

687

688 return true;

689}

690

691

692bool HexagonMCChecker::checkSolo() {

696 reportError(I.getLoc(), "Instruction is marked `isSolo' and "

697 "cannot have other instructions in "

698 "the same packet");

699 return false;

700 }

701 }

702

703 return true;

704}

705

706bool HexagonMCChecker::checkShuffle() {

707 HexagonMCShuffler MCSDX(Context, ReportErrors, MCII, STI, MCB);

708 return MCSDX.check();

709}

710

711bool HexagonMCChecker::checkValidTmpDst() {

712 if (!STI.hasFeature(Hexagon::ArchV69)) {

713 return true;

714 }

715 auto HasTmp = [&](MCInst const &I) {

718 };

719 unsigned HasTmpCount =

721

722 if (HasTmpCount > 1) {

724 MCB.getLoc(),

725 "this packet has more than one HVX vtmp/.tmp destination instruction");

726

728 if (HasTmp(I))

730 "this is an HVX vtmp/.tmp destination instruction");

731

732 return false;

733 }

734 return true;

735}

736

737void HexagonMCChecker::compoundRegisterMap(unsigned &Register) {

739 default:

740 break;

741 case Hexagon::R15:

743 break;

744 case Hexagon::R14:

746 break;

747 case Hexagon::R13:

749 break;

750 case Hexagon::R12:

752 break;

753 case Hexagon::R11:

755 break;

756 case Hexagon::R10:

758 break;

759 case Hexagon::R9:

761 break;

762 case Hexagon::R8:

764 break;

765 }

766}

767

770 "' modified more than once");

771}

772

775 "' used with `.new' "

776 "but not validly modified in the same packet");

777}

778

782

784 if (ReportErrors)

785 Context.reportError(Loc, Msg);

786}

787

789 if (ReportErrors) {

790 auto SM = Context.getSourceManager();

791 if (SM)

793 }

794}

795

797 if (ReportErrors)

798 Context.reportWarning(MCB.getLoc(), Msg);

799}

800

801bool HexagonMCChecker::checkLegalVecRegPair() {

802 const bool IsPermitted = STI.hasFeature(Hexagon::ArchV67);

803 const bool HasReversePairs = ReversePairs.size() != 0;

804

805 if (!IsPermitted && HasReversePairs) {

806 for (auto R : ReversePairs)

808 "' is not permitted for this architecture");

809 return false;

810 }

811 return true;

812}

813

814

815bool HexagonMCChecker::checkHVXAccum()

816{

818 bool IsTarget =

820 if (!IsTarget)

821 continue;

822 MCRegister R = I.getOperand(0).getReg();

823 TmpDefsIterator It = TmpDefs.find(R);

824 if (It != TmpDefs.end()) {

825 reportError("register `" + Twine(RI.getName(R)) + ".tmp" +

826 "' is accumulated in this packet");

827 return false;

828 }

829 }

830 return true;

831}

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

static cl::opt< bool > RelaxNVChecks("relax-nv-checks", cl::Hidden, cl::desc("Relax checks of new-value validity"))

static bool isDuplexAGroup(unsigned Opcode)

Definition HexagonMCChecker.cpp:239

static bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID)

Definition HexagonMCChecker.cpp:272

Promote Memory to Register

static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))

void reportErrorNewValue(MCRegister Register)

Definition HexagonMCChecker.cpp:773

HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &mcb, const MCRegisterInfo &ri, bool ReportErrors=true)

Definition HexagonMCChecker.cpp:197

bool check(bool FullCheck=true)

Definition HexagonMCChecker.cpp:213

void reportWarning(Twine const &Msg)

Definition HexagonMCChecker.cpp:796

void reportNote(SMLoc Loc, Twine const &Msg)

Definition HexagonMCChecker.cpp:788

void reportErrorRegisters(MCRegister Register)

Definition HexagonMCChecker.cpp:768

void reportBranchErrors()

Definition HexagonMCChecker.cpp:319

void reportError(SMLoc Loc, Twine const &Msg)

Definition HexagonMCChecker.cpp:783

bool isPredicated() const

Context object for machine code objects.

Instances of this class represent a single low-level machine instruction.

const MCOperand & getOperand(unsigned i) const

unsigned getNumOperands() const

Return the number of declared MachineOperands for this MachineInstruction.

unsigned getNumDefs() const

Return the number of MachineOperands that are register definitions.

bool isBranch() const

Returns true if this is a conditional, unconditional, or indirect branch.

ArrayRef< MCPhysReg > implicit_defs() const

Return a list of registers that are potentially written by any instance of this machine instruction.

bool isCall() const

Return true if the instruction is a call.

ArrayRef< MCPhysReg > implicit_uses() const

Return a list of registers that are potentially read by any instance of this machine instruction.

Interface to description of machine instruction set.

MCRegister getReg() const

Returns the register number.

const MCInst * getInst() const

MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...

const char * getName(MCRegister RegNo) const

Return the human-readable symbolic target-specific name for the specified physical register.

Wrapper class representing physical registers. Should be passed by value.

Generic base class for all target subtargets.

bool hasFeature(unsigned Feature) const

Wrapper class representing virtual and physical registers.

Represents a location in source code.

void push_back(const T &Elt)

constexpr bool empty() const

empty - Check if the string is empty.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

The instances of the Type class are immutable: once they are created, they are never changed.

#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 hasHvxTmp(MCInstrInfo const &MCII, MCInst const &MCI)

bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI)

Return whether the insn is solo, i.e., cannot be in a packet.

bool isPredicatedNew(MCInstrInfo const &MCII, MCInst const &MCI)

Return whether the insn is newly predicated.

bool IsReverseVecRegPair(MCRegister VecReg)

bool isOuterLoop(MCInst const &MCI)

unsigned getAddrMode(MCInstrInfo const &MCII, MCInst const &MCI)

size_t bundleSize(MCInst const &MCI)

bool IsABranchingInst(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &I)

bool isDuplex(MCInstrInfo const &MCII, MCInst const &MCI)

bool isPredicateLate(MCInstrInfo const &MCII, MCInst const &MCI)

bool isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI)

Return whether the insn can be packaged only with A and X-type insns.

bool isNewValue(MCInstrInfo const &MCII, MCInst const &MCI)

Return whether the insn expects newly produced value.

MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)

iterator_range< Hexagon::PacketIterator > bundleInstructions(MCInstrInfo const &MCII, MCInst const &MCI)

bool isBundle(MCInst const &MCI)

bool isCofRelax1(MCInstrInfo const &MCII, MCInst const &MCI)

unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)

Return the Hexagon ISA class for the insn.

MCOperand const & getNewValueOperand(MCInstrInfo const &MCII, MCInst const &MCI)

bool isPredicated(MCInstrInfo const &MCII, MCInst const &MCI)

bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI)

bool isInnerLoop(MCInst const &MCI)

PredicateInfo predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI)

unsigned slotsConsumed(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)

bool hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI)

unsigned packetSizeSlots(MCSubtargetInfo const &STI)

bool isPredReg(MCRegisterInfo const &MRI, MCRegister Reg)

bool isPredicatedTrue(MCInstrInfo const &MCII, MCInst const &MCI)

bool isAccumulator(MCInstrInfo const &MCII, MCInst const &MCI)

Return where the instruction is an accumulator.

bool isCVINew(MCInstrInfo const &MCII, MCInst const &MCI)

bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI)

Return whether it is a floating-point insn.

bool isCofRelax2(MCInstrInfo const &MCII, MCInst const &MCI)

This is an optimization pass for GlobalISel generic memory operations.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

class LLVM_GSL_OWNER SmallVector

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

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

DWARFExpression::Operation Op

auto count_if(R &&Range, UnaryPredicate P)

Wrapper function around std::count_if to count the number of times an element satisfying a given pred...