Index: llvm/trunk/lib/Target/X86/X86FastISel.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FastISel.cpp +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp @@ -2672,6 +2672,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. @@ -2689,28 +2692,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); + MVT VT; + auto *TI = dyn_cast(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. @@ -2721,13 +2730,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. @@ -2749,9 +2751,7 @@ 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: llvm/trunk/test/CodeGen/X86/fast-isel-call-bool.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/fast-isel-call-bool.ll +++ llvm/trunk/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 +}