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

1

2

3

4

5

6

7

8

9

10

11

12

25#include "llvm/IR/IntrinsicsHexagon.h"

29#include

30#include

31#include

32

33using namespace llvm;

34

35#define DEBUG_TYPE "hexagon-subtarget"

36

37#define GET_SUBTARGETINFO_CTOR

38#define GET_SUBTARGETINFO_TARGET_DESC

39#include "HexagonGenSubtargetInfo.inc"

40

43

46

49 cl::desc("Enable the scheduler to generate .cur"));

50

53 cl::desc("Disable Hexagon MI Scheduling"));

54

57 cl::desc("If present, forces/disables the use of long calls"));

58

61 cl::desc("Consider calls to be predicable"));

62

65

68

71 cl::desc("Enable checking for cache bank conflicts"));

72

77 CPUString(std::string(Hexagon_MC::selectHexagonCPU(CPU))),

79 TLInfo(TM, *this), InstrItins(getInstrItineraryForCPU(CPUString)) {

81

82

83 assert(InstrItins.Itineraries != nullptr && "InstrItins not initialized");

84}

85

88 std::optionalHexagon::ArchEnum ArchVer = Hexagon::getCpu(CPUString);

89 if (ArchVer)

91 else

93

94 UseHVX128BOps = false;

95 UseHVX64BOps = false;

96 UseAudioOps = false;

97 UseLongCalls = false;

98

100

101

102

103

104

106 return F == "+hvx-qfloat" || F == "-hvx-qfloat";

107 };

111 if (F.starts_with("+hvxv"))

112 return F;

113 }

115 if (F == "-hvx")

117 if (F.starts_with("+hvx") || F == "-hvx")

118 return F.take_front(4);

119 }

121 };

122

123 bool AddQFloat = false;

124 StringRef HvxVer = getHvxVersion(FS);

126 int Ver = 0;

128 AddQFloat = true;

129 } else if (HvxVer == "+hvx") {

131 AddQFloat = true;

132 }

133

134 if (AddQFloat)

136 }

137

138 std::string FeatureString = Features.getString();

140

142 UseHVXFloatingPoint = UseHVXIEEEFPOps || UseHVXQFloatOps;

143

144 if (UseHVXQFloatOps && UseHVXIEEEFPOps && UseHVXFloatingPoint)

146 dbgs() << "Behavior is undefined for simultaneous qfloat and ieee hvx codegen...");

147

150

152

154

155

158 }

159

162 setFeatureBits(FeatureBits.reset(Hexagon::FeatureDuplex));

164

165 return *this;

166}

167

170 return false;

171 if (Ty.isVector())

172 Ty = Ty.getVectorElementType();

173 if (IncludeBool && Ty == MVT::i1)

174 return true;

177}

178

181 return false;

183 return false;

185 if (!IncludeBool && ElemTy == MVT::i1)

186 return false;

187

191

192 if (IncludeBool && ElemTy == MVT::i1) {

193

194

195 for (MVT T : ElemTypes)

196 if (NumElems * T.getSizeInBits() == 8 * HwLen)

197 return true;

198 return false;

199 }

200

202 if (VecWidth != 8 * HwLen && VecWidth != 16 * HwLen)

203 return false;

205}

206

209 return false;

210

214 return false;

215

216

218 if (!Ty.getVectorElementType().isSimple())

219 return false;

220

221 auto isHvxTy = [this, IncludeBool](MVT SimpleTy) {

223 return true;

226 };

227

228

229

231 unsigned VecLen = PowerOf2Ceil(Ty.getVectorNumElements());

232 while (VecLen > 1) {

234 if (SimpleTy.isValid() && isHvxTy(SimpleTy))

235 return true;

236 VecLen /= 2;

237 }

238

239 return false;

240}

241

245 continue;

247 for (auto &D : SU.Preds)

248 if (D.getKind() == SDep::Output && D.getReg() == Hexagon::USR_OVF)

250 for (auto &E : Erase)

252 }

253}

254

257

258

259

262 bool IsStoreMI1 = MI1.mayStore();

263 bool IsLoadMI1 = MI1.mayLoad();

264 if (!QII->isHVXVec(MI1) || !(IsStoreMI1 || IsLoadMI1))

265 continue;

268 continue;

