mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-05 11:46:42 +00:00
Improved the interface of methods commuting operands, improved X86-FMA3 mem-folding&coalescing.
Patch by Slava Klochkov (vyacheslav.n.klochkov@intel.com) Differential Revision: http://reviews.llvm.org/D11370 llvm-svn: 248735
This commit is contained in:
parent
41beb27585
commit
8d27e2d077
@ -94,6 +94,41 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// This method commutes the operands of the given machine instruction MI.
|
||||
/// The operands to be commuted are specified by their indices OpIdx1 and
|
||||
/// OpIdx2.
|
||||
///
|
||||
/// If a target has any instructions that are commutable but require
|
||||
/// converting to different instructions or making non-trivial changes
|
||||
/// to commute them, this method can be overloaded to do that.
|
||||
/// The default implementation simply swaps the commutable operands.
|
||||
///
|
||||
/// If NewMI is false, MI is modified in place and returned; otherwise, a
|
||||
/// new machine instruction is created and returned.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
virtual MachineInstr *commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const;
|
||||
|
||||
/// Assigns the (CommutableOpIdx1, CommutableOpIdx2) pair of commutable
|
||||
/// operand indices to (ResultIdx1, ResultIdx2).
|
||||
/// One or both input values of the pair: (ResultIdx1, ResultIdx2) may be
|
||||
/// predefined to some indices or be undefined (designated by the special
|
||||
/// value 'CommuteAnyOperandIndex').
|
||||
/// The predefined result indices cannot be re-defined.
|
||||
/// The function returns true iff after the result pair redefinition
|
||||
/// the fixed result pair is equal to or equivalent to the source pair of
|
||||
/// indices: (CommutableOpIdx1, CommutableOpIdx2). It is assumed here that
|
||||
/// the pairs (x,y) and (y,x) are equivalent.
|
||||
static bool fixCommutedOpIndices(unsigned &ResultIdx1,
|
||||
unsigned &ResultIdx2,
|
||||
unsigned CommutableOpIdx1,
|
||||
unsigned CommutableOpIdx2);
|
||||
|
||||
private:
|
||||
/// For instructions with opcodes for which the M_REMATERIALIZABLE flag is
|
||||
/// set and the target hook isReallyTriviallyReMaterializable returns false,
|
||||
@ -250,20 +285,51 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// If a target has any instructions that are commutable but require
|
||||
/// converting to different instructions or making non-trivial changes to
|
||||
/// commute them, this method can overloaded to do that.
|
||||
/// The default implementation simply swaps the commutable operands.
|
||||
/// If NewMI is false, MI is modified in place and returned; otherwise, a
|
||||
/// new machine instruction is created and returned. Do not call this
|
||||
/// method for a non-commutable instruction, but there may be some cases
|
||||
/// where this method fails and returns null.
|
||||
virtual MachineInstr *commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI = false) const;
|
||||
// This constant can be used as an input value of operand index passed to
|
||||
// the method findCommutedOpIndices() to tell the method that the
|
||||
// corresponding operand index is not pre-defined and that the method
|
||||
// can pick any commutable operand.
|
||||
static const unsigned CommuteAnyOperandIndex = ~0U;
|
||||
|
||||
/// If specified MI is commutable, return the two operand indices that would
|
||||
/// swap value. Return false if the instruction
|
||||
/// is not in a form which this routine understands.
|
||||
/// This method commutes the operands of the given machine instruction MI.
|
||||
///
|
||||
/// The operands to be commuted are specified by their indices OpIdx1 and
|
||||
/// OpIdx2. OpIdx1 and OpIdx2 arguments may be set to a special value
|
||||
/// 'CommuteAnyOperandIndex', which means that the method is free to choose
|
||||
/// any arbitrarily chosen commutable operand. If both arguments are set to
|
||||
/// 'CommuteAnyOperandIndex' then the method looks for 2 different commutable
|
||||
/// operands; then commutes them if such operands could be found.
|
||||
///
|
||||
/// If NewMI is false, MI is modified in place and returned; otherwise, a
|
||||
/// new machine instruction is created and returned.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction or
|
||||
/// for non-commuable operands.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
MachineInstr *
|
||||
commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI = false,
|
||||
unsigned OpIdx1 = CommuteAnyOperandIndex,
|
||||
unsigned OpIdx2 = CommuteAnyOperandIndex) const;
|
||||
|
||||
/// Returns true iff the routine could find two commutable operands in the
|
||||
/// given machine instruction.
|
||||
/// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments.
|
||||
/// If any of the INPUT values is set to the special value
|
||||
/// 'CommuteAnyOperandIndex' then the method arbitrarily picks a commutable
|
||||
/// operand, then returns its index in the corresponding argument.
|
||||
/// If both of INPUT values are set to 'CommuteAnyOperandIndex' then method
|
||||
/// looks for 2 commutable operands.
|
||||
/// If INPUT values refer to some operands of MI, then the method simply
|
||||
/// returns true if the corresponding operands are commutable and returns
|
||||
/// false otherwise.
|
||||
///
|
||||
/// For example, calling this method this way:
|
||||
/// unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex;
|
||||
/// findCommutedOpIndices(MI, Op1, Op2);
|
||||
/// can be interpreted as a query asking to find an operand that would be
|
||||
/// commutable with the operand#1.
|
||||
virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const;
|
||||
|
||||
|
@ -665,14 +665,18 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
|
||||
unsigned UseOpIdx;
|
||||
if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx))
|
||||
return false;
|
||||
unsigned Op1, Op2, NewDstIdx;
|
||||
if (!TII->findCommutedOpIndices(DefMI, Op1, Op2))
|
||||
return false;
|
||||
if (Op1 == UseOpIdx)
|
||||
NewDstIdx = Op2;
|
||||
else if (Op2 == UseOpIdx)
|
||||
NewDstIdx = Op1;
|
||||
else
|
||||
|
||||
// FIXME: The code below tries to commute 'UseOpIdx' operand with some other
|
||||
// commutable operand which is expressed by 'CommuteAnyOperandIndex'value
|
||||
// passed to the method. That _other_ operand is chosen by
|
||||
// the findCommutedOpIndices() method.
|
||||
//
|
||||
// That is obviously an area for improvement in case of instructions having
|
||||
// more than 2 operands. For example, if some instruction has 3 commutable
|
||||
// operands then all possible variants (i.e. op#1<->op#2, op#1<->op#3,
|
||||
// op#2<->op#3) of commute transformation should be considered/tried here.
|
||||
unsigned NewDstIdx = TargetInstrInfo::CommuteAnyOperandIndex;
|
||||
if (!TII->findCommutedOpIndices(DefMI, UseOpIdx, NewDstIdx))
|
||||
return false;
|
||||
|
||||
MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx);
|
||||
@ -705,7 +709,8 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
|
||||
// At this point we have decided that it is legal to do this
|
||||
// transformation. Start by commuting the instruction.
|
||||
MachineBasicBlock *MBB = DefMI->getParent();
|
||||
MachineInstr *NewMI = TII->commuteInstruction(DefMI);
|
||||
MachineInstr *NewMI =
|
||||
TII->commuteInstruction(DefMI, false, UseOpIdx, NewDstIdx);
|
||||
if (!NewMI)
|
||||
return false;
|
||||
if (TargetRegisterInfo::isVirtualRegister(IntA.reg) &&
|
||||
|
@ -118,23 +118,23 @@ TargetInstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
|
||||
MBB->addSuccessor(NewDest);
|
||||
}
|
||||
|
||||
// commuteInstruction - The default implementation of this method just exchanges
|
||||
// the two operands returned by findCommutedOpIndices.
|
||||
MachineInstr *TargetInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI) const {
|
||||
MachineInstr *TargetInstrInfo::commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned Idx1,
|
||||
unsigned Idx2) const {
|
||||
const MCInstrDesc &MCID = MI->getDesc();
|
||||
bool HasDef = MCID.getNumDefs();
|
||||
if (HasDef && !MI->getOperand(0).isReg())
|
||||
// No idea how to commute this instruction. Target should implement its own.
|
||||
return nullptr;
|
||||
unsigned Idx1, Idx2;
|
||||
if (!findCommutedOpIndices(MI, Idx1, Idx2)) {
|
||||
assert(MI->isCommutable() && "Precondition violation: MI must be commutable.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned CommutableOpIdx1 = Idx1, CommutableOpIdx2 = Idx2;
|
||||
assert(findCommutedOpIndices(MI, CommutableOpIdx1, CommutableOpIdx2) &&
|
||||
CommutableOpIdx1 == Idx1 && CommutableOpIdx2 == Idx2 &&
|
||||
"TargetInstrInfo::CommuteInstructionImpl(): not commutable operands.");
|
||||
assert(MI->getOperand(Idx1).isReg() && MI->getOperand(Idx2).isReg() &&
|
||||
"This only knows how to commute register operands so far");
|
||||
|
||||
unsigned Reg0 = HasDef ? MI->getOperand(0).getReg() : 0;
|
||||
unsigned Reg1 = MI->getOperand(Idx1).getReg();
|
||||
unsigned Reg2 = MI->getOperand(Idx2).getReg();
|
||||
@ -184,9 +184,53 @@ MachineInstr *TargetInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
return MI;
|
||||
}
|
||||
|
||||
/// findCommutedOpIndices - If specified MI is commutable, return the two
|
||||
/// operand indices that would swap value. Return true if the instruction
|
||||
/// is not in a form which this routine understands.
|
||||
MachineInstr *TargetInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const {
|
||||
// If OpIdx1 or OpIdx2 is not specified, then this method is free to choose
|
||||
// any commutable operand, which is done in findCommutedOpIndices() method
|
||||
// called below.
|
||||
if ((OpIdx1 == CommuteAnyOperandIndex || OpIdx2 == CommuteAnyOperandIndex) &&
|
||||
!findCommutedOpIndices(MI, OpIdx1, OpIdx2)) {
|
||||
assert(MI->isCommutable() &&
|
||||
"Precondition violation: MI must be commutable.");
|
||||
return nullptr;
|
||||
}
|
||||
return commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
|
||||
bool TargetInstrInfo::fixCommutedOpIndices(unsigned &ResultIdx1,
|
||||
unsigned &ResultIdx2,
|
||||
unsigned CommutableOpIdx1,
|
||||
unsigned CommutableOpIdx2) {
|
||||
if (ResultIdx1 == CommuteAnyOperandIndex &&
|
||||
ResultIdx2 == CommuteAnyOperandIndex) {
|
||||
ResultIdx1 = CommutableOpIdx1;
|
||||
ResultIdx2 = CommutableOpIdx2;
|
||||
} else if (ResultIdx1 == CommuteAnyOperandIndex) {
|
||||
if (ResultIdx2 == CommutableOpIdx1)
|
||||
ResultIdx1 = CommutableOpIdx2;
|
||||
else if (ResultIdx2 == CommutableOpIdx2)
|
||||
ResultIdx1 = CommutableOpIdx1;
|
||||
else
|
||||
return false;
|
||||
} else if (ResultIdx2 == CommuteAnyOperandIndex) {
|
||||
if (ResultIdx1 == CommutableOpIdx1)
|
||||
ResultIdx2 = CommutableOpIdx2;
|
||||
else if (ResultIdx1 == CommutableOpIdx2)
|
||||
ResultIdx2 = CommutableOpIdx1;
|
||||
else
|
||||
return false;
|
||||
} else
|
||||
// Check that the result operand indices match the given commutable
|
||||
// operand indices.
|
||||
return (ResultIdx1 == CommutableOpIdx1 && ResultIdx2 == CommutableOpIdx2) ||
|
||||
(ResultIdx1 == CommutableOpIdx2 && ResultIdx2 == CommutableOpIdx1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TargetInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const {
|
||||
@ -196,10 +240,15 @@ bool TargetInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
const MCInstrDesc &MCID = MI->getDesc();
|
||||
if (!MCID.isCommutable())
|
||||
return false;
|
||||
|
||||
// This assumes v0 = op v1, v2 and commuting would swap v1 and v2. If this
|
||||
// is not true, then the target must implement this.
|
||||
SrcOpIdx1 = MCID.getNumDefs();
|
||||
SrcOpIdx2 = SrcOpIdx1 + 1;
|
||||
unsigned CommutableOpIdx1 = MCID.getNumDefs();
|
||||
unsigned CommutableOpIdx2 = CommutableOpIdx1 + 1;
|
||||
if (!fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2,
|
||||
CommutableOpIdx1, CommutableOpIdx2))
|
||||
return false;
|
||||
|
||||
if (!MI->getOperand(SrcOpIdx1).isReg() ||
|
||||
!MI->getOperand(SrcOpIdx2).isReg())
|
||||
// No idea.
|
||||
@ -207,7 +256,6 @@ bool TargetInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
|
||||
if (!MI->isTerminator()) return false;
|
||||
|
@ -110,8 +110,8 @@ class TwoAddressInstructionPass : public MachineFunctionPass {
|
||||
bool isProfitableToCommute(unsigned regA, unsigned regB, unsigned regC,
|
||||
MachineInstr *MI, unsigned Dist);
|
||||
|
||||
bool commuteInstruction(MachineBasicBlock::iterator &mi,
|
||||
unsigned RegB, unsigned RegC, unsigned Dist);
|
||||
bool commuteInstruction(MachineInstr *MI,
|
||||
unsigned RegBIdx, unsigned RegCIdx, unsigned Dist);
|
||||
|
||||
bool isProfitableToConv3Addr(unsigned RegA, unsigned RegB);
|
||||
|
||||
@ -133,6 +133,11 @@ class TwoAddressInstructionPass : public MachineFunctionPass {
|
||||
unsigned SrcIdx, unsigned DstIdx,
|
||||
unsigned Dist, bool shouldOnlyCommute);
|
||||
|
||||
bool tryInstructionCommute(MachineInstr *MI,
|
||||
unsigned DstOpIdx,
|
||||
unsigned BaseOpIdx,
|
||||
bool BaseOpKilled,
|
||||
unsigned Dist);
|
||||
void scanUses(unsigned DstReg);
|
||||
|
||||
void processCopy(MachineInstr *MI);
|
||||
@ -645,12 +650,13 @@ isProfitableToCommute(unsigned regA, unsigned regB, unsigned regC,
|
||||
/// commuteInstruction - Commute a two-address instruction and update the basic
|
||||
/// block, distance map, and live variables if needed. Return true if it is
|
||||
/// successful.
|
||||
bool TwoAddressInstructionPass::
|
||||
commuteInstruction(MachineBasicBlock::iterator &mi,
|
||||
unsigned RegB, unsigned RegC, unsigned Dist) {
|
||||
MachineInstr *MI = mi;
|
||||
bool TwoAddressInstructionPass::commuteInstruction(MachineInstr *MI,
|
||||
unsigned RegBIdx,
|
||||
unsigned RegCIdx,
|
||||
unsigned Dist) {
|
||||
unsigned RegC = MI->getOperand(RegCIdx).getReg();
|
||||
DEBUG(dbgs() << "2addr: COMMUTING : " << *MI);
|
||||
MachineInstr *NewMI = TII->commuteInstruction(MI);
|
||||
MachineInstr *NewMI = TII->commuteInstruction(MI, false, RegBIdx, RegCIdx);
|
||||
|
||||
if (NewMI == nullptr) {
|
||||
DEBUG(dbgs() << "2addr: COMMUTING FAILED!\n");
|
||||
@ -1155,6 +1161,61 @@ rescheduleKillAboveMI(MachineBasicBlock::iterator &mi,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Tries to commute the operand 'BaseOpIdx' and some other operand in the
|
||||
/// given machine instruction to improve opportunities for coalescing and
|
||||
/// elimination of a register to register copy.
|
||||
///
|
||||
/// 'DstOpIdx' specifies the index of MI def operand.
|
||||
/// 'BaseOpKilled' specifies if the register associated with 'BaseOpIdx'
|
||||
/// operand is killed by the given instruction.
|
||||
/// The 'Dist' arguments provides the distance of MI from the start of the
|
||||
/// current basic block and it is used to determine if it is profitable
|
||||
/// to commute operands in the instruction.
|
||||
///
|
||||
/// Returns true if the transformation happened. Otherwise, returns false.
|
||||
bool TwoAddressInstructionPass::tryInstructionCommute(MachineInstr *MI,
|
||||
unsigned DstOpIdx,
|
||||
unsigned BaseOpIdx,
|
||||
bool BaseOpKilled,
|
||||
unsigned Dist) {
|
||||
unsigned DstOpReg = MI->getOperand(DstOpIdx).getReg();
|
||||
unsigned BaseOpReg = MI->getOperand(BaseOpIdx).getReg();
|
||||
unsigned OpsNum = MI->getDesc().getNumOperands();
|
||||
unsigned OtherOpIdx = MI->getDesc().getNumDefs();
|
||||
for (; OtherOpIdx < OpsNum; OtherOpIdx++) {
|
||||
// The call of findCommutedOpIndices below only checks if BaseOpIdx
|
||||
// and OtherOpIdx are commutable, it does not really searches for
|
||||
// other commutable operands and does not change the values of passed
|
||||
// variables.
|
||||
if (OtherOpIdx == BaseOpIdx ||
|
||||
!TII->findCommutedOpIndices(MI, BaseOpIdx, OtherOpIdx))
|
||||
continue;
|
||||
|
||||
unsigned OtherOpReg = MI->getOperand(OtherOpIdx).getReg();
|
||||
bool AggressiveCommute = false;
|
||||
|
||||
// If OtherOp dies but BaseOp does not, swap the OtherOp and BaseOp
|
||||
// operands. This makes the live ranges of DstOp and OtherOp joinable.
|
||||
bool DoCommute =
|
||||
!BaseOpKilled && isKilled(*MI, OtherOpReg, MRI, TII, LIS, false);
|
||||
|
||||
if (!DoCommute &&
|
||||
isProfitableToCommute(DstOpReg, BaseOpReg, OtherOpReg, MI, Dist)) {
|
||||
DoCommute = true;
|
||||
AggressiveCommute = true;
|
||||
}
|
||||
|
||||
// If it's profitable to commute, try to do so.
|
||||
if (DoCommute && commuteInstruction(MI, BaseOpIdx, OtherOpIdx, Dist)) {
|
||||
++NumCommuted;
|
||||
if (AggressiveCommute)
|
||||
++NumAggrCommuted;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// tryInstructionTransform - For the case where an instruction has a single
|
||||
/// pair of tied register operands, attempt some transformations that may
|
||||
/// either eliminate the tied operands or improve the opportunities for
|
||||
@ -1181,31 +1242,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi,
|
||||
if (TargetRegisterInfo::isVirtualRegister(regA))
|
||||
scanUses(regA);
|
||||
|
||||
// Check if it is profitable to commute the operands.
|
||||
unsigned SrcOp1, SrcOp2;
|
||||
unsigned regC = 0;
|
||||
unsigned regCIdx = ~0U;
|
||||
bool TryCommute = false;
|
||||
bool AggressiveCommute = false;
|
||||
if (MI.isCommutable() && MI.getNumOperands() >= 3 &&
|
||||
TII->findCommutedOpIndices(&MI, SrcOp1, SrcOp2)) {
|
||||
if (SrcIdx == SrcOp1)
|
||||
regCIdx = SrcOp2;
|
||||
else if (SrcIdx == SrcOp2)
|
||||
regCIdx = SrcOp1;
|
||||
|
||||
if (regCIdx != ~0U) {
|
||||
regC = MI.getOperand(regCIdx).getReg();
|
||||
if (!regBKilled && isKilled(MI, regC, MRI, TII, LIS, false))
|
||||
// If C dies but B does not, swap the B and C operands.
|
||||
// This makes the live ranges of A and C joinable.
|
||||
TryCommute = true;
|
||||
else if (isProfitableToCommute(regA, regB, regC, &MI, Dist)) {
|
||||
TryCommute = true;
|
||||
AggressiveCommute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool Commuted = tryInstructionCommute(&MI, DstIdx, SrcIdx, regBKilled, Dist);
|
||||
|
||||
// If the instruction is convertible to 3 Addr, instead
|
||||
// of returning try 3 Addr transformation aggresively and
|
||||
@ -1215,17 +1252,8 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi,
|
||||
// addl %esi, %edi
|
||||
// movl %edi, %eax
|
||||
// ret
|
||||
bool Commuted = false;
|
||||
|
||||
// If it's profitable to commute, try to do so.
|
||||
if (TryCommute && commuteInstruction(mi, regB, regC, Dist)) {
|
||||
Commuted = true;
|
||||
++NumCommuted;
|
||||
if (AggressiveCommute)
|
||||
++NumAggrCommuted;
|
||||
if (!MI.isConvertibleTo3Addr())
|
||||
return false;
|
||||
}
|
||||
if (Commuted && !MI.isConvertibleTo3Addr())
|
||||
return false;
|
||||
|
||||
if (shouldOnlyCommute)
|
||||
return false;
|
||||
|
@ -165,8 +165,8 @@ static bool tryAddToFoldList(std::vector<FoldCandidate> &FoldList,
|
||||
|
||||
// Operand is not legal, so try to commute the instruction to
|
||||
// see if this makes it possible to fold.
|
||||
unsigned CommuteIdx0;
|
||||
unsigned CommuteIdx1;
|
||||
unsigned CommuteIdx0 = TargetInstrInfo::CommuteAnyOperandIndex;
|
||||
unsigned CommuteIdx1 = TargetInstrInfo::CommuteAnyOperandIndex;
|
||||
bool CanCommute = TII->findCommutedOpIndices(MI, CommuteIdx0, CommuteIdx1);
|
||||
|
||||
if (CanCommute) {
|
||||
@ -176,7 +176,16 @@ static bool tryAddToFoldList(std::vector<FoldCandidate> &FoldList,
|
||||
OpNo = CommuteIdx0;
|
||||
}
|
||||
|
||||
if (!CanCommute || !TII->commuteInstruction(MI))
|
||||
// One of operands might be an Imm operand, and OpNo may refer to it after
|
||||
// the call of commuteInstruction() below. Such situations are avoided
|
||||
// here explicitly as OpNo must be a register operand to be a candidate
|
||||
// for memory folding.
|
||||
if (CanCommute && (!MI->getOperand(CommuteIdx0).isReg() ||
|
||||
!MI->getOperand(CommuteIdx1).isReg()))
|
||||
return false;
|
||||
|
||||
if (!CanCommute ||
|
||||
!TII->commuteInstruction(MI, false, CommuteIdx0, CommuteIdx1))
|
||||
return false;
|
||||
|
||||
if (!TII->isOperandLegal(MI, OpNo, OpToFold))
|
||||
|
@ -782,8 +782,17 @@ bool SIInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI) const {
|
||||
/// Commutes the operands in the given instruction.
|
||||
/// The commutable operands are specified by their indices OpIdx0 and OpIdx1.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction or for
|
||||
/// non-commutable pair of operand indices OpIdx0 and OpIdx1.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
MachineInstr *SIInstrInfo::commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx0,
|
||||
unsigned OpIdx1) const {
|
||||
int CommutedOpcode = commuteOpcode(*MI);
|
||||
if (CommutedOpcode == -1)
|
||||
return nullptr;
|
||||
@ -796,6 +805,13 @@ MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
|
||||
int Src1Idx = AMDGPU::getNamedOperandIdx(MI->getOpcode(),
|
||||
AMDGPU::OpName::src1);
|
||||
|
||||
if ((OpIdx0 != static_cast<unsigned>(Src0Idx) ||
|
||||
OpIdx1 != static_cast<unsigned>(Src1Idx)) &&
|
||||
(OpIdx0 != static_cast<unsigned>(Src1Idx) ||
|
||||
OpIdx1 != static_cast<unsigned>(Src0Idx)))
|
||||
return nullptr;
|
||||
|
||||
MachineOperand &Src1 = MI->getOperand(Src1Idx);
|
||||
|
||||
// Make sure it's legal to commute operands for VOP2.
|
||||
@ -841,7 +857,7 @@ MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
Src1.ChangeToRegister(Reg, false);
|
||||
Src1.setSubReg(SubReg);
|
||||
} else {
|
||||
MI = TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
MI = TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx0, OpIdx1);
|
||||
}
|
||||
|
||||
if (MI)
|
||||
@ -854,8 +870,8 @@ MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
|
||||
// between the true commutable operands, and the base
|
||||
// TargetInstrInfo::commuteInstruction uses it.
|
||||
bool SIInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const {
|
||||
unsigned &SrcOpIdx0,
|
||||
unsigned &SrcOpIdx1) const {
|
||||
const MCInstrDesc &MCID = MI->getDesc();
|
||||
if (!MCID.isCommutable())
|
||||
return false;
|
||||
@ -866,7 +882,8 @@ bool SIInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
return false;
|
||||
|
||||
// FIXME: Workaround TargetInstrInfo::commuteInstruction asserting on
|
||||
// immediate.
|
||||
// immediate. Also, immediate src0 operand is not handled in
|
||||
// SIInstrInfo::commuteInstruction();
|
||||
if (!MI->getOperand(Src0Idx).isReg())
|
||||
return false;
|
||||
|
||||
@ -874,18 +891,22 @@ bool SIInstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
if (Src1Idx == -1)
|
||||
return false;
|
||||
|
||||
if (!MI->getOperand(Src1Idx).isReg())
|
||||
MachineOperand &Src1 = MI->getOperand(Src1Idx);
|
||||
if (Src1.isImm()) {
|
||||
// SIInstrInfo::commuteInstruction() does support commuting the immediate
|
||||
// operand src1 in 2 and 3 operand instructions.
|
||||
if (!isVOP2(MI->getOpcode()) && !isVOP3(MI->getOpcode()))
|
||||
return false;
|
||||
} else if (Src1.isReg()) {
|
||||
// If any source modifiers are set, the generic instruction commuting won't
|
||||
// understand how to copy the source modifiers.
|
||||
if (hasModifiersSet(*MI, AMDGPU::OpName::src0_modifiers) ||
|
||||
hasModifiersSet(*MI, AMDGPU::OpName::src1_modifiers))
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
// If any source modifiers are set, the generic instruction commuting won't
|
||||
// understand how to copy the source modifiers.
|
||||
if (hasModifiersSet(*MI, AMDGPU::OpName::src0_modifiers) ||
|
||||
hasModifiersSet(*MI, AMDGPU::OpName::src1_modifiers))
|
||||
return false;
|
||||
|
||||
SrcOpIdx1 = Src0Idx;
|
||||
SrcOpIdx2 = Src1Idx;
|
||||
return true;
|
||||
return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
|
||||
}
|
||||
|
||||
MachineInstr *SIInstrInfo::buildMovInstr(MachineBasicBlock *MBB,
|
||||
|
@ -61,6 +61,12 @@ private:
|
||||
|
||||
unsigned findUsedSGPR(const MachineInstr *MI, int OpIndices[3]) const;
|
||||
|
||||
protected:
|
||||
MachineInstr *commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx0,
|
||||
unsigned OpIdx1) const override;
|
||||
|
||||
public:
|
||||
explicit SIInstrInfo(const AMDGPUSubtarget &st);
|
||||
|
||||
@ -117,8 +123,6 @@ public:
|
||||
LLVM_READONLY
|
||||
int commuteOpcode(const MachineInstr &MI) const;
|
||||
|
||||
MachineInstr *commuteInstruction(MachineInstr *MI,
|
||||
bool NewMI = false) const override;
|
||||
bool findCommutedOpIndices(MachineInstr *MI,
|
||||
unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const override;
|
||||
|
@ -1738,9 +1738,10 @@ unsigned llvm::getMatchingCondBranchOpcode(unsigned Opc) {
|
||||
llvm_unreachable("Unknown unconditional branch opcode!");
|
||||
}
|
||||
|
||||
/// commuteInstruction - Handle commutable instructions.
|
||||
MachineInstr *
|
||||
ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
MachineInstr *ARMBaseInstrInfo::commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const {
|
||||
switch (MI->getOpcode()) {
|
||||
case ARM::MOVCCr:
|
||||
case ARM::t2MOVCCr: {
|
||||
@ -1750,7 +1751,7 @@ ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
// MOVCC AL can't be inverted. Shouldn't happen.
|
||||
if (CC == ARMCC::AL || PredReg != ARM::CPSR)
|
||||
return nullptr;
|
||||
MI = TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
MI = TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
if (!MI)
|
||||
return nullptr;
|
||||
// After swapping the MOVCC operands, also invert the condition.
|
||||
@ -1759,7 +1760,7 @@ ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
return MI;
|
||||
}
|
||||
}
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
|
||||
/// Identify instructions that can be folded into a MOVCC instruction, and
|
||||
|
@ -86,6 +86,18 @@ protected:
|
||||
RegSubRegPair &BaseReg,
|
||||
RegSubRegPairAndIdx &InsertedReg) const override;
|
||||
|
||||
/// Commutes the operands in the given instruction.
|
||||
/// The commutable operands are specified by their indices OpIdx1 and OpIdx2.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction or for
|
||||
/// non-commutable pair of operand indices OpIdx1 and OpIdx2.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
MachineInstr *commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const override;
|
||||
|
||||
public:
|
||||
// Return whether the target has an explicit NOP encoding.
|
||||
bool hasNOP() const;
|
||||
@ -188,9 +200,6 @@ public:
|
||||
MachineInstr *duplicate(MachineInstr *Orig,
|
||||
MachineFunction &MF) const override;
|
||||
|
||||
MachineInstr *commuteInstruction(MachineInstr*,
|
||||
bool=false) const override;
|
||||
|
||||
const MachineInstrBuilder &AddDReg(MachineInstrBuilder &MIB, unsigned Reg,
|
||||
unsigned SubIdx, unsigned State,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
@ -659,11 +659,13 @@ Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
}
|
||||
} else if (Reg0 != Reg1) {
|
||||
// Try to commute the operands to make it a 2-address instruction.
|
||||
unsigned CommOpIdx1, CommOpIdx2;
|
||||
unsigned CommOpIdx1 = 1;
|
||||
unsigned CommOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;
|
||||
if (!TII->findCommutedOpIndices(MI, CommOpIdx1, CommOpIdx2) ||
|
||||
CommOpIdx1 != 1 || MI->getOperand(CommOpIdx2).getReg() != Reg0)
|
||||
MI->getOperand(CommOpIdx2).getReg() != Reg0)
|
||||
return false;
|
||||
MachineInstr *CommutedMI = TII->commuteInstruction(MI);
|
||||
MachineInstr *CommutedMI =
|
||||
TII->commuteInstruction(MI, false, CommOpIdx1, CommOpIdx2);
|
||||
if (!CommutedMI)
|
||||
return false;
|
||||
}
|
||||
|
@ -316,16 +316,16 @@ unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// commuteInstruction - We can commute rlwimi instructions, but only if the
|
||||
// rotate amt is zero. We also have to munge the immediates a bit.
|
||||
MachineInstr *
|
||||
PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
MachineInstr *PPCInstrInfo::commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const {
|
||||
MachineFunction &MF = *MI->getParent()->getParent();
|
||||
|
||||
// Normal instructions can be commuted the obvious way.
|
||||
if (MI->getOpcode() != PPC::RLWIMI &&
|
||||
MI->getOpcode() != PPC::RLWIMIo)
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
// Note that RLWIMI can be commuted as a 32-bit instruction, but not as a
|
||||
// 64-bit instruction (so we don't handle PPC::RLWIMI8 here), because
|
||||
// changing the relative order of the mask operands might change what happens
|
||||
@ -343,6 +343,8 @@ PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
// Op0 = (Op2 & ~M) | (Op1 & M)
|
||||
|
||||
// Swap op1/op2
|
||||
assert(((OpIdx1 == 1 && OpIdx2 == 2) || (OpIdx1 == 2 && OpIdx2 == 1)) &&
|
||||
"Only the operands 1 and 2 can be swapped in RLSIMI/RLWIMIo.");
|
||||
unsigned Reg0 = MI->getOperand(0).getReg();
|
||||
unsigned Reg1 = MI->getOperand(1).getReg();
|
||||
unsigned Reg2 = MI->getOperand(2).getReg();
|
||||
@ -410,9 +412,9 @@ bool PPCInstrInfo::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
if (AltOpc == -1)
|
||||
return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
|
||||
|
||||
SrcOpIdx1 = 2;
|
||||
SrcOpIdx2 = 3;
|
||||
return true;
|
||||
// The commutable operand indices are 2 and 3. Return them in SrcOpIdx1
|
||||
// and SrcOpIdx2.
|
||||
return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
|
||||
}
|
||||
|
||||
void PPCInstrInfo::insertNoop(MachineBasicBlock &MBB,
|
||||
|
@ -79,6 +79,23 @@ class PPCInstrInfo : public PPCGenInstrInfo {
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs,
|
||||
bool &NonRI, bool &SpillsVRS) const;
|
||||
virtual void anchor();
|
||||
|
||||
protected:
|
||||
/// Commutes the operands in the given instruction.
|
||||
/// The commutable operands are specified by their indices OpIdx1 and OpIdx2.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction or for
|
||||
/// non-commutable pair of operand indices OpIdx1 and OpIdx2.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
///
|
||||
/// For example, we can commute rlwimi instructions, but only if the
|
||||
/// rotate amt is zero. We also have to munge the immediates a bit.
|
||||
MachineInstr *commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const override;
|
||||
|
||||
public:
|
||||
explicit PPCInstrInfo(PPCSubtarget &STI);
|
||||
|
||||
@ -140,10 +157,6 @@ public:
|
||||
unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const override;
|
||||
|
||||
// commuteInstruction - We can commute rlwimi instructions, but only if the
|
||||
// rotate amt is zero. We also have to munge the immediates a bit.
|
||||
MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const override;
|
||||
|
||||
bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const override;
|
||||
|
||||
|
@ -2917,10 +2917,10 @@ X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
/// We have a few instructions that must be hacked on to commute them.
|
||||
///
|
||||
MachineInstr *
|
||||
X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr *MI,
|
||||
bool NewMI,
|
||||
unsigned OpIdx1,
|
||||
unsigned OpIdx2) const {
|
||||
switch (MI->getOpcode()) {
|
||||
case X86::SHRD16rri8: // A = SHRD16rri8 B, C, I -> A = SHLD16rri8 C, B, (16-I)
|
||||
case X86::SHLD16rri8: // A = SHLD16rri8 B, C, I -> A = SHRD16rri8 C, B, (16-I)
|
||||
@ -2947,7 +2947,7 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
}
|
||||
MI->setDesc(get(Opc));
|
||||
MI->getOperand(3).setImm(Size-Amt);
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
case X86::BLENDPDrri:
|
||||
case X86::BLENDPSrri:
|
||||
@ -2983,7 +2983,7 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
NewMI = false;
|
||||
}
|
||||
MI->getOperand(3).setImm(Mask ^ Imm);
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
case X86::PCLMULQDQrr:
|
||||
case X86::VPCLMULQDQrr:{
|
||||
@ -2998,7 +2998,7 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
NewMI = false;
|
||||
}
|
||||
MI->getOperand(3).setImm((Src1Hi << 4) | (Src2Hi >> 4));
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
case X86::CMPPDrri:
|
||||
case X86::CMPPSrri:
|
||||
@ -3019,7 +3019,7 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
MI = MF.CloneMachineInstr(MI);
|
||||
NewMI = false;
|
||||
}
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@ -3048,7 +3048,7 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
NewMI = false;
|
||||
}
|
||||
MI->getOperand(3).setImm(Imm);
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
case X86::CMOVB16rr: case X86::CMOVB32rr: case X86::CMOVB64rr:
|
||||
case X86::CMOVAE16rr: case X86::CMOVAE32rr: case X86::CMOVAE64rr:
|
||||
@ -3127,11 +3127,12 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
|
||||
// Fallthrough intended.
|
||||
}
|
||||
default:
|
||||
return TargetInstrInfo::commuteInstruction(MI, NewMI);
|
||||
return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
|
||||
}
|
||||
}
|
||||
|
||||
bool X86InstrInfo::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
bool X86InstrInfo::findCommutedOpIndices(MachineInstr *MI,
|
||||
unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const {
|
||||
switch (MI->getOpcode()) {
|
||||
case X86::CMPPDrri:
|
||||
@ -3144,13 +3145,13 @@ bool X86InstrInfo::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
// Ordered/Unordered/Equal/NotEqual tests
|
||||
unsigned Imm = MI->getOperand(3).getImm() & 0x7;
|
||||
switch (Imm) {
|
||||
case 0x00: // EQUAL
|
||||
case 0x03: // UNORDERED
|
||||
case 0x04: // NOT EQUAL
|
||||
case 0x07: // ORDERED
|
||||
SrcOpIdx1 = 1;
|
||||
SrcOpIdx2 = 2;
|
||||
return true;
|
||||
case 0x00: // EQUAL
|
||||
case 0x03: // UNORDERED
|
||||
case 0x04: // NOT EQUAL
|
||||
case 0x07: // ORDERED
|
||||
// The indices of the commutable operands are 1 and 2.
|
||||
// Assign them to the returned operand indices here.
|
||||
return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 1, 2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -3178,12 +3179,13 @@ bool X86InstrInfo::findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
case X86::VFNMADDPSr231rY:
|
||||
case X86::VFNMSUBPDr231rY:
|
||||
case X86::VFNMSUBPSr231rY:
|
||||
SrcOpIdx1 = 2;
|
||||
SrcOpIdx2 = 3;
|
||||
return true;
|
||||
// The indices of the commutable operands are 2 and 3.
|
||||
// Assign them to the returned operand indices here.
|
||||
return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
|
||||
default:
|
||||
return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static X86::CondCode getCondFromBranchOpc(unsigned BrOpc) {
|
||||
@ -4998,60 +5000,56 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl(
|
||||
// If the instruction and target operand are commutable, commute the
|
||||
// instruction and try again.
|
||||
if (AllowCommute) {
|
||||
unsigned OriginalOpIdx = OpNum, CommuteOpIdx1, CommuteOpIdx2;
|
||||
unsigned CommuteOpIdx1 = OpNum, CommuteOpIdx2 = CommuteAnyOperandIndex;
|
||||
if (findCommutedOpIndices(MI, CommuteOpIdx1, CommuteOpIdx2)) {
|
||||
bool HasDef = MI->getDesc().getNumDefs();
|
||||
unsigned Reg0 = HasDef ? MI->getOperand(0).getReg() : 0;
|
||||
unsigned Reg1 = MI->getOperand(CommuteOpIdx1).getReg();
|
||||
unsigned Reg2 = MI->getOperand(CommuteOpIdx2).getReg();
|
||||
bool Tied0 =
|
||||
0 == MI->getDesc().getOperandConstraint(CommuteOpIdx1, MCOI::TIED_TO);
|
||||
bool Tied1 =
|
||||
0 == MI->getDesc().getOperandConstraint(CommuteOpIdx1, MCOI::TIED_TO);
|
||||
bool Tied2 =
|
||||
0 == MI->getDesc().getOperandConstraint(CommuteOpIdx2, MCOI::TIED_TO);
|
||||
|
||||
// If either of the commutable operands are tied to the destination
|
||||
// then we can not commute + fold.
|
||||
if ((HasDef && Reg0 == Reg1 && Tied0) ||
|
||||
(HasDef && Reg0 == Reg2 && Tied1))
|
||||
if ((HasDef && Reg0 == Reg1 && Tied1) ||
|
||||
(HasDef && Reg0 == Reg2 && Tied2))
|
||||
return nullptr;
|
||||
|
||||
if ((CommuteOpIdx1 == OriginalOpIdx) ||
|
||||
(CommuteOpIdx2 == OriginalOpIdx)) {
|
||||
MachineInstr *CommutedMI = commuteInstruction(MI, false);
|
||||
if (!CommutedMI) {
|
||||
// Unable to commute.
|
||||
return nullptr;
|
||||
}
|
||||
if (CommutedMI != MI) {
|
||||
// New instruction. We can't fold from this.
|
||||
CommutedMI->eraseFromParent();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attempt to fold with the commuted version of the instruction.
|
||||
unsigned CommuteOp =
|
||||
(CommuteOpIdx1 == OriginalOpIdx ? CommuteOpIdx2 : CommuteOpIdx1);
|
||||
NewMI =
|
||||
foldMemoryOperandImpl(MF, MI, CommuteOp, MOs, InsertPt, Size, Align,
|
||||
/*AllowCommute=*/false);
|
||||
if (NewMI)
|
||||
return NewMI;
|
||||
|
||||
// Folding failed again - undo the commute before returning.
|
||||
MachineInstr *UncommutedMI = commuteInstruction(MI, false);
|
||||
if (!UncommutedMI) {
|
||||
// Unable to commute.
|
||||
return nullptr;
|
||||
}
|
||||
if (UncommutedMI != MI) {
|
||||
// New instruction. It doesn't need to be kept.
|
||||
UncommutedMI->eraseFromParent();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return here to prevent duplicate fuse failure report.
|
||||
MachineInstr *CommutedMI =
|
||||
commuteInstruction(MI, false, CommuteOpIdx1, CommuteOpIdx2);
|
||||
if (!CommutedMI) {
|
||||
// Unable to commute.
|
||||
return nullptr;
|
||||
}
|
||||
if (CommutedMI != MI) {
|
||||
// New instruction. We can't fold from this.
|
||||
CommutedMI->eraseFromParent();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attempt to fold with the commuted version of the instruction.
|
||||
NewMI = foldMemoryOperandImpl(MF, MI, CommuteOpIdx2, MOs, InsertPt,
|
||||
Size, Align, /*AllowCommute=*/false);
|
||||
if (NewMI)
|
||||
return NewMI;
|
||||
|
||||
// Folding failed again - undo the commute before returning.
|
||||
MachineInstr *UncommutedMI =
|
||||
commuteInstruction(MI, false, CommuteOpIdx1, CommuteOpIdx2);
|
||||
if (!UncommutedMI) {
|
||||
// Unable to commute.
|
||||
return nullptr;
|
||||
}
|
||||
if (UncommutedMI != MI) {
|
||||
// New instruction. It doesn't need to be kept.
|
||||
UncommutedMI->eraseFromParent();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return here to prevent duplicate fuse failure report.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,11 +246,21 @@ public:
|
||||
MachineBasicBlock::iterator &MBBI,
|
||||
LiveVariables *LV) const override;
|
||||
|
||||
/// commuteInstruction - We have a few instructions that must be hacked on to
|
||||
/// commute them.
|
||||
/// Returns true iff the routine could find two commutable operands in the
|
||||
/// given machine instruction.
|
||||
/// The 'SrcOpIdx1' and 'SrcOpIdx2' are INPUT and OUTPUT arguments. Their
|
||||
/// input values can be re-defined in this method only if the input values
|
||||
/// are not pre-defined, which is designated by the special value
|
||||
/// 'CommuteAnyOperandIndex' assigned to it.
|
||||
/// If both of indices are pre-defined and refer to some operands, then the
|
||||
/// method simply returns true if the corresponding operands are commutable
|
||||
/// and returns false otherwise.
|
||||
///
|
||||
MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const override;
|
||||
|
||||
/// For example, calling this method this way:
|
||||
/// unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex;
|
||||
/// findCommutedOpIndices(MI, Op1, Op2);
|
||||
/// can be interpreted as a query asking to find an operand that would be
|
||||
/// commutable with the operand#1.
|
||||
bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1,
|
||||
unsigned &SrcOpIdx2) const override;
|
||||
|
||||
@ -485,6 +495,22 @@ public:
|
||||
ArrayRef<std::pair<unsigned, const char *>>
|
||||
getSerializableDirectMachineOperandTargetFlags() const override;
|
||||
|
||||
protected:
|
||||
/// Commutes the operands in the given instruction by changing the operands
|
||||
/// order and/or changing the instruction's opcode and/or the immediate value
|
||||
/// operand.
|
||||
///
|
||||
/// The arguments 'CommuteOpIdx1' and 'CommuteOpIdx2' specify the operands
|
||||
/// to be commuted.
|
||||
///
|
||||
/// Do not call this method for a non-commutable instruction or
|
||||
/// non-commutable operands.
|
||||
/// Even though the instruction is commutable, the method may still
|
||||
/// fail to commute the operands, null pointer is returned in such cases.
|
||||
MachineInstr *commuteInstructionImpl(MachineInstr *MI, bool NewMI,
|
||||
unsigned CommuteOpIdx1,
|
||||
unsigned CommuteOpIdx2) const override;
|
||||
|
||||
private:
|
||||
MachineInstr * convertToThreeAddressWithLEA(unsigned MIOpc,
|
||||
MachineFunction::iterator &MFI,
|
||||
|
Loading…
x
Reference in New Issue
Block a user