Besides removing phi cycles that reduce to a single value, also remove dead

phi cycles.  Adjust a few tests to keep dead instructions from being optimized
away.  This (together with my previous change for phi cycles) fixes Apple
radar 7627077.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96057 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bob Wilson 2010-02-13 00:31:44 +00:00
parent 39125d8ef9
commit bf9b221c00
6 changed files with 114 additions and 25 deletions

View File

@ -295,6 +295,10 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
printAndVerify(PM, "After Instruction Selection",
/* allowDoubleDefs= */ true);
// Optimize PHIs before DCE: removing dead PHI cycles may make more
// instructions dead.
if (OptLevel != CodeGenOpt::None)
PM.add(createOptimizePHIsPass());
// Delete dead machine instructions regardless of optimization level.
PM.add(createDeadMachineInstructionElimPass());
@ -303,7 +307,6 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM,
if (OptLevel != CodeGenOpt::None) {
PM.add(createOptimizeExtsPass());
PM.add(createOptimizePHIsPass());
if (!DisableMachineLICM)
PM.add(createMachineLICMPass());
if (!DisableMachineSink)

View File

@ -19,11 +19,12 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Function.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
namespace {
class OptimizePHIs : public MachineFunctionPass {
@ -42,9 +43,13 @@ namespace {
}
private:
bool IsSingleValuePHICycle(const MachineInstr *MI, unsigned &SingleValReg,
SmallSet<unsigned, 16> &RegsInCycle);
bool ReplacePHICycles(MachineBasicBlock &MBB);
typedef SmallPtrSet<MachineInstr*, 16> InstrSet;
typedef SmallPtrSetIterator<MachineInstr*> InstrSetIterator;
bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg,
InstrSet &PHIsInCycle);
bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle);
bool OptimizeBB(MachineBasicBlock &MBB);
};
}
@ -58,12 +63,13 @@ bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
MRI = &Fn.getRegInfo();
TII = Fn.getTarget().getInstrInfo();
// Find PHI cycles that can be replaced by a single value. InstCombine
// does this, but DAG legalization may introduce new opportunities, e.g.,
// when i64 values are split up for 32-bit targets.
// Find dead PHI cycles and PHI cycles that can be replaced by a single
// value. InstCombine does these optimizations, but DAG legalization may
// introduce new opportunities, e.g., when i64 values are split up for
// 32-bit targets.
bool Changed = false;
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
Changed |= ReplacePHICycles(*I);
Changed |= OptimizeBB(*I);
return Changed;
}
@ -71,20 +77,20 @@ bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
/// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands
/// are copies of SingleValReg, possibly via copies through other PHIs. If
/// SingleValReg is zero on entry, it is set to the register with the single
/// non-copy value. RegsInCycle is a set used to keep track of the PHIs that
/// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that
/// have been scanned.
bool OptimizePHIs::IsSingleValuePHICycle(const MachineInstr *MI,
bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI,
unsigned &SingleValReg,
SmallSet<unsigned, 16> &RegsInCycle) {
InstrSet &PHIsInCycle) {
assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction");
unsigned DstReg = MI->getOperand(0).getReg();
// See if we already saw this register.
if (!RegsInCycle.insert(DstReg))
if (!PHIsInCycle.insert(MI))
return true;
// Don't scan crazily complex things.
if (RegsInCycle.size() == 16)
if (PHIsInCycle.size() == 16)
return false;
// Scan the PHI operands.
@ -92,7 +98,7 @@ bool OptimizePHIs::IsSingleValuePHICycle(const MachineInstr *MI,
unsigned SrcReg = MI->getOperand(i).getReg();
if (SrcReg == DstReg)
continue;
const MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
// Skip over register-to-register moves.
unsigned MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx;
@ -105,7 +111,7 @@ bool OptimizePHIs::IsSingleValuePHICycle(const MachineInstr *MI,
return false;
if (SrcMI->isPHI()) {
if (!IsSingleValuePHICycle(SrcMI, SingleValReg, RegsInCycle))
if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle))
return false;
} else {
// Fail if there is more than one non-phi/non-move register.
@ -117,9 +123,35 @@ bool OptimizePHIs::IsSingleValuePHICycle(const MachineInstr *MI,
return true;
}
/// ReplacePHICycles - Find PHI cycles that can be replaced by a single
/// value and remove them.
bool OptimizePHIs::ReplacePHICycles(MachineBasicBlock &MBB) {
/// IsDeadPHICycle - Check if the register defined by a PHI is only used by
/// other PHIs in a cycle.
bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) {
assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction");
unsigned DstReg = MI->getOperand(0).getReg();
assert(TargetRegisterInfo::isVirtualRegister(DstReg) &&
"PHI destination is not a virtual register");
// See if we already saw this register.
if (!PHIsInCycle.insert(MI))
return true;
// Don't scan crazily complex things.
if (PHIsInCycle.size() == 16)
return false;
for (MachineRegisterInfo::use_iterator I = MRI->use_begin(DstReg),
E = MRI->use_end(); I != E; ++I) {
MachineInstr *UseMI = &*I;
if (!UseMI->isPHI() || !IsDeadPHICycle(UseMI, PHIsInCycle))
return false;
}
return true;
}
/// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by
/// a single value.
bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineBasicBlock::iterator
MII = MBB.begin(), E = MBB.end(); MII != E; ) {
@ -127,14 +159,30 @@ bool OptimizePHIs::ReplacePHICycles(MachineBasicBlock &MBB) {
if (!MI->isPHI())
break;
// Check for single-value PHI cycles.
unsigned SingleValReg = 0;
SmallSet<unsigned, 16> RegsInCycle;
if (IsSingleValuePHICycle(MI, SingleValReg, RegsInCycle) &&
InstrSet PHIsInCycle;
if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) &&
SingleValReg != 0) {
MRI->replaceRegWith(MI->getOperand(0).getReg(), SingleValReg);
MI->eraseFromParent();
++NumPHICycles;
Changed = true;
continue;
}
// Check for dead PHI cycles.
PHIsInCycle.clear();
if (IsDeadPHICycle(MI, PHIsInCycle)) {
for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end();
PI != PE; ++PI) {
MachineInstr *PhiMI = *PI;
if (&*MII == PhiMI)
++MII;
PhiMI->eraseFromParent();
}
++NumDeadPHICycles;
Changed = true;
}
}
return Changed;

