diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index f975ad344ad..5f555b2f631 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -35,6 +35,7 @@ namespace { class VISIBILITY_HIDDEN MachineSinking : public MachineFunctionPass { const TargetMachine *TM; const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; MachineFunction *CurMF; // Current MachineFunction MachineRegisterInfo *RegInfo; // Machine register information MachineDominatorTree *DT; // Machine dominator tree @@ -95,6 +96,7 @@ bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { CurMF = &MF; TM = &CurMF->getTarget(); TII = TM->getInstrInfo(); + TRI = TM->getRegisterInfo(); RegInfo = &CurMF->getRegInfo(); DT = &getAnalysis(); @@ -176,8 +178,19 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { if (TargetRegisterInfo::isPhysicalRegister(Reg)) { // If this is a physical register use, we can't move it. If it is a def, // we can move it, but only if the def is dead. - if (MO.isUse() || !MO.isDead()) + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. + if (!RegInfo->def_empty(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) + if (!RegInfo->def_empty(*Alias)) + return false; + } else if (!MO.isDead()) { + // A def that isn't dead. We can't move it. return false; + } } else { // Virtual register uses are always safe to sink. if (MO.isUse()) continue; diff --git a/test/CodeGen/X86/sink.ll b/test/CodeGen/X86/sink.ll new file mode 100644 index 00000000000..1d128b9006f --- /dev/null +++ b/test/CodeGen/X86/sink.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s + +; Currently, floating-point selects are lowered to CFG triangles. +; This means that one side of the select is always unconditionally +; evaluated, however with MachineSink we can sink the other side so +; that it's conditionally evaluated. + +; CHECK: foo: +; CHECK-NEXT: divsd +; CHECK-NEXT: testb $1, %dil +; CHECK-NEXT: jne + +define double @foo(double %x, double %y, i1 %c) nounwind { + %a = fdiv double %x, 3.2 + %b = fdiv double %y, 3.3 + %z = select i1 %c, double %a, double %b + ret double %z +}