summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2015-09-28 20:33:22 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2015-09-28 20:33:22 +0000
commit16c4da03d5c8741a4ebbc4bec76c3bfa0c0259c3 (patch)
tree8b6857bf14737d4660d5a57b2355328a22caa14d /llvm/lib/CodeGen
parent69dc971527faad8ccfa754ce7d855908b7a3f923 (diff)
downloadbcm5719-llvm-16c4da03d5c8741a4ebbc4bec76c3bfa0c0259c3.tar.gz
bcm5719-llvm-16c4da03d5c8741a4ebbc4bec76c3bfa0c0259c3.zip
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
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/RegisterCoalescer.cpp23
-rw-r--r--llvm/lib/CodeGen/TargetInstrInfo.cpp78
-rw-r--r--llvm/lib/CodeGen/TwoAddressInstructionPass.cpp114
3 files changed, 148 insertions, 67 deletions
diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp
index 5236b39107d..a2b03aec277 100644
--- a/llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -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) &&
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 4fb1926e3b1..e51f46ac5af 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -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;
diff --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index 13d349be40b..717b07ca059 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -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;
OpenPOWER on IntegriCloud