Index: lib/Target/X86/X86FastISel.cpp =================================================================== --- lib/Target/X86/X86FastISel.cpp +++ lib/Target/X86/X86FastISel.cpp @@ -2674,6 +2674,9 @@ TM.Options.GuaranteedTailCallOpt)) return false; + SmallVector OutVTs; + SmallVector 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. @@ -2691,28 +2694,34 @@ // 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(Val)) { - if (TI->getType()->isIntegerTy(1) && CLI.CS && - (TI->getParent() == CLI.CS->getInstruction()->getParent()) && - TI->hasOneUse()) { - Val = cast(Val)->getOperand(0); - unsigned ResultReg = getRegForValue(Val); - - if (!ResultReg) - return false; + MVT VT; + auto *TI = dyn_cast(Val); + if (TI && TI->getType()->isIntegerTy(1) && CLI.CS && + (TI->getParent() == CLI.CS->getInstruction()->getParent()) && + TI->hasOneUse()) { + Value *PrevVal = TI->getOperand(0); + unsigned ResultReg = getRegForValue(PrevVal); + + 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; + + ArgRegs.push_back(ResultReg); + } else { + if (!isTypeLegal(Val->getType(), VT)) + return false; + ArgRegs.push_back(getRegForValue(Val)); } + + OutVTs.push_back(VT); } // Analyze operands of the call, assigning locations to each operand. @@ -2723,13 +2732,6 @@ if (IsWin64) CCInfo.AllocateStack(32, 8); - SmallVector 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. @@ -2751,7 +2753,7 @@ if (ArgVT == MVT::x86mmx) return false; - unsigned ArgReg = getRegForValue(ArgVal); + unsigned ArgReg = ArgRegs[VA.getValNo()]; if (!ArgReg) return false; Index: test/CodeGen/X86/fast-isel-call-bool.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/fast-isel-call-bool.ll @@ -0,0 +1,20 @@ +; 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" + +; Function Attrs: sspreq +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 +}