270 if (!QII->isHVXVec(MI2))

271 continue;

272 if ((IsStoreMI1 && MI2.mayStore()) || (IsLoadMI1 && MI2.mayLoad())) {

273 SI.setLatency(1);

275

276 for (SDep &PI : SI.getSUnit()->Preds) {

277 if (PI.getSUnit() != &SU || PI.getKind() != SDep::Order)

278 continue;

279 PI.setLatency(1);

280 SI.getSUnit()->setDepthDirty();

281 }

282 }

283 }

284 }

285}

286

287

288

289

290

291

292

293

294bool HexagonSubtarget::CallMutation::shouldTFRICallBind(

296 const SUnit &Inst2) const {

298 return false;

299

300

304}

305

308 SUnit* LastSequentialCall = nullptr;

309

311

312

316

317

318

319 for (unsigned su = 0, e = DAG->SUnits.size(); su != e; ++su) {

320

321 if (DAG->SUnits[su].getInstr()->isCall())

322 LastSequentialCall = &DAG->SUnits[su];

323

324 else if (DAG->SUnits[su].getInstr()->isCompare() && LastSequentialCall)

326

327 else if (SchedPredsCloser && LastSequentialCall && su > 1 && su < e-1 &&

328 shouldTFRICallBind(HII, DAG->SUnits[su], DAG->SUnits[su+1]))

330

331

332

333

334

335

336

337

338

339

340

341

342

343

346 if (MI->isCopy() && MI->getOperand(1).getReg().isPhysical()) {

347

348 VRegHoldingReg[MI->getOperand(0).getReg()] = MI->getOperand(1).getReg();

349 LastVRegUse.erase(MI->getOperand(1).getReg());

350 } else {

352 if (!MO.isReg())

353 continue;

354 if (MO.isUse() && MI->isCopy() &&

355 VRegHoldingReg.count(MO.getReg())) {

356

357 LastVRegUse[VRegHoldingReg[MO.getReg()]] = &DAG->SUnits[su];

358 } else if (MO.isDef() && MO.getReg().isPhysical()) {

360 ++AI) {

361 if (auto It = LastVRegUse.find(*AI); It != LastVRegUse.end()) {

362 if (It->second != &DAG->SUnits[su])

363

366 LastVRegUse.erase(It);

367 }

368 }

369 }

370 }

371 }

372 }

373 }

374}

375

378 return;

379

381

382

383

384

385 for (unsigned i = 0, e = DAG->SUnits.size(); i != e; ++i) {

390 continue;

391 int64_t Offset0;

394

395 if (BaseOp0 == nullptr || !BaseOp0->isReg() || !Size0.hasValue() ||

397 continue;

398

399 for (unsigned j = i+1, m = std::min(i+32, e); j != m; ++j) {

404 continue;

405 int64_t Offset1;

408 if (BaseOp1 == nullptr || !BaseOp1->isReg() || !Size0.hasValue() ||

410 continue;

411

412

413 if (((Offset0 ^ Offset1) & 0x18) != 0)

414 continue;

415

416

418 A.setLatency(1);

419 S1.addPred(A, true);

420 }

421 }

422}

423

424

425

428 return true;

429 return false;

430}

431

432

433

435 SUnit *Src, int SrcOpIdx, SUnit *Dst, int DstOpIdx, SDep &Dep,

437 if (!Src->isInstr() || !Dst->isInstr())

438 return;

439

443

444

448 isBestZeroLatency(Src, Dst, QII, ExclSrc, ExclDst)) {

450 return;

451 }

452

453

454

455 if (DstInst->isCopy())

457

458

459

460

461

462

465 std::optional DLatency;

466 for (const auto &DDep : Dst->Succs) {

467 MachineInstr *DDst = DDep.getSUnit()->getInstr();

468 int UseIdx = -1;

469 for (unsigned OpNum = 0; OpNum < DDst->getNumOperands(); OpNum++) {

472 UseIdx = OpNum;

473 break;

474 }

475 }

476

477 if (UseIdx == -1)

478 continue;

479

480 std::optional Latency =

481 InstrInfo.getOperandLatency(&InstrItins, *SrcInst, 0, *DDst, UseIdx);

482

483

484 if (!DLatency)

486

487

488

