Fix PR3391 and PR3864. Reg allocator infinite looping.
authorEvan Cheng <evan.cheng@apple.com>
Mon, 23 Mar 2009 18:24:37 +0000 (18:24 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Mon, 23 Mar 2009 18:24:37 +0000 (18:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67544 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/LiveIntervalAnalysis.h
lib/CodeGen/LiveIntervalAnalysis.cpp
lib/CodeGen/RegAllocLinearScan.cpp
test/CodeGen/X86/inline-asm-out-regs.ll [new file with mode: 0644]

index aec72858c8326d5aa6b2b87c29bb4944e8e90c38..33837a2ca23192e870c6db41b6cc5c4142deed87 100644 (file)
@@ -367,8 +367,9 @@ namespace llvm {
                               VirtRegMap &vrm, float& SSWeight);
 
     /// spillPhysRegAroundRegDefsUses - Spill the specified physical register
-    /// around all defs and uses of the specified interval.
-    void spillPhysRegAroundRegDefsUses(const LiveInterval &li,
+    /// around all defs and uses of the specified interval. Return true if it
+    /// was able to cut its interval.
+    bool spillPhysRegAroundRegDefsUses(const LiveInterval &li,
                                        unsigned PhysReg, VirtRegMap &vrm);
 
     /// isReMaterializable - Returns true if every definition of MI of every
index b5c21952fa3da858ffd0a50714b8df3b8aeb156b..cd6f81c6eb232e8a8a785ba3a1f1f36a98c606ba 100644 (file)
@@ -2214,8 +2214,9 @@ unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li,
 }
 
 /// spillPhysRegAroundRegDefsUses - Spill the specified physical register
-/// around all defs and uses of the specified interval.
-void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
+/// around all defs and uses of the specified interval. Return true if it
+/// was able to cut its interval.
+bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
                                             unsigned PhysReg, VirtRegMap &vrm) {
   unsigned SpillReg = getRepresentativeReg(PhysReg);
 
@@ -2226,6 +2227,7 @@ void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
     assert(*AS == SpillReg || !allocatableRegs_[*AS] ||
            tri_->isSuperRegister(*AS, SpillReg));
 
+  bool Cut = false;
   LiveInterval &pli = getInterval(SpillReg);
   SmallPtrSet<MachineInstr*, 8> SeenMIs;
   for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg),
@@ -2240,9 +2242,10 @@ void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
       vrm.addEmergencySpill(SpillReg, MI);
       unsigned StartIdx = getLoadIndex(Index);
       unsigned EndIdx = getStoreIndex(Index)+1;
-      if (pli.isInOneLiveRange(StartIdx, EndIdx))
+      if (pli.isInOneLiveRange(StartIdx, EndIdx)) {
         pli.removeRange(StartIdx, EndIdx);
-      else {
+        Cut = true;
+      } else {
         cerr << "Ran out of registers during register allocation!\n";
         if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {
           cerr << "Please check your inline asm statement for invalid "
@@ -2260,6 +2263,7 @@ void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
       }
     }
   }
+  return Cut;
 }
 
 LiveRange LiveIntervals::addLiveRangeToEndOfBlock(unsigned reg,
index e8296a74775c88faa15cc8ec8214e260e2f8c741..912135a57f6cbedc1188ea0e0a7dac8cda111ffd 100644 (file)
@@ -869,8 +869,12 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
     if (cur->weight == HUGE_VALF ||
         li_->getApproximateInstructionCount(*cur) == 0) {
       // Spill a physical register around defs and uses.
-      li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_);
-      assignRegOrStackSlotAtInterval(cur);
+      if (li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_))
+        assignRegOrStackSlotAtInterval(cur);
+      else {
+        cerr << "Ran out of registers during register allocation!\n";
+        exit(1);
+      }
       return;
     }
   }
diff --git a/test/CodeGen/X86/inline-asm-out-regs.ll b/test/CodeGen/X86/inline-asm-out-regs.ll
new file mode 100644 (file)
index 0000000..3a84bad
--- /dev/null
@@ -0,0 +1,42 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-unknown-linux-gnu
+; XFAIL: *
+; Expected to run out of registers during allocation.
+; PR3391
+
+@pci_indirect = external global { }             ; <{ }*> [#uses=1]
+@pcibios_last_bus = external global i32         ; <i32*> [#uses=2]
+
+define void @pci_pcbios_init() nounwind section ".init.text" {
+entry:
+        br label %bb1.i
+
+bb1.i:          ; preds = %bb6.i.i, %bb1.i, %entry
+        %0 = load i32* null, align 8            ; <i32> [#uses=1]
+        %1 = icmp ugt i32 %0, 1048575           ; <i1> [#uses=1]
+        br i1 %1, label %bb2.i, label %bb1.i
+
+bb2.i:          ; preds = %bb1.i
+        %asmtmp.i.i = tail call { i32, i32, i32, i32 } asm "lcall *(%edi); cld\0A\09jc 1f\0A\09xor %ah, %ah\0A1:", "={dx},={ax},={bx},={cx},1,{di},~{dirflag},~{fpsr},~{flags},~{memory}"(i32 45313, { }* @pci_indirect) nounwind             ; <{ i32, i32, i32, i32 }> [#uses=2]
+        %asmresult2.i.i = extractvalue { i32, i32, i32, i32 } %asmtmp.i.i, 1   
+        ; <i32> [#uses=1]
+        %2 = lshr i32 %asmresult2.i.i, 8                ; <i32> [#uses=1]
+        %3 = trunc i32 %2 to i8         ; <i8> [#uses=1]
+        %4 = load i32* @pcibios_last_bus, align 4               ; <i32> [#uses=1]
+        %5 = icmp slt i32 %4, 0         ; <i1> [#uses=1]
+        br i1 %5, label %bb5.i.i, label %bb6.i.i
+
+bb5.i.i:                ; preds = %bb2.i
+        %asmresult4.i.i = extractvalue { i32, i32, i32, i32 } %asmtmp.i.i, 3   
+        ; <i32> [#uses=1]
+        %6 = and i32 %asmresult4.i.i, 255               ; <i32> [#uses=1]
+        store i32 %6, i32* @pcibios_last_bus, align 4
+        br label %bb6.i.i
+
+bb6.i.i:                ; preds = %bb5.i.i, %bb2.i
+        %7 = icmp eq i8 %3, 0           ; <i1> [#uses=1]
+        %or.cond.i.i = and i1 %7, false         ; <i1> [#uses=1]
+        br i1 %or.cond.i.i, label %bb1.i, label %bb8.i.i
+
+bb8.i.i:                ; preds = %bb6.i.i
+        unreachable
+}