23 #define DEBUG_TYPE "si-fold-operands"
28 struct FoldCandidate {
35 unsigned char UseOpNo;
40 if (FoldOp->
isImm()) {
41 ImmToFold = FoldOp->
getImm();
42 }
else if (FoldOp->
isFI()) {
43 FrameIndexToFold = FoldOp->
getIndex();
85 StringRef getPassName()
const override {
return "SI Fold Operands"; }
96 "SI Fold Operands",
false,
false)
98 char SIFoldOperands::
ID = 0;
108 if (TII->isInlineConstant(UseMI, OpNo, OpToFold))
111 unsigned Opc = UseMI.getOpcode();
113 case AMDGPU::V_MAC_F32_e64:
114 case AMDGPU::V_MAC_F16_e64: {
118 if (static_cast<int>(OpNo) == Src2Idx) {
119 bool IsF32 = Opc == AMDGPU::V_MAC_F32_e64;
121 = TII->get(IsF32 ? AMDGPU::V_MAD_F32 : AMDGPU::V_MAD_F16);
131 return new SIFoldOperands();
136 case AMDGPU::V_MOV_B32_e32:
137 case AMDGPU::V_MOV_B32_e64:
138 case AMDGPU::V_MOV_B64_PSEUDO: {
146 case AMDGPU::S_MOV_B32:
147 case AMDGPU::S_MOV_B64:
185 for (
auto Candidate : FoldList) {
186 if (Candidate.UseMI == MI)
200 if ((Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64) &&
202 bool IsF32 = Opc == AMDGPU::V_MAC_F32_e64;
206 MI->
setDesc(TII->get(IsF32 ? AMDGPU::V_MAD_F32 : AMDGPU::V_MAD_F16));
216 if (Opc == AMDGPU::S_SETREG_B32 && OpToFold->
isImm()) {
217 MI->
setDesc(TII->get(AMDGPU::S_SETREG_IMM32_B32));
218 FoldList.
push_back(FoldCandidate(MI, OpNo, OpToFold));
235 if (CommuteIdx0 == OpNo)
237 else if (CommuteIdx1 == OpNo)
250 !TII->commuteInstruction(*MI,
false, CommuteIdx0, CommuteIdx1))
257 FoldList.
push_back(FoldCandidate(MI, OpNo, OpToFold));
269 void SIFoldOperands::foldOperand(
306 RSUse =
MRI->use_begin(RegSeqDstReg), RSE =
MRI->use_end();
307 RSUse != RSE; ++RSUse) {
310 if (RSUse->getSubReg() != RegSeqDstSubReg)
313 foldOperand(OpToFold, RSUseMI, RSUse.
getOperandNo(), FoldList,
321 bool FoldingImm = OpToFold.
isImm();
325 if (FoldingImm && UseMI->
isCopy()) {
329 MRI->getRegClass(DestReg) :
330 TRI->getPhysRegClass(DestReg);
332 unsigned MovOp =
TII->getMovOpcode(DestRC);
333 if (MovOp == AMDGPU::COPY)
370 MRI->getRegClass(UseReg) :
371 TRI->getPhysRegClass(UseReg);
373 assert(Imm.getBitWidth() == 64);
379 Imm = Imm.getLoBits(32);
382 Imm = Imm.getHiBits(32);
393 case AMDGPU::V_AND_B32_e64:
394 case AMDGPU::V_AND_B32_e32:
395 case AMDGPU::S_AND_B32:
398 case AMDGPU::V_OR_B32_e64:
399 case AMDGPU::V_OR_B32_e32:
400 case AMDGPU::S_OR_B32:
403 case AMDGPU::V_XOR_B32_e64:
404 case AMDGPU::V_XOR_B32_e32:
405 case AMDGPU::S_XOR_B32:
408 case AMDGPU::V_LSHL_B32_e64:
409 case AMDGPU::V_LSHL_B32_e32:
410 case AMDGPU::S_LSHL_B32:
412 Result = LHS << (RHS & 31);
414 case AMDGPU::V_LSHLREV_B32_e64:
415 case AMDGPU::V_LSHLREV_B32_e32:
416 Result = RHS << (LHS & 31);
418 case AMDGPU::V_LSHR_B32_e64:
419 case AMDGPU::V_LSHR_B32_e32:
420 case AMDGPU::S_LSHR_B32:
421 Result = LHS >> (RHS & 31);
423 case AMDGPU::V_LSHRREV_B32_e64:
424 case AMDGPU::V_LSHRREV_B32_e32:
425 Result = RHS >> (LHS & 31);
427 case AMDGPU::V_ASHR_I32_e64:
428 case AMDGPU::V_ASHR_I32_e32:
429 case AMDGPU::S_ASHR_I32:
430 Result =
static_cast<int32_t
>(LHS) >> (RHS & 31);
432 case AMDGPU::V_ASHRREV_I32_e64:
433 case AMDGPU::V_ASHRREV_I32_e32:
434 Result =
static_cast<int32_t
>(RHS) >> (LHS & 31);
442 return IsScalar ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
467 if (Op.
getSubReg() != AMDGPU::NoSubRegister)
489 if (Opc == AMDGPU::V_NOT_B32_e64 || Opc == AMDGPU::V_NOT_B32_e32 ||
490 Opc == AMDGPU::S_NOT_B32) {
504 if (!Src0->
isImm() && !Src1->isImm())
510 if (Src0->
isImm() && Src1->isImm()) {
529 if (Src0->
isImm() && !Src1->isImm()) {
534 int32_t Src1Val =
static_cast<int32_t
>(Src1->getImm());
535 if (Opc == AMDGPU::V_OR_B32_e64 ||
536 Opc == AMDGPU::V_OR_B32_e32 ||
537 Opc == AMDGPU::S_OR_B32) {
542 }
else if (Src1Val == -1) {
552 if (MI->
getOpcode() == AMDGPU::V_AND_B32_e64 ||
553 MI->
getOpcode() == AMDGPU::V_AND_B32_e32 ||
559 }
else if (Src1Val == -1) {
570 if (MI->
getOpcode() == AMDGPU::V_XOR_B32_e64 ||
571 MI->
getOpcode() == AMDGPU::V_XOR_B32_e32 ||
593 bool FoldingImm = OpToFold.
isImm() || OpToFold.
isFI();
595 unsigned NumLiteralUses = 0;
597 int NonInlineUseOpNo = -1;
603 NextUse = std::next(
Use);
617 DEBUG(
dbgs() <<
"Constant folded " << *UseMI <<
'\n');
643 foldOperand(OpToFold, UseMI, OpNo, FoldList, CopiesToReplace);
645 if (++NumLiteralUses == 1) {
646 NonInlineUse = &*
Use;
647 NonInlineUseOpNo = OpNo;
652 if (NumLiteralUses == 1) {
654 foldOperand(OpToFold, UseMI, NonInlineUseOpNo, FoldList, CopiesToReplace);
664 FoldList, CopiesToReplace);
671 Copy->addImplicitDefUseOperands(*MF);
673 for (FoldCandidate &Fold : FoldList) {
677 assert(Fold.OpToFold && Fold.OpToFold->isReg());
681 MRI->clearKillFlags(Fold.OpToFold->getReg());
683 DEBUG(
dbgs() <<
"Folded source from " << MI <<
" into OpNo " <<
684 static_cast<int>(Fold.UseOpNo) <<
" of " << *Fold.UseMI <<
'\n');
704 for (I = MBB.
begin(); I != MBB.
end(); I = Next) {
712 bool FoldingImm = OpToFold.
isImm() || OpToFold.
isFI();
715 if (!FoldingImm && !OpToFold.
isReg())
718 if (OpToFold.
isReg() &&
733 foldInstOperand(MI, OpToFold);
static bool isReg(const MCInst &MI, unsigned OpNo)
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
unsigned getNumImplicitUses() const
Return the number of implicit uses this instruction has.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
AMDGPU specific subclass of TargetSubtarget.
static bool isUseMIInFoldList(ArrayRef< FoldCandidate > FoldList, const MachineInstr *MI)
unsigned getNumImplicitDefs() const
Return the number of implicit defs this instruct has.
Describe properties that are true of each instruction in the target description file.
MachineInstrBuilder MachineInstrBuilder &DefMI const MCInstrDesc & Desc
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
const SIInstrInfo * getInstrInfo() const override
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, const MachineOperand *MO=nullptr) const
Check if MO is a legal operand if it was the OpIdx Operand for MI.
unsigned getID() const
Return the register class ID number.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
void substVirtReg(unsigned Reg, unsigned SubIdx, const TargetRegisterInfo &)
substVirtReg - Substitute the current register with the virtual subregister Reg:SubReg.
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
static unsigned getMovOpc(bool IsScalar)
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
A Use represents the edge between a Value definition and its users.
static bool tryAddToFoldList(SmallVectorImpl< FoldCandidate > &FoldList, MachineInstr *MI, unsigned OpNo, MachineOperand *OpToFold, const SIInstrInfo *TII)
static bool updateOperand(FoldCandidate &Fold, const TargetRegisterInfo &TRI)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static MachineOperand * getImmOrMaterializedImm(MachineRegisterInfo &MRI, MachineOperand &Op)
unsigned getNumOperands() const
Access to explicit operands of the instruction.
uint8_t OperandType
Information about the type of the operand.
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
const HexagonRegisterInfo & getRegisterInfo() const
HexagonInstrInfo specifics.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
void untieRegOperand(unsigned OpIdx)
Break any tie involving OpIdx.
const SIRegisterInfo & getRegisterInfo() const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
const MachineBasicBlock * getParent() const
static const unsigned CommuteAnyOperandIndex
unsigned const MachineRegisterInfo * MRI
static void mutateCopyOp(MachineInstr &MI, const MCInstrDesc &NewDesc)
unsigned getOperandNo() const
Return the operand # of this use in its User.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineInstrBuilder & UseMI
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
unsigned getSubReg() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Iterator for intrusive lists based on ilist_node.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool isSGPRReg(const MachineRegisterInfo &MRI, unsigned Reg) const
void setPreservesCFG()
This function should be called by the pass, iff they do not:
static void stripExtraCopyOperands(MachineInstr &MI)
Remove any leftover implicit operands from mutating the instruction.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Class for arbitrary precision integers.
static bool evalBinaryInstruction(unsigned Opcode, int32_t &Result, uint32_t LHS, uint32_t RHS)
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.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void initializeSIFoldOperandsPass(PassRegistry &)
Interface definition for SIInstrInfo.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static bool isUseSafeToFold(const MachineInstr &MI, const MachineOperand &UseMO)
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
FunctionPass * createSIFoldOperandsPass()
static unsigned UseReg(const MachineOperand &MO)
static MachineOperand CreateImm(int64_t Val)
static bool isInlineConstantIfFolded(const SIInstrInfo *TII, const MachineInstr &UseMI, unsigned OpNo, const MachineOperand &OpToFold)
Abstract Stack Frame Index.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
unsigned getReg() const
getReg - Returns the register number.
bool isCommutable(QueryType Type=IgnoreBundle) const
Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z, ..."), which produces the same result if Y and Z are exchanged.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const MCOperandInfo * OpInfo
void ChangeToFrameIndex(int Idx)
Replace this operand with a frame index.
static bool isSafeToFold(const MachineInstr &MI)
StringRef - Represent a constant reference to a string, i.e.
static bool tryConstantFoldOp(MachineRegisterInfo &MRI, const SIInstrInfo *TII, MachineInstr *MI, MachineOperand *ImmOp)
bool isRegSequence() const
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction...
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
bool findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const override