Fix PR5614: parts of a physical register def may be killed the rest.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 1 Dec 2009 00:44:45 +0000 (00:44 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 1 Dec 2009 00:44:45 +0000 (00:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90180 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/LiveVariables.h
lib/CodeGen/LiveVariables.cpp
test/CodeGen/ARM/2009-11-30-LiveVariablesBug.ll [new file with mode: 0644]

index a37abd4645529a0ea328117fd303a1669efa18be..39a4b89f54db082725292329571481e1794ab05b 100644 (file)
@@ -163,8 +163,13 @@ private:   // Intermediate data structures
                         SmallVector<unsigned, 4> &Defs);
   void UpdatePhysRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs);
 
-  /// FindLastPartialDef - Return the last partial def of the specified register.
-  /// Also returns the sub-registers that're defined by the instruction.
+  /// FindLastRefOrPartRef - Return the last reference or partial reference of
+  /// the specified register.
+  MachineInstr *FindLastRefOrPartRef(unsigned Reg);
+
+  /// FindLastPartialDef - Return the last partial def of the specified
+  /// register. Also returns the sub-registers that're defined by the
+  /// instruction.
   MachineInstr *FindLastPartialDef(unsigned Reg,
                                    SmallSet<unsigned,4> &PartDefRegs);
 
index bfc2d08528a197ad1666797a45aed282360db50b..68f80acf1562f01e76eebc10eb97113419442adc 100644 (file)
@@ -279,6 +279,43 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) {
     PhysRegUse[SubReg] =  MI;
 }
 
+/// FindLastRefOrPartRef - Return the last reference or partial reference of
+/// the specified register.
+MachineInstr *LiveVariables::FindLastRefOrPartRef(unsigned Reg) {
+  MachineInstr *LastDef = PhysRegDef[Reg];
+  MachineInstr *LastUse = PhysRegUse[Reg];
+  if (!LastDef && !LastUse)
+    return false;
+
+  MachineInstr *LastRefOrPartRef = LastUse ? LastUse : LastDef;
+  unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef];
+  MachineInstr *LastPartDef = 0;
+  unsigned LastPartDefDist = 0;
+  for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
+       unsigned SubReg = *SubRegs; ++SubRegs) {
+    MachineInstr *Def = PhysRegDef[SubReg];
+    if (Def && Def != LastDef) {
+      // There was a def of this sub-register in between. This is a partial
+      // def, keep track of the last one.
+      unsigned Dist = DistanceMap[Def];
+      if (Dist > LastPartDefDist) {
+        LastPartDefDist = Dist;
+        LastPartDef = Def;
+      }
+      continue;
+    }
+    if (MachineInstr *Use = PhysRegUse[SubReg]) {
+      unsigned Dist = DistanceMap[Use];
+      if (Dist > LastRefOrPartRefDist) {
+        LastRefOrPartRefDist = Dist;
+        LastRefOrPartRef = Use;
+      }
+    }
+  }
+
+  return LastRefOrPartRef;
+}
+
 bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
   MachineInstr *LastDef = PhysRegDef[Reg];
   MachineInstr *LastUse = PhysRegUse[Reg];
@@ -373,7 +410,16 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
       if (NeedDef)
         PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg,
                                                  true/*IsDef*/, true/*IsImp*/));
-      LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true);
+      MachineInstr *LastSubRef = FindLastRefOrPartRef(SubReg);
+      if (LastSubRef)
+        LastSubRef->addRegisterKilled(SubReg, TRI, true);
+      else {
+        LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true);
+        PhysRegUse[SubReg] = LastRefOrPartRef;
+        for (const unsigned *SSRegs = TRI->getSubRegisters(SubReg);
+             unsigned SSReg = *SSRegs; ++SSRegs)
+          PhysRegUse[SSReg] = LastRefOrPartRef;
+      }
       for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
         PartUses.erase(*SS);
     }
diff --git a/test/CodeGen/ARM/2009-11-30-LiveVariablesBug.ll b/test/CodeGen/ARM/2009-11-30-LiveVariablesBug.ll
new file mode 100644 (file)
index 0000000..efe74cf
--- /dev/null
@@ -0,0 +1,41 @@
+; RUN: llc -mtriple=armv7-eabi -mcpu=cortex-a8 < %s
+; PR5614
+
+%"als" = type { i32 (...)** }
+%"av" = type { %"als" }
+%"c" = type { %"lsm", %"Vec3", %"av"*, float, i8, float, %"lsm", i8, %"Vec3", %"Vec3", %"Vec3", float, float, float, %"Vec3", %"Vec3" }
+%"lsm" = type { %"als", %"Vec3", %"Vec3", %"Vec3", %"Vec3" }
+%"Vec3" = type { float, float, float }
+
+define arm_aapcs_vfpcc void @foo(%"c"* %this, %"Vec3"* nocapture %adjustment) {
+entry:
+  switch i32 undef, label %return [
+    i32 1, label %bb
+    i32 2, label %bb72
+    i32 3, label %bb31
+    i32 4, label %bb79
+    i32 5, label %bb104
+  ]
+
+bb:                                               ; preds = %entry
+  ret void
+
+bb31:                                             ; preds = %entry
+  %0 = call arm_aapcs_vfpcc  %"Vec3" undef(%"lsm"* undef) ; <%"Vec3"> [#uses=1]
+  %mrv_gr69 = extractvalue %"Vec3" %0, 1 ; <float> [#uses=1]
+  %1 = fsub float %mrv_gr69, undef                ; <float> [#uses=1]
+  store float %1, float* undef, align 4
+  ret void
+
+bb72:                                             ; preds = %entry
+  ret void
+
+bb79:                                             ; preds = %entry
+  ret void
+
+bb104:                                            ; preds = %entry
+  ret void
+
+return:                                           ; preds = %entry
+  ret void
+}