489 if (DLatency != Latency) {

490 DLatency = std::nullopt;

491 break;

492 }

493 }

494 Dep.setLatency(DLatency.value_or(0));

495 }

496

497

501 isBestZeroLatency(Src, Dst, QII, ExclSrc, ExclDst)) {

503 return;

504 }

507 Latency = updateLatency(*SrcInst, *DstInst, IsArtificial, Latency);

509}

510

512 std::vector<std::unique_ptr> &Mutations) const {

513 Mutations.push_back(std::make_unique());

514 Mutations.push_back(std::make_unique());

515 Mutations.push_back(std::make_unique());

516}

517

519 std::vector<std::unique_ptr> &Mutations) const {

520 Mutations.push_back(std::make_unique());

521 Mutations.push_back(std::make_unique());

522}

523

524

525void HexagonSubtarget::anchor() {}

526

532

536

537int HexagonSubtarget::updateLatency(MachineInstr &SrcInst,

540 if (IsArtificial)

541 return 1;

544

546

550}

551

552void HexagonSubtarget::restoreLatency(SUnit *Src, SUnit *Dst) const {

554 for (auto &I : Src->Succs) {

555 if (I.isAssignedRegDep() || I.getSUnit() != Dst)

556 continue;

558 int DefIdx = -1;

559 for (unsigned OpNum = 0; OpNum < SrcI->getNumOperands(); OpNum++) {

561 bool IsSameOrSubReg = false;

562 if (MO.isReg()) {

565 IsSameOrSubReg = (MOReg == DepR);

566 } else {

567 IsSameOrSubReg = getRegisterInfo()->isSubRegisterEq(DepR, MOReg);

568 }

569 if (MO.isDef() && IsSameOrSubReg)

570 DefIdx = OpNum;

571 }

572 }

573 assert(DefIdx >= 0 && "Def Reg not found in Src MI");

574 MachineInstr *DstI = Dst->getInstr();

575 SDep T = I;

576 for (unsigned OpNum = 0; OpNum < DstI->getNumOperands(); OpNum++) {

577 const MachineOperand &MO = DstI->getOperand(OpNum);

579 std::optional Latency = InstrInfo.getOperandLatency(

580 &InstrItins, *SrcI, DefIdx, *DstI, OpNum);

581

582

583

586 bool IsArtificial = I.isArtificial();

587 Latency = updateLatency(*SrcI, *DstI, IsArtificial, *Latency);

589 }

590 }

591

592

593 T.setSUnit(Src);

594 auto F = find(Dst->Preds, T);

595 assert(F != Dst->Preds.end());

596 F->setLatency(I.getLatency());

597 }

598}

599

600

601void HexagonSubtarget::changeLatency(SUnit *Src, SUnit *Dst, unsigned Lat)

602 const {

603 for (auto &I : Src->Succs) {

604 if (I.isAssignedRegDep() || I.getSUnit() != Dst)

605 continue;

606 SDep T = I;

607 I.setLatency(Lat);

608

609

610 T.setSUnit(Src);

611 auto F = find(Dst->Preds, T);

612 assert(F != Dst->Preds.end());

613 F->setLatency(Lat);

614 }

615}

616

617

619 for (auto &I : Deps)

620 if (I.isAssignedRegDep() && I.getLatency() == 0 &&

621 I.getSUnit()->getInstr()->isPseudo())

622 return I.getSUnit();

623 return nullptr;

624}

625

626

627

628

629

