LLVM: lib/CodeGen/GlobalISel/LegalizerInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

25#include

26

27using namespace llvm;

29

30#define DEBUG_TYPE "legalizer-info"

31

33 "disable-gisel-legality-check",

34 cl::desc("Don't verify that MIR is fully legal between GlobalISel passes"),

36

38 "verbose-gisel-verify-legalizer-info",

39 cl::desc("Print more information to dbgs about GlobalISel legalizer rules "

40 "being verified"),

42

44 switch (Action) {

46 OS << "Legal";

47 break;

49 OS << "NarrowScalar";

50 break;

52 OS << "WidenScalar";

53 break;

55 OS << "FewerElements";

56 break;

58 OS << "MoreElements";

59 break;

61 OS << "Bitcast";

62 break;

64 OS << "Lower";

65 break;

67 OS << "Libcall";

68 break;

70 OS << "Custom";

71 break;

73 OS << "Unsupported";

74 break;

76 OS << "NotFound";

77 break;

79 OS << "UseLegacyRules";

80 break;

81 }

82 return OS;

83}

84

86 OS << "Opcode=" << Opcode << ", Tys={";

88 OS << Type << ", ";

89 }

90 OS << "}, MMOs={";

91 for (const auto &MMODescr : MMODescrs) {

92 OS << MMODescr.MemoryTy << ", ";

93 }

94 OS << "}";

95

96 return OS;

97}

98

99#ifndef NDEBUG

100

102 const std::pair<unsigned, LLT> &Mutation) {

110 break;

111 default:

113 }

114 return true;

115}

116

117

120 std::pair<unsigned, LLT> Mutation) {

121

122

124 return true;

125

126

127 if (Mutation.second.isValid())

128 return true;

129

130 const unsigned TypeIdx = Mutation.first;

131 const LLT OldTy = Q.Types[TypeIdx];

133

137 return false;

138 [[fallthrough]];

140

145

147 return false;

148 } else {

149

151 return false;

152 }

154 return false;

155

156

158 }

162

165 return false;

166 } else {

167

169 return false;

170 }

171

173

175 return false;

176 } else {

177

179 return false;

180 }

181

182 return true;

183 }

186 }

187 default:

188 return true;

189 }

190}

191#endif

192

195 dbgs() << "\n");

196 if (Rules.empty()) {

197 LLVM_DEBUG(dbgs() << ".. fallback to legacy rules (no rules defined)\n");

198 return {LegalizeAction::UseLegacyRules, 0, LLT{}};

199 }

201 if (Rule.match(Query)) {

203 std::pair<unsigned, LLT> Mutation = Rule.determineMutation(Query);

204 LLVM_DEBUG(dbgs() << ".. .. " << Rule.getAction() << ", "

207 "legality mutation invalid for match");

210 } else

212 }

214 return {LegalizeAction::Unsupported, 0, LLT{}};

215}

216

218#ifndef NDEBUG

219 if (Rules.empty()) {

221 LLVM_DEBUG(dbgs() << ".. type index coverage check SKIPPED: "

222 << "no rules defined\n");

223 }

224 return true;

225 }

226 const int64_t FirstUncovered = TypeIdxsCovered.find_first_unset();

227 if (FirstUncovered < 0) {

229 LLVM_DEBUG(dbgs() << ".. type index coverage check SKIPPED:"

230 " user-defined predicate detected\n");

231 }

232 return true;

233 }

234 const bool AllCovered = (FirstUncovered >= NumTypeIdxs);

235 if (NumTypeIdxs > 0) {

237 LLVM_DEBUG(dbgs() << ".. the first uncovered type index: "

238 << FirstUncovered << ", "

239 << (AllCovered ? "OK" : "FAIL") << "\n");

240 }

241 }

242 return AllCovered;

243#else

244 return true;

245#endif

246}

247

249#ifndef NDEBUG

250 if (Rules.empty()) {

252 LLVM_DEBUG(dbgs() << ".. imm index coverage check SKIPPED: "

253 << "no rules defined\n");

254 }

255 return true;

256 }

257 const int64_t FirstUncovered = ImmIdxsCovered.find_first_unset();

258 if (FirstUncovered < 0) {

260 LLVM_DEBUG(dbgs() << ".. imm index coverage check SKIPPED:"

261 " user-defined predicate detected\n");

262 }

263 return true;

264 }

265 const bool AllCovered = (FirstUncovered >= NumImmIdxs);

267 LLVM_DEBUG(dbgs() << ".. the first uncovered imm index: " << FirstUncovered

268 << ", " << (AllCovered ? "OK" : "FAIL") << "\n");

269 }

270 return AllCovered;

271#else

272 return true;

