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:
Andrew Kaylor 2015-09-28 20:33:22 +00:00
parent 41beb27585
commit 8d27e2d077
14 changed files with 421 additions and 189 deletions

View File

@ -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;

View File

@ -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) &&

View File

@ -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;

View File

@ -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;

View File

@ -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))

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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,