630bool HexagonSubtarget::isBestZeroLatency(

631 SUnit *Src, SUnit *Dst, const HexagonInstrInfo *TII,

632 SmallPtrSet<SUnit *, 4> &ExclSrc, SmallPtrSet<SUnit *, 4> &ExclDst) const {

633 MachineInstr &SrcInst = *Src->getInstr();

634 MachineInstr &DstInst = *Dst->getInstr();

635

636

637 if (Dst->isBoundaryNode())

638 return false;

639

640 if (SrcInst.isPHI() || DstInst.isPHI())

641 return false;

642

643 if (TII->isToBeScheduledASAP(SrcInst, DstInst) &&

644 TII->canExecuteInBundle(SrcInst, DstInst))

645 return false;

646

647

648

649

651 return false;

652

653

654 SUnit *Best = nullptr;

655 SUnit *DstBest = nullptr;

657 if (SrcBest == nullptr || Src->NodeNum >= SrcBest->NodeNum) {

658

660 if (DstBest == nullptr || Dst->NodeNum <= DstBest->NodeNum)

661 Best = Dst;

662 }

663 if (Best != Dst)

664 return false;

665

666

667

668 if ((Src == SrcBest && Dst == DstBest ) ||

669 (SrcBest == nullptr && Dst == DstBest) ||

670 (Src == SrcBest && Dst == nullptr))

671 return true;

672

673

674

675 if (SrcBest != nullptr) {

677 changeLatency(SrcBest, Dst, 1);

678 else

679 restoreLatency(SrcBest, Dst);

680 }

681 if (DstBest != nullptr) {

683 changeLatency(Src, DstBest, 1);

684 else

685 restoreLatency(Src, DstBest);

686 }

687

688

689

690 if (SrcBest && DstBest)

691

692

693 changeLatency(SrcBest, DstBest, 0);

694 else if (DstBest) {

695

696

698 for (auto &I : DstBest->Preds)

699 if (ExclSrc.count(I.getSUnit()) == 0 &&

700 isBestZeroLatency(I.getSUnit(), DstBest, TII, ExclSrc, ExclDst))

701 changeLatency(I.getSUnit(), DstBest, 0);

702 } else if (SrcBest) {

703

704

706 for (auto &I : SrcBest->Succs)

707 if (ExclDst.count(I.getSUnit()) == 0 &&

708 isBestZeroLatency(SrcBest, I.getSUnit(), TII, ExclSrc, ExclDst))

709 changeLatency(SrcBest, I.getSUnit(), 0);

710 }

711

712 return true;

713}

714

718

722

724

726 struct Scalar {

727 unsigned Opcode;

729 };

730 struct Hvx {

731 unsigned Opcode;

733 };

734

735 static Scalar ScalarInts[] = {

736#define GET_SCALAR_INTRINSICS

738#undef GET_SCALAR_INTRINSICS

739 };

740

741 static Hvx HvxInts[] = {

742#define GET_HVX_INTRINSICS

744#undef GET_HVX_INTRINSICS

745 };

746

747 const auto CmpOpcode = [](auto A, auto B) { return A.Opcode < B.Opcode; };

748 [[maybe_unused]] static bool SortedScalar =

749 (llvm::sort(ScalarInts, CmpOpcode), true);

750 [[maybe_unused]] static bool SortedHvx =

751 (llvm::sort(HvxInts, CmpOpcode), true);

752

753 auto [BS, ES] = std::make_pair(std::begin(ScalarInts), std::end(ScalarInts));

754 auto [BH, EH] = std::make_pair(std::begin(HvxInts), std::end(HvxInts));

755

756 auto FoundScalar = std::lower_bound(BS, ES, Scalar{Opc, 0}, CmpOpcode);

757 if (FoundScalar != ES && FoundScalar->Opcode == Opc)

758 return FoundScalar->IntId;

759

760 auto FoundHvx = std::lower_bound(BH, EH, Hvx{Opc, 0, 0}, CmpOpcode);

761 if (FoundHvx != EH && FoundHvx->Opcode == Opc) {

763 if (HwLen == 64)

764 return FoundHvx->Int64Id;

765 if (HwLen == 128)

766 return FoundHvx->Int128Id;

767 }

768

769 std::string error = "Invalid opcode (" + std::to_string(Opc) + ")";

771 return 0;

772}

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

const TargetInstrInfo & TII

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

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

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

static cl::opt< bool > DisableHexagonMISched("disable-hexagon-misched", cl::Hidden, cl::desc("Disable Hexagon MI Scheduling"))

static cl::opt< bool > EnableDotCurSched("enable-cur-sched", cl::Hidden, cl::init(true), cl::desc("Enable the scheduler to generate .cur"))

static cl::opt< bool > EnableCheckBankConflict("hexagon-check-bank-conflict", cl::Hidden, cl::init(true), cl::desc("Enable checking for cache bank conflicts"))

static cl::opt< bool > OverrideLongCalls("hexagon-long-calls", cl::Hidden, cl::desc("If present, forces/disables the use of long calls"))

static cl::opt< bool > SchedPredsCloser("sched-preds-closer", cl::Hidden, cl::init(true))

