Catch more cases where 2-address pass should 3-addressify instructions. rdar://9002648.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126811 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2011-03-02 01:08:17 +00:00
parent d3fdaeb69a
commit f06e6c2ba7
3 changed files with 86 additions and 55 deletions

View File

@ -105,7 +105,7 @@ namespace {
MachineFunction::iterator &mbbi, MachineFunction::iterator &mbbi,
unsigned RegB, unsigned RegC, unsigned Dist); unsigned RegB, unsigned RegC, unsigned Dist);
bool isProfitableToConv3Addr(unsigned RegA); bool isProfitableToConv3Addr(unsigned RegA, unsigned RegB);
bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi,
MachineBasicBlock::iterator &nmi, MachineBasicBlock::iterator &nmi,
@ -124,7 +124,11 @@ namespace {
MachineBasicBlock::iterator &nmi, MachineBasicBlock::iterator &nmi,
MachineFunction::iterator &mbbi, MachineFunction::iterator &mbbi,
unsigned SrcIdx, unsigned DstIdx, unsigned SrcIdx, unsigned DstIdx,
unsigned Dist); unsigned Dist,
SmallPtrSet<MachineInstr*, 8> &Processed);
void ScanUses(unsigned DstReg, MachineBasicBlock *MBB,
SmallPtrSet<MachineInstr*, 8> &Processed);
void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB, void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB,
SmallPtrSet<MachineInstr*, 8> &Processed); SmallPtrSet<MachineInstr*, 8> &Processed);
@ -615,16 +619,18 @@ TwoAddressInstructionPass::CommuteInstruction(MachineBasicBlock::iterator &mi,
/// isProfitableToConv3Addr - Return true if it is profitable to convert the /// isProfitableToConv3Addr - Return true if it is profitable to convert the
/// given 2-address instruction to a 3-address one. /// given 2-address instruction to a 3-address one.
bool bool
TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA) { TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA,unsigned RegB){
// Look for situations like this: // Look for situations like this:
// %reg1024<def> = MOV r1 // %reg1024<def> = MOV r1
// %reg1025<def> = MOV r0 // %reg1025<def> = MOV r0
// %reg1026<def> = ADD %reg1024, %reg1025 // %reg1026<def> = ADD %reg1024, %reg1025
// r2 = MOV %reg1026 // r2 = MOV %reg1026
// Turn ADD into a 3-address instruction to avoid a copy. // Turn ADD into a 3-address instruction to avoid a copy.
unsigned FromRegA = getMappedReg(RegA, SrcRegMap); unsigned FromRegB = getMappedReg(RegB, SrcRegMap);
if (!FromRegB)
return false;
unsigned ToRegA = getMappedReg(RegA, DstRegMap); unsigned ToRegA = getMappedReg(RegA, DstRegMap);
return (FromRegA && ToRegA && !regsAreCompatible(FromRegA, ToRegA, TRI)); return (ToRegA && !regsAreCompatible(FromRegB, ToRegA, TRI));
} }
/// ConvertInstTo3Addr - Convert the specified two-address instruction into a /// ConvertInstTo3Addr - Convert the specified two-address instruction into a
@ -664,6 +670,54 @@ TwoAddressInstructionPass::ConvertInstTo3Addr(MachineBasicBlock::iterator &mi,
return false; return false;
} }
/// ScanUses - Scan forward recursively for only uses, update maps if the use
/// is a copy or a two-address instruction.
void
TwoAddressInstructionPass::ScanUses(unsigned DstReg, MachineBasicBlock *MBB,
SmallPtrSet<MachineInstr*, 8> &Processed) {
SmallVector<unsigned, 4> VirtRegPairs;
bool IsDstPhys;
bool IsCopy = false;
unsigned NewReg = 0;
unsigned Reg = DstReg;
while (MachineInstr *UseMI = findOnlyInterestingUse(Reg, MBB, MRI, TII,IsCopy,
NewReg, IsDstPhys)) {
if (IsCopy && !Processed.insert(UseMI))
break;
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UseMI);
if (DI != DistanceMap.end())
// Earlier in the same MBB.Reached via a back edge.
break;
if (IsDstPhys) {
VirtRegPairs.push_back(NewReg);
break;
}
bool isNew = SrcRegMap.insert(std::make_pair(NewReg, Reg)).second;
if (!isNew)
assert(SrcRegMap[NewReg] == Reg && "Can't map to two src registers!");
VirtRegPairs.push_back(NewReg);
Reg = NewReg;
}
if (!VirtRegPairs.empty()) {
unsigned ToReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
while (!VirtRegPairs.empty()) {
unsigned FromReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second;
if (!isNew)
assert(DstRegMap[FromReg] == ToReg &&"Can't map to two dst registers!");
ToReg = FromReg;
}
bool isNew = DstRegMap.insert(std::make_pair(DstReg, ToReg)).second;
if (!isNew)
assert(DstRegMap[DstReg] == ToReg && "Can't map to two dst registers!");
}
}
/// ProcessCopy - If the specified instruction is not yet processed, process it /// ProcessCopy - If the specified instruction is not yet processed, process it
/// if it's a copy. For a copy instruction, we find the physical registers the /// if it's a copy. For a copy instruction, we find the physical registers the
/// source and destination registers might be mapped to. These are kept in /// source and destination registers might be mapped to. These are kept in
@ -695,49 +749,11 @@ void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI,
assert(SrcRegMap[DstReg] == SrcReg && assert(SrcRegMap[DstReg] == SrcReg &&
"Can't map to two src physical registers!"); "Can't map to two src physical registers!");
SmallVector<unsigned, 4> VirtRegPairs; ScanUses(DstReg, MBB, Processed);
bool IsCopy = false;
unsigned NewReg = 0;
while (MachineInstr *UseMI = findOnlyInterestingUse(DstReg, MBB, MRI,TII,
IsCopy, NewReg, IsDstPhys)) {
if (IsCopy) {
if (!Processed.insert(UseMI))
break;
}
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UseMI);
if (DI != DistanceMap.end())
// Earlier in the same MBB.Reached via a back edge.
break;
if (IsDstPhys) {
VirtRegPairs.push_back(NewReg);
break;
}
bool isNew = SrcRegMap.insert(std::make_pair(NewReg, DstReg)).second;
if (!isNew)
assert(SrcRegMap[NewReg] == DstReg &&
"Can't map to two src physical registers!");
VirtRegPairs.push_back(NewReg);
DstReg = NewReg;
}
if (!VirtRegPairs.empty()) {
unsigned ToReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
while (!VirtRegPairs.empty()) {
unsigned FromReg = VirtRegPairs.back();
VirtRegPairs.pop_back();
bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second;
if (!isNew)
assert(DstRegMap[FromReg] == ToReg &&
"Can't map to two dst physical registers!");
ToReg = FromReg;
}
}
} }
Processed.insert(MI); Processed.insert(MI);
return;
} }
/// isSafeToDelete - If the specified instruction does not produce any side /// isSafeToDelete - If the specified instruction does not produce any side
@ -836,7 +852,8 @@ bool TwoAddressInstructionPass::
TryInstructionTransform(MachineBasicBlock::iterator &mi, TryInstructionTransform(MachineBasicBlock::iterator &mi,
MachineBasicBlock::iterator &nmi, MachineBasicBlock::iterator &nmi,
MachineFunction::iterator &mbbi, MachineFunction::iterator &mbbi,
unsigned SrcIdx, unsigned DstIdx, unsigned Dist) { unsigned SrcIdx, unsigned DstIdx, unsigned Dist,
SmallPtrSet<MachineInstr*, 8> &Processed) {
const TargetInstrDesc &TID = mi->getDesc(); const TargetInstrDesc &TID = mi->getDesc();
unsigned regA = mi->getOperand(DstIdx).getReg(); unsigned regA = mi->getOperand(DstIdx).getReg();
unsigned regB = mi->getOperand(SrcIdx).getReg(); unsigned regB = mi->getOperand(SrcIdx).getReg();
@ -887,10 +904,13 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi,
return false; return false;
} }
if (TargetRegisterInfo::isVirtualRegister(regA))
ScanUses(regA, &*mbbi, Processed);
if (TID.isConvertibleTo3Addr()) { if (TID.isConvertibleTo3Addr()) {
// This instruction is potentially convertible to a true // This instruction is potentially convertible to a true
// three-address instruction. Check if it is profitable. // three-address instruction. Check if it is profitable.
if (!regBKilled || isProfitableToConv3Addr(regA)) { if (!regBKilled || isProfitableToConv3Addr(regA, regB)) {
// Try to convert it. // Try to convert it.
if (ConvertInstTo3Addr(mi, nmi, mbbi, regA, regB, Dist)) { if (ConvertInstTo3Addr(mi, nmi, mbbi, regA, regB, Dist)) {
++NumConvertedTo3Addr; ++NumConvertedTo3Addr;
@ -951,7 +971,7 @@ TryInstructionTransform(MachineBasicBlock::iterator &mi,
MachineBasicBlock::iterator NewMI = NewMIs[1]; MachineBasicBlock::iterator NewMI = NewMIs[1];
bool TransformSuccess = bool TransformSuccess =
TryInstructionTransform(NewMI, mi, mbbi, TryInstructionTransform(NewMI, mi, mbbi,
NewSrcIdx, NewDstIdx, Dist); NewSrcIdx, NewDstIdx, Dist, Processed);
if (TransformSuccess || if (TransformSuccess ||
NewMIs[1]->getOperand(NewSrcIdx).isKill()) { NewMIs[1]->getOperand(NewSrcIdx).isKill()) {
// Success, or at least we made an improvement. Keep the unfolded // Success, or at least we made an improvement. Keep the unfolded
@ -1100,7 +1120,8 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
mi->getOperand(DstIdx).getReg()) mi->getOperand(DstIdx).getReg())
break; // Done with this instruction. break; // Done with this instruction.
if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist)) if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist,
Processed))
break; // The tied operands have been eliminated. break; // The tied operands have been eliminated.
} }

View File

@ -1,12 +1,11 @@
; RUN: llc < %s -march=x86-64 -stats |& \ ; RUN: llc < %s -march=x86-64 -stats |& \
; RUN: grep {6 .*Number of machine instrs printed} ; RUN: grep {5 .*Number of machine instrs printed}
;; Integer absolute value, should produce something at least as good as: ;; Integer absolute value, should produce something at least as good as:
;; movl %edi, %eax ;; movl %edi, %ecx
;; sarl $31, %eax ;; sarl $31, %ecx
;; addl %eax, %edi ;; leal (%rdi,%rcx), %eax
;; xorl %eax, %edi ;; xorl %ecx, %eax
;; movl %edi, %eax
;; ret ;; ret
define i32 @test(i32 %a) nounwind { define i32 @test(i32 %a) nounwind {
%tmp1neg = sub i32 0, %a %tmp1neg = sub i32 0, %a

View File

@ -34,3 +34,14 @@ entry:
%add5 = add i32 %add3, %d %add5 = add i32 %add3, %d
ret i32 %add5 ret i32 %add5
} }
; rdar://9002648
define i64 @test3(i64 %x) nounwind readnone ssp {
entry:
; CHECK: test3:
; CHECK: leaq (%rdi,%rdi), %rax
; CHECK-NOT: addq
; CHECK-NEXT: ret
%0 = shl i64 %x, 1
ret i64 %0
}