From 19778e7558bc161b87920c5be9cc01bb84a08de2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 25 Sep 2009 22:53:29 +0000 Subject: [PATCH] Fix MachineSink to be able to sink instructions that use physical registers which have no defs anywhere in the function. In particular, this fixes sinking of instructions that reference RIP on x86-64, which is currently being modeled as a register. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82815 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineSink.cpp | 15 ++++++++++++++- test/CodeGen/X86/sink.ll | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 test/CodeGen/X86/sink.ll 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 +}