#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGenTypes/LowLevelType.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
usingnamespacellvm;
usingnamespaceLegalizeActions;
#define DEBUG_TYPE …
cl::opt<bool> llvm::DisableGISelLegalityCheck(
"disable-gisel-legality-check",
cl::desc("Don't verify that MIR is fully legal between GlobalISel passes"),
cl::Hidden);
raw_ostream &llvm::operator<<(raw_ostream &OS, LegalizeAction Action) { … }
raw_ostream &LegalityQuery::print(raw_ostream &OS) const { … }
#ifndef NDEBUG
static bool hasNoSimpleLoops(const LegalizeRule &Rule, const LegalityQuery &Q,
const std::pair<unsigned, LLT> &Mutation) {
switch (Rule.getAction()) {
case Legal:
case Custom:
case Lower:
case MoreElements:
case FewerElements:
case Libcall:
break;
default:
return Q.Types[Mutation.first] != Mutation.second;
}
return true;
}
static bool mutationIsSane(const LegalizeRule &Rule,
const LegalityQuery &Q,
std::pair<unsigned, LLT> Mutation) {
if (Rule.getAction() == Custom || Rule.getAction() == Legal)
return true;
if (!Mutation.second.isValid())
return true;
const unsigned TypeIdx = Mutation.first;
const LLT OldTy = Q.Types[TypeIdx];
const LLT NewTy = Mutation.second;
switch (Rule.getAction()) {
case FewerElements:
if (!OldTy.isVector())
return false;
[[fallthrough]];
case MoreElements: {
const ElementCount OldElts = OldTy.isVector() ?
OldTy.getElementCount() : ElementCount::getFixed(1);
if (NewTy.isVector()) {
if (Rule.getAction() == FewerElements) {
if (ElementCount::isKnownGE(NewTy.getElementCount(), OldElts))
return false;
} else {
if (ElementCount::isKnownLE(NewTy.getElementCount(), OldElts))
return false;
}
} else if (Rule.getAction() == MoreElements)
return false;
return NewTy.getScalarType() == OldTy.getScalarType();
}
case NarrowScalar:
case WidenScalar: {
if (OldTy.isVector()) {
if (!NewTy.isVector() ||
OldTy.getElementCount() != NewTy.getElementCount())
return false;
} else {
if (NewTy.isVector())
return false;
}
if (Rule.getAction() == NarrowScalar) {
if (NewTy.getScalarSizeInBits() >= OldTy.getScalarSizeInBits())
return false;
} else {
if (NewTy.getScalarSizeInBits() <= OldTy.getScalarSizeInBits())
return false;
}
return true;
}
case Bitcast: {
return OldTy != NewTy && OldTy.getSizeInBits() == NewTy.getSizeInBits();
}
default:
return true;
}
}
#endif
LegalizeActionStep LegalizeRuleSet::apply(const LegalityQuery &Query) const { … }
bool LegalizeRuleSet::verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const { … }
bool LegalizeRuleSet::verifyImmIdxsCoverage(unsigned NumImmIdxs) const { … }
static LLT getTypeFromTypeIdx(const MachineInstr &MI,
const MachineRegisterInfo &MRI, unsigned OpIdx,
unsigned TypeIdx) { … }
unsigned LegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode) const { … }
unsigned LegalizerInfo::getActionDefinitionsIdx(unsigned Opcode) const { … }
const LegalizeRuleSet &
LegalizerInfo::getActionDefinitions(unsigned Opcode) const { … }
LegalizeRuleSet &LegalizerInfo::getActionDefinitionsBuilder(unsigned Opcode) { … }
LegalizeRuleSet &LegalizerInfo::getActionDefinitionsBuilder(
std::initializer_list<unsigned> Opcodes) { … }
void LegalizerInfo::aliasActionDefinitions(unsigned OpcodeTo,
unsigned OpcodeFrom) { … }
LegalizeActionStep
LegalizerInfo::getAction(const LegalityQuery &Query) const { … }
LegalizeActionStep
LegalizerInfo::getAction(const MachineInstr &MI,
const MachineRegisterInfo &MRI) const { … }
bool LegalizerInfo::isLegal(const MachineInstr &MI,
const MachineRegisterInfo &MRI) const { … }
bool LegalizerInfo::isLegalOrCustom(const MachineInstr &MI,
const MachineRegisterInfo &MRI) const { … }
unsigned LegalizerInfo::getExtOpcodeForWideningConstant(LLT SmallTy) const { … }
void LegalizerInfo::verify(const MCInstrInfo &MII) const { … }
#ifndef NDEBUG
const MachineInstr *llvm::machineFunctionIsIllegal(const MachineFunction &MF) {
if (const LegalizerInfo *MLI = MF.getSubtarget().getLegalizerInfo()) {
const MachineRegisterInfo &MRI = MF.getRegInfo();
for (const MachineBasicBlock &MBB : MF)
for (const MachineInstr &MI : MBB)
if (isPreISelGenericOpcode(MI.getOpcode()) &&
!MLI->isLegalOrCustom(MI, MRI))
return &MI;
}
return nullptr;
}
#endif