26 #define DEBUG_TYPE "si-shrink-instructions" 29 "Number of 64-bit instruction reduced to 32-bit.");
31 "Number of literal constants folded into 32-bit instructions.");
47 StringRef getPassName()
const override {
return "SI Shrink Instructions"; }
58 "SI Shrink Instructions",
false,
false)
60 char SIShrinkInstructions::
ID = 0;
63 return new SIShrinkInstructions();
78 unsigned Reg = Src0.getReg();
83 bool ConstantFolded =
false;
90 Src0.ChangeToImmediate(MovSrc.
getImm());
91 ConstantFolded =
true;
92 }
else if (MovSrc.
isFI()) {
94 Src0.ChangeToFrameIndex(MovSrc.
getIndex());
95 ConstantFolded =
true;
101 ++NumLiteralConstantsFolded;
110 if (TII->commuteInstruction(MI)) {
115 TII->commuteInstruction(MI);
154 int32_t &ReverseImm) {
158 ReverseImm = reverseBits<int32_t>(
static_cast<int32_t
>(Src.
getImm()));
159 return ReverseImm >= -16 && ReverseImm <= 64;
180 TII->commuteInstruction(MI,
false, 0, 1);
192 if (SOPKOpc == AMDGPU::S_CMPK_EQ_U32 || SOPKOpc == AMDGPU::S_CMPK_LG_U32) {
196 SOPKOpc = (SOPKOpc == AMDGPU::S_CMPK_EQ_U32) ?
197 AMDGPU::S_CMPK_EQ_I32 : AMDGPU::S_CMPK_LG_I32;
230 if (SrcImm->
isImm() &&
235 if (Opc == AMDGPU::S_AND_B32) {
238 Opc = AMDGPU::S_BITSET0_B32;
241 Opc = AMDGPU::S_ANDN2_B32;
243 }
else if (Opc == AMDGPU::S_OR_B32) {
246 Opc = AMDGPU::S_BITSET1_B32;
249 Opc = AMDGPU::S_ORN2_B32;
251 }
else if (Opc == AMDGPU::S_XOR_B32) {
254 Opc = AMDGPU::S_XNOR_B32;
260 if ((Opc == AMDGPU::S_ANDN2_B32 || Opc == AMDGPU::S_ORN2_B32) &&
262 if (!TII->commuteInstruction(MI,
false, 1, 2))
276 if (Opc == AMDGPU::S_BITSET0_B32 ||
277 Opc == AMDGPU::S_BITSET1_B32) {
301 if (TRI.regsOverlap(Reg, MO.getReg()))
303 }
else if (MO.getReg() == Reg &&
305 LaneBitmask Overlap = TRI.getSubRegIndexLaneMask(SubReg) &
306 TRI.getSubRegIndexLaneMask(MO.getSubReg());
329 if (TRI.getRegSizeInBits(Reg, MRI) != 32) {
380 if (YTop.getSubReg() != Tsub)
384 if ((MovY.
getOpcode() != AMDGPU::V_MOV_B32_e32 &&
413 (
I->getOpcode() != AMDGPU::V_MOV_B32_e32 &&
414 I->getOpcode() != AMDGPU::COPY) ||
415 I->getOperand(0).getReg() != X ||
416 I->getOperand(0).getSubReg() != Xsub) {
426 LLVM_DEBUG(
dbgs() <<
"Matched v_swap_b32:\n" << MovT << *MovX << MovY);
428 for (
unsigned I = 0;
I <
Size; ++
I) {
433 TII->get(AMDGPU::V_SWAP_B32))
461 std::vector<unsigned> I1Defs;
468 for (I = MBB.
begin(); I != MBB.
end(); I = Next) {
472 if (MI.
getOpcode() == AMDGPU::V_MOV_B32_e32) {
486 MI.
setDesc(TII->get(AMDGPU::V_BFREV_B32_e32));
495 if (
auto *NextMI =
matchSwap(MI, MRI, TII)) {
496 Next = NextMI->getIterator();
510 (*Next).getOpcode() == AMDGPU::S_NOP) {
520 if (Nop0 + Nop1 <= 8) {
533 if (MI.
getOpcode() == AMDGPU::S_ADD_I32 ||
540 if (TII->commuteInstruction(MI,
false, 1, 2))
556 unsigned Opc = (MI.
getOpcode() == AMDGPU::S_ADD_I32) ?
557 AMDGPU::S_ADDK_I32 : AMDGPU::S_MULK_I32;
572 if (MI.
getOpcode() == AMDGPU::S_MOV_B32) {
580 MI.
setDesc(TII->get(AMDGPU::S_MOVK_I32));
582 MI.
setDesc(TII->get(AMDGPU::S_BREV_B32));
591 if (MI.
getOpcode() == AMDGPU::S_AND_B32 ||
598 if (!TII->hasVALU32BitEncoding(MI.
getOpcode()))
601 if (!TII->canShrink(MI, MRI)) {
604 if (!MI.
isCommutable() || !TII->commuteInstruction(MI) ||
605 !TII->canShrink(MI, MRI))
611 if (!TII->hasVALU32BitEncoding(MI.
getOpcode()))
616 if (TII->isVOPC(Op32)) {
630 if (DstReg != AMDGPU::VCC)
634 if (Op32 == AMDGPU::V_CNDMASK_B32_e32) {
638 TII->getNamedOperand(MI, AMDGPU::OpName::src2);
641 unsigned SReg = Src2->
getReg();
646 if (SReg != AMDGPU::VCC)
652 AMDGPU::OpName::sdst);
656 AMDGPU::OpName::src2);
659 if (SDst->
getReg() != AMDGPU::VCC) {
667 if (Src2 && Src2->
getReg() != AMDGPU::VCC) {
679 ++NumInstructionsShrunk;
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
unsigned getNumImplicitUses() const
Return the number of implicit uses this instruction has.
constexpr bool isUInt< 32 >(uint64_t x)
static bool isReverseInlineImm(const SIInstrInfo *TII, const MachineOperand &Src, int32_t &ReverseImm)
static unsigned getSubRegFromChannel(unsigned Channel)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool use_nodbg_empty(unsigned RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register...
AMDGPU specific subclass of TargetSubtarget.
instr_iterator instr_end()
unsigned getNumImplicitDefs() const
Return the number of implicit defs this instruct has.
This class represents lattice values for constants.
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
static bool sopkIsZext(const MachineInstr &MI)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator_range< use_nodbg_iterator > use_nodbg_operands(unsigned Reg) const
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
unsigned getOperandNo(const_mop_iterator I) const
Returns the number of the operand iterator I points to.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
unsigned getSubReg() const
const SIInstrInfo * getInstrInfo() const override
static bool instModifiesReg(const MachineInstr *MI, unsigned Reg, unsigned SubReg, const SIRegisterInfo &TRI)
constexpr bool isInt< 16 >(int64_t x)
unsigned const TargetRegisterInfo * TRI
bool isInlineConstant(const APInt &Imm) const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const SIRegisterInfo & getRegisterInfo() const
bool isMoveImmediate(QueryType Type=IgnoreBundle) const
Return true if this instruction is a move immediate (including conditional moves) instruction...
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
const HexagonInstrInfo * TII
static TargetInstrInfo::RegSubRegPair getSubRegForIndex(unsigned Reg, unsigned Sub, unsigned I, const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI)
unsigned getNumOperands() const
Retuns the total number of operands.
std::size_t countTrailingOnes(T Value, ZeroBehavior ZB=ZB_Width)
Count the number of ones from the least significant bit to the first zero bit.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static bool isKImmOrKUImmOperand(const SIInstrInfo *TII, const MachineOperand &Src, bool &IsUnsigned)
static bool instAccessReg(iterator_range< MachineInstr::const_mop_iterator > &&R, unsigned Reg, unsigned SubReg, const SIRegisterInfo &TRI)
unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const
Return the size in bytes of the operand OpNo on the given.
bool isVGPR(const MachineRegisterInfo &MRI, unsigned Reg) const
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
STATISTIC(NumInstructionsShrunk, "Number of 64-bit instruction reduced to 32-bit.")
#define DEBUG_TYPE
The pass tries to use the 32-bit encoding for instructions when possible.
static bool isKUImmOperand(const SIInstrInfo *TII, const MachineOperand &Src)
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
TargetInstrInfo::RegSubRegPair RegSubRegPair
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
static void shrinkScalarCompare(const SIInstrInfo *TII, MachineInstr &MI)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
LLVM_READONLY int getSOPKOp(uint16_t Opcode)
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
self_iterator getIterator()
constexpr Type getAsInteger() const
static bool isVOP2(const MachineInstr &MI)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setIsKill(bool Val=true)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool instReadsReg(const MachineInstr *MI, unsigned Reg, unsigned SubReg, const SIRegisterInfo &TRI)
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...
constexpr bool isInt< 32 >(int64_t x)
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_READONLY int getVOPe32(uint16_t Opcode)
MachineOperand class - Representation of each machine instruction operand.
void setRegAllocationHint(unsigned VReg, unsigned Type, unsigned PrefReg)
setRegAllocationHint - Specify a register allocation hint for the specified virtual register...
A pair composed of a register and a sub-register index.
static bool isKImmOperand(const SIInstrInfo *TII, const MachineOperand &Src)
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly. ...
void setPreservesCFG()
This function should be called by the pass, iff they do not:
MachineInstr * getUniqueVRegDef(unsigned Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
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.
A range adaptor for a pair of iterators.
static MachineInstr * matchSwap(MachineInstr &MovT, MachineRegisterInfo &MRI, const SIInstrInfo *TII)
bool use_empty(unsigned RegNo) const
use_empty - Return true if there are no instructions using the specified register.
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
static void copyExtraImplicitOps(MachineInstr &NewMI, MachineFunction &MF, const MachineInstr &MI)
Copy implicit register operands from specified instruction to this instruction that are not part of t...
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
bool hasInv2PiInlineImm() const
Interface definition for SIInstrInfo.
FunctionPass * createSIShrinkInstructionsPass()
bool hasOneUse(unsigned RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static bool isVOPC(const MachineInstr &MI)
constexpr bool any() const
void setSubReg(unsigned subReg)
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
constexpr bool isUInt< 16 >(uint64_t x)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool shrinkScalarLogicOp(const GCNSubtarget &ST, MachineRegisterInfo &MRI, const SIInstrInfo *TII, MachineInstr &MI)
Attempt to shink AND/OR/XOR operations requiring non-inlineable literals.
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
StringRef - Represent a constant reference to a string, i.e.
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
const MachineInstrBuilder & addDef(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineOperand & getOperand(unsigned i) const
static bool isVOP1(const MachineInstr &MI)
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.
static bool foldImmediates(MachineInstr &MI, const SIInstrInfo *TII, MachineRegisterInfo &MRI, bool TryToCommute=true)
This function checks MI for operands defined by a move immediate instruction and then folds the liter...
void tieOperands(unsigned DefIdx, unsigned UseIdx)
Add a tie between the register operands at DefIdx and UseIdx.