273#endif

274}

275

276

279 unsigned TypeIdx) {

280 assert(TypeIdx < MI.getNumOperands() && "Unexpected TypeIdx");

281

282

283

284 if (MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)

285 return MRI.getType(MI.getOperand(MI.getNumOperands() - 1).getReg());

286 return MRI.getType(MI.getOperand(OpIdx).getReg());

287}

288

290 assert(Opcode >= FirstOp && Opcode <= LastOp && "Unsupported opcode");

291 return Opcode - FirstOp;

292}

293

296 if (unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {

298 LLVM_DEBUG(dbgs() << ".. opcode " << Opcode << " is aliased to " << Alias

299 << "\n");

300 }

302 assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 && "Cannot chain aliases");

303 }

304

305 return OpcodeIdx;

306}

307

311 return RulesForOpcode[OpcodeIdx];

312}

313

316 auto &Result = RulesForOpcode[OpcodeIdx];

317 assert(!Result.isAliasedByAnother() && "Modifying this opcode will modify aliases");

318 return Result;

319}

320

322 std::initializer_list Opcodes) {

323 unsigned Representative = *Opcodes.begin();

324

325 assert(Opcodes.size() >= 2 &&

326 "Initializer list must have at least two opcodes");

327

330

332 Return.setIsAliasedByAnother();

333 return Return;

334}

335

337 unsigned OpcodeFrom) {

338 assert(OpcodeTo != OpcodeFrom && "Cannot alias to self");

339 assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp && "Unsupported opcode");

341 RulesForOpcode[OpcodeFromIdx].aliasTo(OpcodeTo);

342}

343

347 if (Step.Action != LegalizeAction::UseLegacyRules) {

348 return Step;

349 }

350

352}

353

360

361 for (unsigned i = 0; i < MI.getDesc().getNumOperands(); ++i) {

362 if (!OpInfo[i].isGenericType())

363 continue;

364

365

366

367 unsigned TypeIdx = OpInfo[i].getGenericTypeIndex();

368 if (SeenTypes[TypeIdx])

369 continue;

370

371 SeenTypes.set(TypeIdx);

372

374 Types.push_back(Ty);

375 }

376

378 for (const auto &MMO : MI.memoperands())

380

381 return getAction({MI.getOpcode(), Types, MemDescrs});

382}

383

388

392

393

394 return Action == Legal || Action == Custom;

395}

396

398 return SmallTy.isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;

399}

400

401

403#ifndef NDEBUG

404 std::vector FailedOpcodes;

405 for (unsigned Opcode = FirstOp; Opcode <= LastOp; ++Opcode) {

407 const unsigned NumTypeIdxs = std::accumulate(

408 MCID.operands().begin(), MCID.operands().end(), 0U,

410 return OpInfo.isGenericType()

411 ? std::max(OpInfo.getGenericTypeIndex() + 1U, Acc)

412 : Acc;

413 });

414 const unsigned NumImmIdxs = std::accumulate(

415 MCID.operands().begin(), MCID.operands().end(), 0U,

417 return OpInfo.isGenericImm()

418 ? std::max(OpInfo.getGenericImmIndex() + 1U, Acc)

419 : Acc;

420 });

423 << "): " << NumTypeIdxs << " type ind"

424 << (NumTypeIdxs == 1 ? "ex" : "ices") << ", "

425 << NumImmIdxs << " imm ind"

426 << (NumImmIdxs == 1 ? "ex" : "ices") << "\n");

427 }

430 FailedOpcodes.push_back(Opcode);

432 FailedOpcodes.push_back(Opcode);

433 }

434 if (!FailedOpcodes.empty()) {

435 errs() << "The following opcodes have ill-defined legalization rules:";

436 for (unsigned Opcode : FailedOpcodes)

438 errs() << "\n";

439

441 "-debug-only=legalizer-info and "

442 "-verbose-gisel-verify-legalizer-info for details");

443 }

444#endif

445}

446

447#ifndef NDEBUG

448

449

450

451

452

459 !MLI->isLegalOrCustom(MI, MRI))

460 return &MI;

461 }

462 return nullptr;

463}

464#endif

unsigned const MachineRegisterInfo * MRI

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

static cl::opt< bool > VerboseVerifyLegalizerInfo("verbose-gisel-verify-legalizer-info", cl::desc("Print more information to dbgs about GlobalISel legalizer rules " "being verified"), cl::Hidden)

static bool hasNoSimpleLoops(const LegalizeRule &Rule, const LegalityQuery &Q, const std::pair< unsigned, LLT > &Mutation)

Definition LegalizerInfo.cpp:101

static LLT getTypeFromTypeIdx(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned OpIdx, unsigned TypeIdx)