static cl::opt< bool > SchedRetvalOptimization("sched-retval-optimization", cl::Hidden, cl::init(true))

static cl::opt< bool > EnableTCLatencySched("enable-tc-latency-sched", cl::Hidden, cl::init(false))

static cl::opt< bool > EnableBSBSched("enable-bsb-sched", cl::Hidden, cl::init(true))

static SUnit * getZeroLatency(SUnit *N, SmallVector< SDep, 4 > &Deps)

If the SUnit has a zero latency edge, return the other SUnit.

Definition HexagonSubtarget.cpp:618

static cl::opt< bool > EnablePredicatedCalls("hexagon-pred-calls", cl::Hidden, cl::desc("Consider calls to be predicable"))

Register const TargetRegisterInfo * TRI

This file defines the SmallVector class.

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

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

Container class for subtarget features.

constexpr FeatureBitset & reset(unsigned I)

unsigned getAddrMode(const MachineInstr &MI) const

bool canExecuteInBundle(const MachineInstr &First, const MachineInstr &Second) const

Can these instructions execute at the same time in a bundle.

bool isHVXVec(const MachineInstr &MI) const

bool isToBeScheduledASAP(const MachineInstr &MI1, const MachineInstr &MI2) const

MachineOperand * getBaseAndOffset(const MachineInstr &MI, int64_t &Offset, LocationSize &AccessSize) const

uint64_t getType(const MachineInstr &MI) const

Hexagon::ArchEnum HexagonArchVersion

void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep, const TargetSchedModel *SchedModel) const override

Perform target specific adjustments to the latency of a schedule dependency.

Definition HexagonSubtarget.cpp:434

bool usePredicatedCalls() const

Definition HexagonSubtarget.cpp:533

const HexagonInstrInfo * getInstrInfo() const override

const HexagonRegisterInfo * getRegisterInfo() const override

void getSMSMutations(std::vector< std::unique_ptr< ScheduleDAGMutation > > &Mutations) const override

Definition HexagonSubtarget.cpp:518

HexagonSubtarget(const Triple &TT, StringRef CPU, StringRef FS, const TargetMachine &TM)

Definition HexagonSubtarget.cpp:73

bool isHVXVectorType(EVT VecTy, bool IncludeBool=false) const

Definition HexagonSubtarget.cpp:179

void getPostRAMutations(std::vector< std::unique_ptr< ScheduleDAGMutation > > &Mutations) const override

Definition HexagonSubtarget.cpp:511

const HexagonTargetLowering * getTargetLowering() const override

bool UseBSBScheduling

True if the target should use Back-Skip-Back scheduling.

unsigned getL1PrefetchDistance() const

Definition HexagonSubtarget.cpp:719

ArrayRef< MVT > getHVXElementTypes() const

bool useHVXFloatingPoint() const

bool enableSubRegLiveness() const override

Definition HexagonSubtarget.cpp:723

unsigned getVectorLength() const

void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)

ParseSubtargetFeatures - Parses features string setting specified subtarget options.

bool useHVXV68Ops() const

unsigned getL1CacheLineSize() const

Definition HexagonSubtarget.cpp:715

bool isTypeForHVX(Type *VecTy, bool IncludeBool=false) const

Definition HexagonSubtarget.cpp:207

Intrinsic::ID getIntrinsicId(unsigned Opc) const

Definition HexagonSubtarget.cpp:725

HexagonSubtarget & initializeSubtargetDependencies(StringRef CPU, StringRef FS)

Definition HexagonSubtarget.cpp:87

bool enableMachineScheduler() const override

Definition HexagonSubtarget.cpp:527

bool useBSBScheduling() const

bool isHVXElementType(MVT Ty, bool IncludeBool=false) const

Definition HexagonSubtarget.cpp:168

bool useAA() const override