View File

@ -29,6 +29,44 @@ return: ; preds = %bb, %entry
ret i32 undef
}
define arm_apcscc i32 @test_dead_cycle(i32 %n) nounwind {
; CHECK: test_dead_cycle:
; CHECK: blx
; CHECK-NOT: mov
; CHECK: blx
entry:
%0 = icmp eq i32 %n, 1 ; <i1> [#uses=1]
br i1 %0, label %return, label %bb.nph
bb.nph: ; preds = %entry
%tmp = add i32 %n, -1 ; <i32> [#uses=2]
br label %bb
bb: ; preds = %bb.nph, %bb2
%indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb2 ] ; <i32> [#uses=2]
%u.17 = phi i64 [ undef, %bb.nph ], [ %u.0, %bb2 ] ; <i64> [#uses=2]
%tmp9 = sub i32 %tmp, %indvar ; <i32> [#uses=1]
%1 = icmp sgt i32 %tmp9, 1 ; <i1> [#uses=1]
br i1 %1, label %bb1, label %bb2
bb1: ; preds = %bb
%2 = tail call arm_apcscc i32 @f() nounwind ; <i32> [#uses=1]
%tmp6 = zext i32 %2 to i64 ; <i64> [#uses=1]
%mask = and i64 %u.17, -4294967296 ; <i64> [#uses=1]
%ins = or i64 %tmp6, %mask ; <i64> [#uses=1]
tail call arm_apcscc void @g(i64 %ins) nounwind
br label %bb2
bb2: ; preds = %bb1, %bb
%u.0 = phi i64 [ %ins, %bb1 ], [ %u.17, %bb ] ; <i64> [#uses=2]
%indvar.next = add i32 %indvar, 1 ; <i32> [#uses=2]
%exitcond = icmp eq i32 %indvar.next, %tmp ; <i1> [#uses=1]
br i1 %exitcond, label %return, label %bb
return: ; preds = %bb2, %entry
ret i32 undef
}
declare arm_apcscc i32 @f()
declare arm_apcscc void @g(i64)

View File

@ -12,8 +12,8 @@ declare <4 x float> @llvm.arm.neon.vld1.v4f32(i8*) nounwind readonly
define arm_apcscc void @aaa(%quuz* %this, i8* %block) {
; CHECK: aaa:
; CHECK: bic r4, r4, #15
; CHECK: vst1.64 {{.*}}[r{{.*}}, :128]
; CHECK: vld1.64 {{.*}}[r{{.*}}, :128]
; CHECK: vst1.64 {{.*}}[{{.*}}, :128]
; CHECK: vld1.64 {{.*}}[{{.*}}, :128]
entry:
%0 = call <4 x float> @llvm.arm.neon.vld1.v4f32(i8* undef) nounwind ; <<4 x float>> [#uses=1]
store float 6.300000e+01, float* undef, align 4

View File

@ -20,7 +20,7 @@ bb: ; preds = %bb9.i, %entry
bb9.i: ; preds = %bb
%2 = fsub double %.rle4, %0 ; <double> [#uses=0]
%3 = tail call double @asin(double 0.000000e+00) nounwind readonly ; <double> [#uses=0]
%3 = tail call double @asin(double %.rle4) nounwind readonly ; <double> [#uses=0]
%4 = fmul double 0.000000e+00, %0 ; <double> [#uses=1]
%5 = tail call double @tan(double 0.000000e+00) nounwind readonly ; <double> [#uses=0]
%6 = fmul double %4, 0.000000e+00 ; <double> [#uses=1]

View File

@ -22,7 +22,7 @@ bb: ; preds = %bb9.i, %entry
bb9.i: ; preds = %bb
%2 = fsub double %.rle4, %0 ; <double> [#uses=0]
%3 = tail call double @asin(double 0.000000e+00) nounwind readonly ; <double> [#uses=0]
%3 = tail call double @asin(double %.rle4) nounwind readonly ; <double> [#uses=0]
%4 = tail call double @sin(double 0.000000e+00) nounwind readonly ; <double> [#uses=1]
%5 = fmul double %4, %0 ; <double> [#uses=1]
%6 = tail call double @tan(double 0.000000e+00) nounwind readonly ; <double> [#uses=0]