aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h5
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp12
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp8
-rw-r--r--test/CodeGen/X86/inline-asm-out-regs.ll42
4 files changed, 59 insertions, 8 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index aec7285..33837a2 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -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
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index b5c2195..cd6f81c 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -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,
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index e8296a7..912135a 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -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
index 0000000..3a84bad
--- /dev/null
+++ b/test/CodeGen/X86/inline-asm-out-regs.ll
@@ -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
+}