Enable use of alias analysis during code generation (during MI scheduling, DAGCombine,...

Definition HexagonSubtarget.cpp:426

LegalizeTypeAction getPreferredVectorAction(MVT VT) const override

Return the preferred vector type legalization action.

static LocationSize precise(uint64_t Value)

TypeSize getValue() const

MCRegAliasIterator enumerates all registers aliasing Reg.

static MVT getVectorVT(MVT VT, unsigned NumElements)

MVT getVectorElementType() const

bool isValid() const

Return true if this is a valid simple valuetype.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

unsigned getNumOperands() const

Retuns the total number of operands.

bool mayLoad(QueryType Type=AnyInBundle) const

Return true if this instruction could possibly read memory.

bool isRegSequence() const

bool mayStore(QueryType Type=AnyInBundle) const

Return true if this instruction could possibly modify memory.

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.

Register getReg() const

getReg - Returns the register number.

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

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

@ Output

A register output-dependence (aka WAW).

@ Order

Any other ordering dependency.

void setLatency(unsigned Lat)

Sets the latency for this edge.

@ Barrier

An unknown scheduling barrier.

@ Artificial

Arbitrary strong DAG edge (no real dependence).

unsigned getLatency() const

Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...

bool isArtificial() const

Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...

Scheduling unit. This is a node in the scheduling DAG.

bool isInstr() const

Returns true if this SUnit refers to a machine instruction as opposed to an SDNode.

unsigned NodeNum

Entry # of node in the node vector.

LLVM_ABI void setHeightDirty()

Sets a flag in this node to indicate that its stored Height value will require recomputation the next...

LLVM_ABI void removePred(const SDep &D)

Removes the specified edge as a pred of the current node if it exists.

SmallVector< SDep, 4 > Succs

All sunit successors.

SmallVector< SDep, 4 > Preds

All sunit predecessors.

MachineInstr * getInstr() const

Returns the representative MachineInstr for this SUnit.

A ScheduleDAG for scheduling lists of MachineInstr.

bool addEdge(SUnit *SuccSU, const SDep &PredDep)

Add a DAG edge to the given SU with the given predecessor dependence data.

ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...

const TargetInstrInfo * TII

Target instruction information.

std::vector< SUnit > SUnits

The scheduling units.

MachineFunction & MF

Machine function.

size_type count(ConstPtrType Ptr) const

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

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

bool consumeInteger(unsigned Radix, T &Result)

Parse the current string as an integer of the specified radix.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

Manages the enabling and disabling of subtarget specific features.

const std::vector< std::string > & getFeatures() const

Returns the vector of individual subtarget features.

LLVM_ABI std::string getString() const

Returns features as a string.

LLVM_ABI void AddFeature(StringRef String, bool Enable=true)

Adds Features.

Primary interface to the complete machine description for the target machine.

Provide an instruction scheduling machine model to CodeGen passes.

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

Triple - Helper class for working with autoconf configuration names.

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

bool isVectorTy() const

True if this is an instance of VectorType.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

bool isFloatingPointTy() const

Return true if this is one of the floating-point types.

bool isIntegerTy() const

True if this is an instance of IntegerType.

#define llvm_unreachable(msg)

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

void addArchSubtarget(MCSubtargetInfo const *STI, StringRef FS)

FeatureBitset completeHVXFeatures(const FeatureBitset &FB)

std::optional< Hexagon::ArchEnum > getCpu(StringRef CPU)

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

auto find(R &&Range, const T &Val)

Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.

uint64_t PowerOf2Ceil(uint64_t A)

Returns the power of two which is greater than or equal to the given value.

auto reverse(ContainerTy &&C)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

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

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

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

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

cl::opt< bool > HexagonDisableDuplex

Implement std::hash so that hash_code can be used in STL containers.

bool isSimple() const

Test if the given EVT is simple (as opposed to being extended).

TypeSize getSizeInBits() const

Return the size of the specified value type in bits.

static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)

Return the value type corresponding to the specified type.

MVT getSimpleVT() const

Return the SimpleValueType held in the specified simple EVT.

bool isVector() const

Return true if this is a vector value type.

bool isScalableVector() const

Return true if this is a vector type where the runtime length is machine dependent.

unsigned getVectorNumElements() const

Given a vector type, return the number of elements it contains.

void apply(ScheduleDAGInstrs *DAG) override

Definition HexagonSubtarget.cpp:376

void apply(ScheduleDAGInstrs *DAG) override

Definition HexagonSubtarget.cpp:306

void apply(ScheduleDAGInstrs *DAG) override

Definition HexagonSubtarget.cpp:255

void apply(ScheduleDAGInstrs *DAG) override

Definition HexagonSubtarget.cpp:242