Fix MachineSink to be able to sink instructions that use physical registers
authorDan Gohman <gohman@apple.com>
Fri, 25 Sep 2009 22:53:29 +0000 (22:53 +0000)
committerDan Gohman <gohman@apple.com>
Fri, 25 Sep 2009 22:53:29 +0000 (22:53 +0000)
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
test/CodeGen/X86/sink.ll [new file with mode: 0644]

index f975ad344ade007da7dc342ae88f0e5903fac10c..5f555b2f631e49bc61c2df1e27cb7b2b84e68138 100644 (file)
@@ -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<MachineDominatorTree>();
 
@@ -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 (file)
index 0000000..1d128b9
--- /dev/null
@@ -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
+}