Helper function to get LLT for the given type index.

Definition LegalizerInfo.cpp:277

static bool mutationIsSane(const LegalizeRule &Rule, const LegalityQuery &Q, std::pair< unsigned, LLT > Mutation)

Definition LegalizerInfo.cpp:118

Interface for Targets to specify which operations they can successfully select and how the others sho...

Implement a low-level type suitable for MachineInstr level instruction selection.

MachineInstr unsigned OpIdx

This file implements the SmallBitVector class.

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

static constexpr ElementCount getFixed(ScalarTy MinVal)

constexpr unsigned getScalarSizeInBits() const

constexpr bool isVector() const

constexpr bool isByteSized() const

constexpr TypeSize getSizeInBits() const

Returns the total size of the type. Must only be called on sized types.

constexpr ElementCount getElementCount() const

constexpr LLT getScalarType() const

LLVM_ABI LegacyLegalizeActionStep getAction(const LegalityQuery &Query) const

LLVM_ABI bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const

Check if there is no imm index which is obviously not handled by the LegalizeRuleSet in any way at al...

Definition LegalizerInfo.cpp:248

LLVM_ABI bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const

Check if there is no type index which is obviously not handled by the LegalizeRuleSet in any way at a...

Definition LegalizerInfo.cpp:217

LLVM_ABI LegalizeActionStep apply(const LegalityQuery &Query) const

Apply the ruleset to the given LegalityQuery.

Definition LegalizerInfo.cpp:193

A single rule in a legalizer info ruleset.

LegalizeAction getAction() const

const LegalizeRuleSet & getActionDefinitions(unsigned Opcode) const

Get the action definitions for the given opcode.

Definition LegalizerInfo.cpp:309

LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)

Get the action definition builder for the given opcode.

Definition LegalizerInfo.cpp:314

const LegacyLegalizerInfo & getLegacyLegalizerInfo() const

virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const

Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while widening a constant of type Small...

Definition LegalizerInfo.cpp:397

bool isLegalOrCustom(const LegalityQuery &Query) const

void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom)

Definition LegalizerInfo.cpp:336

void verify(const MCInstrInfo &MII) const

Perform simple self-diagnostic and assert if there is anything obviously wrong with the actions set u...

Definition LegalizerInfo.cpp:402

unsigned getOpcodeIdxForOpcode(unsigned Opcode) const

Definition LegalizerInfo.cpp:289

bool isLegal(const LegalityQuery &Query) const

unsigned getActionDefinitionsIdx(unsigned Opcode) const

Definition LegalizerInfo.cpp:294

LegalizeActionStep getAction(const LegalityQuery &Query) const

Determine what action should be taken to legalize the described instruction.

Definition LegalizerInfo.cpp:345

Describe properties that are true of each instruction in the target description file.

Interface to description of machine instruction set.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

StringRef getName(unsigned Opcode) const

Returns the name for the instructions with the given opcode.

This holds information about one operand of a machine instruction, indicating the register class for ...

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.

Representation of each machine instruction.

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

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

void push_back(const T &Elt)

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

virtual const LegalizerInfo * getLegalizerInfo() const

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

static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)

static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)

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

@ FewerElements

The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...

@ Libcall

The operation should be implemented as a call to some kind of runtime support library.

@ Unsupported

This operation is completely unsupported on the target.

@ Lower

The operation itself must be expressed in terms of simpler actions on this target.

@ UseLegacyRules

Fall back onto the old rules.

@ WidenScalar

The operation should be implemented in terms of a wider scalar base-type.

@ Bitcast

Perform the operation on a different, but equivalently sized type.

@ NarrowScalar

The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.

@ Custom

The target wants to do something special with this combination of operand and type.

@ NotFound

Sentinel value for when no action was found in the specified table.

@ MoreElements

The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

bool isPreISelGenericOpcode(unsigned Opcode)

Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.

LLVM_ABI cl::opt< bool > DisableGISelLegalityCheck

LLVM_ABI raw_ostream & dbgs()

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

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

const MachineInstr * machineFunctionIsIllegal(const MachineFunction &MF)

Checks that MIR is fully legal, returns an illegal instruction if it's not, nullptr otherwise.

Definition LegalizerInfo.cpp:453

LLVM_ABI raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

DWARFExpression::Operation Op

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

The LegalityQuery object bundles together all the information that's needed to decide whether a given...

ArrayRef< MemDesc > MMODescrs

Operations which require memory can use this to place requirements on the memory type for each MMO.

LLVM_ABI raw_ostream & print(raw_ostream &OS) const

Definition LegalizerInfo.cpp:85

LegalizeAction Action

The action to take or the final answer.