summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp4
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp12
-rw-r--r--test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll38
3 files changed, 50 insertions, 4 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 24adf364e7..3c1d4b3ccd 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -374,8 +374,6 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
// Value#0 is now defined by the 2-addr instruction.
OldValNo->def = RedefIndex;
OldValNo->setCopy(0);
- if (MO.isEarlyClobber())
- OldValNo->setHasRedefByEC(true);
// Add the new live interval which replaces the range for the input copy.
LiveRange LR(DefIndex, RedefIndex, ValNo);
@@ -513,8 +511,6 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
if (mi->isRegTiedToUseOperand(DefIdx)) {
// Two-address instruction.
end = baseIndex.getDefIndex();
- assert(!mi->getOperand(DefIdx).isEarlyClobber() &&
- "Two address instruction is an early clobber?");
} else {
// Another instruction redefines the register before it is ever read.
// Then the register is essentially dead at the instruction that defines
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index 58763718f9..cb2d22b6c9 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -1938,6 +1938,10 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){
if (Overlaps) {
// If we haven't already recorded that this value # is safe, check it.
if (!InVector(LHSIt->valno, EliminatedLHSVals)) {
+ // If it's re-defined by an early clobber somewhere in the live range,
+ // then conservatively abort coalescing.
+ if (LHSIt->valno->hasRedefByEC())
+ return false;
// Copy from the RHS?
if (!RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg))
return false; // Nope, bail out.
@@ -1977,6 +1981,10 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){
// if coalescing succeeds. Just skip the liverange.
if (++LHSIt == LHSEnd) break;
} else {
+ // If it's re-defined by an early clobber somewhere in the live range,
+ // then conservatively abort coalescing.
+ if (LHSIt->valno->hasRedefByEC())
+ return false;
// Otherwise, if this is a copy from the RHS, mark it as being merged
// in.
if (RangeIsDefinedByCopyFromReg(LHS, LHSIt, RHS.reg)) {
@@ -2316,6 +2324,10 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
if (LHSValNoAssignments[I->valno->id] !=
RHSValNoAssignments[J->valno->id])
return false;
+ // If it's re-defined by an early clobber somewhere in the live range,
+ // then conservatively abort coalescing.
+ if (NewVNInfo[LHSValNoAssignments[I->valno->id]]->hasRedefByEC())
+ return false;
}
if (I->end < J->end) {
diff --git a/test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll b/test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll
new file mode 100644
index 0000000000..1e7a418d1d
--- /dev/null
+++ b/test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll
@@ -0,0 +1,38 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
+; pr5391
+
+define void @t() nounwind ssp {
+entry:
+; CHECK: t:
+; CHECK: movl %ecx, %eax
+; CHECK: %eax = foo (%eax, %ecx)
+ %b = alloca i32 ; <i32*> [#uses=2]
+ %a = alloca i32 ; <i32*> [#uses=1]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ %0 = load i32* %b, align 4 ; <i32> [#uses=1]
+ %1 = load i32* %b, align 4 ; <i32> [#uses=1]
+ %asmtmp = call i32 asm "$0 = foo ($1, $2)", "=&{ax},%0,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1) nounwind ; <i32> [#uses=1]
+ store i32 %asmtmp, i32* %a
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+define void @t2() nounwind ssp {
+entry:
+; CHECK: t2:
+; CHECK: movl %eax, %ecx
+; CHECK: %ecx = foo (%ecx, %eax)
+ %b = alloca i32 ; <i32*> [#uses=2]
+ %a = alloca i32 ; <i32*> [#uses=1]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ %0 = load i32* %b, align 4 ; <i32> [#uses=1]
+ %1 = load i32* %b, align 4 ; <i32> [#uses=1]
+ %asmtmp = call i32 asm "$0 = foo ($1, $2)", "=&r,%0,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1) nounwind ; <i32> [#uses=1]
+ store i32 %asmtmp, i32* %a
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}