aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/llvm/patches/patch-32-llvm-r224884-invalid-reg-replacement.diff164
1 files changed, 164 insertions, 0 deletions
diff --git a/contrib/llvm/patches/patch-32-llvm-r224884-invalid-reg-replacement.diff b/contrib/llvm/patches/patch-32-llvm-r224884-invalid-reg-replacement.diff
new file mode 100644
index 000000000000..dc39636201b2
--- /dev/null
+++ b/contrib/llvm/patches/patch-32-llvm-r224884-invalid-reg-replacement.diff
@@ -0,0 +1,164 @@
+Pull in r224884 from upstream llvm trunk (by Keno Fischer):
+
+ [FastIsel][X86] Fix invalid register replacement for bool args
+
+ Summary:
+ Consider the following IR:
+
+ %3 = load i8* undef
+ %4 = trunc i8 %3 to i1
+ %5 = call %jl_value_t.0* @foo(..., i1 %4, ...)
+ ret %jl_value_t.0* %5
+
+ Bools (that are the result of direct truncs) are lowered as whatever
+ the argument to the trunc was and a "and 1", causing the part of the
+ MBB responsible for this argument to look something like this:
+
+ %vreg8<def,tied1> = AND8ri %vreg7<kill,tied0>, 1, %EFLAGS<imp-def>; GR8:%vreg8,%vreg7
+
+ Later, when the load is lowered, it will insert
+
+ %vreg15<def> = MOV8rm %vreg14, 1, %noreg, 0, %noreg; mem:LD1[undef] GR8:%vreg15 GR64:%vreg14
+
+ but remember to (at the end of isel) replace vreg7 by vreg15. Now for
+ the bug. In fast isel lowering, we mistakenly mark vreg8 as the result
+ of the load instead of the trunc. This adds a fixup to have
+ vreg8 replaced by whatever the result of the load is as well, so
+ we end up with
+
+ %vreg15<def,tied1> = AND8ri %vreg15<kill,tied0>, 1, %EFLAGS<imp-def>; GR8:%vreg15
+
+ which is an SSA violation and causes problems later down the road.
+
+ This fixes PR21557.
+
+ Test Plan: Test test case from PR21557 is added to the test suite.
+
+ Reviewers: ributzka
+
+ Reviewed By: ributzka
+
+ Subscribers: llvm-commits
+
+ Differential Revision: http://reviews.llvm.org/D6245
+
+This fixes a possible assertion failure when compiling toolbox.cxx from
+LibreOffice 4.3.5.
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/278349
+
+Index: lib/Target/X86/X86FastISel.cpp
+===================================================================
+--- lib/Target/X86/X86FastISel.cpp
++++ lib/Target/X86/X86FastISel.cpp
+@@ -2699,6 +2699,9 @@ bool X86FastISel::FastLowerCall(CallLoweringInfo &
+ TM.Options.GuaranteedTailCallOpt))
+ return false;
+
++ SmallVector<MVT, 16> OutVTs;
++ SmallVector<unsigned, 16> ArgRegs;
++
+ // If this is a constant i1/i8/i16 argument, promote to i32 to avoid an extra
+ // instruction. This is safe because it is common to all FastISel supported
+ // calling conventions on x86.
+@@ -2716,28 +2719,34 @@ bool X86FastISel::FastLowerCall(CallLoweringInfo &
+
+ // Passing bools around ends up doing a trunc to i1 and passing it.
+ // Codegen this as an argument + "and 1".
+- if (auto *TI = dyn_cast<TruncInst>(Val)) {
+- if (TI->getType()->isIntegerTy(1) && CLI.CS &&
+- (TI->getParent() == CLI.CS->getInstruction()->getParent()) &&
+- TI->hasOneUse()) {
+- Val = cast<TruncInst>(Val)->getOperand(0);
+- unsigned ResultReg = getRegForValue(Val);
++ MVT VT;
++ auto *TI = dyn_cast<TruncInst>(Val);
++ unsigned ResultReg;
++ if (TI && TI->getType()->isIntegerTy(1) && CLI.CS &&
++ (TI->getParent() == CLI.CS->getInstruction()->getParent()) &&
++ TI->hasOneUse()) {
++ Value *PrevVal = TI->getOperand(0);
++ ResultReg = getRegForValue(PrevVal);
+
+- if (!ResultReg)
+- return false;
++ if (!ResultReg)
++ return false;
+
+- MVT ArgVT;
+- if (!isTypeLegal(Val->getType(), ArgVT))
+- return false;
++ if (!isTypeLegal(PrevVal->getType(), VT))
++ return false;
+
+- ResultReg =
+- FastEmit_ri(ArgVT, ArgVT, ISD::AND, ResultReg, Val->hasOneUse(), 1);
++ ResultReg =
++ FastEmit_ri(VT, VT, ISD::AND, ResultReg, hasTrivialKill(PrevVal), 1);
+
+- if (!ResultReg)
+- return false;
+- UpdateValueMap(Val, ResultReg);
+- }
++ if (!ResultReg)
++ return false;
++ } else {
++ if (!isTypeLegal(Val->getType(), VT))
++ return false;
++ ResultReg = getRegForValue(Val);
+ }
++
++ ArgRegs.push_back(ResultReg);
++ OutVTs.push_back(VT);
+ }
+
+ // Analyze operands of the call, assigning locations to each operand.
+@@ -2749,13 +2758,6 @@ bool X86FastISel::FastLowerCall(CallLoweringInfo &
+ if (IsWin64)
+ CCInfo.AllocateStack(32, 8);
+
+- SmallVector<MVT, 16> OutVTs;
+- for (auto *Val : OutVals) {
+- MVT VT;
+- if (!isTypeLegal(Val->getType(), VT))
+- return false;
+- OutVTs.push_back(VT);
+- }
+ CCInfo.AnalyzeCallOperands(OutVTs, OutFlags, CC_X86);
+
+ // Get a count of how many bytes are to be pushed on the stack.
+@@ -2777,9 +2779,7 @@ bool X86FastISel::FastLowerCall(CallLoweringInfo &
+ if (ArgVT == MVT::x86mmx)
+ return false;
+
+- unsigned ArgReg = getRegForValue(ArgVal);
+- if (!ArgReg)
+- return false;
++ unsigned ArgReg = ArgRegs[VA.getValNo()];
+
+ // Promote the value if needed.
+ switch (VA.getLocInfo()) {
+Index: test/CodeGen/X86/fast-isel-call-bool.ll
+===================================================================
+--- test/CodeGen/X86/fast-isel-call-bool.ll
++++ test/CodeGen/X86/fast-isel-call-bool.ll
+@@ -0,0 +1,19 @@
++; RUN: llc < %s -fast-isel -mcpu=core2 -O1 | FileCheck %s
++; See PR21557
++
++target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
++target triple = "x86_64-apple-darwin14.0.0"
++
++declare i64 @bar(i1)
++
++define i64 @foo(i8* %arg) {
++; CHECK-LABEL: foo:
++top:
++ %0 = load i8* %arg
++; CHECK: movb
++ %1 = trunc i8 %0 to i1
++; CHECK: andb $1,
++ %2 = call i64 @bar(i1 %1)
++; CHECK: callq
++ ret i64 %2
++}