23 #define DEBUG_TYPE "legalizer" 35 : Builder(B), MRI(MRI), LI(LI) {}
39 if (MI.
getOpcode() != TargetOpcode::G_ANYEXT)
51 markInstAndDefDead(MI, *MRI.
getVRegDef(SrcReg), DeadInsts);
63 markInstAndDefDead(MI, *ExtMI, DeadInsts);
66 return tryFoldImplicitDef(MI, DeadInsts);
72 if (MI.
getOpcode() != TargetOpcode::G_ZEXT)
83 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
84 isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
92 markInstAndDefDead(MI, *MRI.
getVRegDef(SrcReg), DeadInsts);
95 return tryFoldImplicitDef(MI, DeadInsts);
101 if (MI.
getOpcode() != TargetOpcode::G_SEXT)
112 if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) ||
113 isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) ||
114 isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
118 unsigned ShAmt = DstTy.
getSizeInBits() - SrcTy.getSizeInBits();
121 TargetOpcode::G_SHL, {DstTy},
123 Builder.
buildInstr(TargetOpcode::G_ASHR, {DstReg}, {MIBShl, MIBShAmt});
124 markInstAndDefDead(MI, *MRI.
getVRegDef(SrcReg), DeadInsts);
127 return tryFoldImplicitDef(MI, DeadInsts);
134 if (Opcode != TargetOpcode::G_ANYEXT && Opcode != TargetOpcode::G_ZEXT &&
135 Opcode != TargetOpcode::G_SEXT)
144 if (Opcode == TargetOpcode::G_ANYEXT) {
146 if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
148 LLVM_DEBUG(
dbgs() <<
".. Combine G_ANYEXT(G_IMPLICIT_DEF): " << MI;);
149 Builder.
buildInstr(TargetOpcode::G_IMPLICIT_DEF, {DstReg}, {});
153 if (isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
155 LLVM_DEBUG(
dbgs() <<
".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;);
159 markInstAndDefDead(MI, *
DefMI, DeadInsts);
168 if (MI.
getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
173 unsigned MergingOpcode;
177 MergingOpcode = TargetOpcode::G_CONCAT_VECTORS;
179 MergingOpcode = TargetOpcode::G_BUILD_VECTOR;
181 MergingOpcode = TargetOpcode::G_MERGE_VALUES;
191 if (NumMergeRegs < NumDefs) {
192 if (NumDefs % NumMergeRegs != 0)
203 const unsigned NewNumDefs = NumDefs / NumMergeRegs;
204 for (
unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) {
206 for (
unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs;
213 }
else if (NumMergeRegs > NumDefs) {
214 if (NumMergeRegs % NumDefs != 0)
225 const unsigned NumRegs = NumMergeRegs / NumDefs;
226 for (
unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) {
228 for (
unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs;
242 for (
unsigned Idx = 0; Idx < NumDefs; ++Idx)
247 markInstAndDefDead(MI, *MergeI, DeadInsts);
260 case TargetOpcode::G_ANYEXT:
261 return tryCombineAnyExt(MI, DeadInsts);
262 case TargetOpcode::G_ZEXT:
263 return tryCombineZExt(MI, DeadInsts);
264 case TargetOpcode::G_SEXT:
265 return tryCombineSExt(MI, DeadInsts);
266 case TargetOpcode::G_UNMERGE_VALUES:
267 return tryCombineMerges(MI, DeadInsts);
268 case TargetOpcode::G_TRUNC: {
269 bool Changed =
false;
271 Changed |= tryCombineInstruction(
Use, DeadInsts);
297 while (PrevMI != &DefMI) {
298 unsigned PrevRegSrc =
302 if (TmpDef != &DefMI) {
304 "Expecting copy here");
325 unsigned lookThroughCopyInstrs(
unsigned Reg) {
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
uint64_t getZExtValue() const
Get zero extended value.
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ...
static APInt getAllOnesValue(unsigned numBits)
Get the all-ones value.
UnaryOp_match< SrcTy, TargetOpcode::G_ANYEXT > m_GAnyExt(const SrcTy &Src)
This class represents lattice values for constants.
void push_back(const T &Elt)
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
bool tryCombineMerges(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
unsigned getReg() const
getReg - Returns the register number.
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
bool tryCombineInstruction(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
Try to combine away MI.
Or< Preds... > m_any_of(Preds &&... preds)
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
A Use represents the edge between a Value definition and its users.
MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Res = COPY Op depending on the differing sizes of Res and Op.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
This operation is completely unsupported on the target.
bool tryCombineAnyExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
bool mi_match(Reg R, MachineRegisterInfo &MRI, Pattern &&P)
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
And< Preds... > m_all_of(Preds &&... preds)
MachineInstr * getOpcodeDef(unsigned Opcode, unsigned Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
Sentinel value for when no action was found in the specified table.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
Helper class to build MachineInstr.
void setInstr(MachineInstr &MI)
Set the insertion point to before MI.
LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI)
bool tryFoldImplicitDef(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
Try to fold G_[ASZ]EXT (G_IMPLICIT_DEF).
MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef< unsigned > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ...
MachineInstrBuilder MachineInstrBuilder & DefMI
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
This file declares the MachineIRBuilder class.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Class for arbitrary precision integers.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
UnaryOp_match< SrcTy, TargetOpcode::G_SEXT > m_GSExt(const SrcTy &Src)
void replaceRegWith(unsigned FromReg, unsigned ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
bool tryCombineSExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
LegalizeAction Action
The action to take or the final answer.
bool hasOneUse(unsigned RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
bool tryCombineZExt(MachineInstr &MI, SmallVectorImpl< MachineInstr *> &DeadInsts)
iterator_range< use_instr_iterator > use_instructions(unsigned Reg) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
operand_type_match m_Reg()
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
const MachineOperand & getOperand(unsigned i) const