diff --git a/docs/LangRef.html b/docs/LangRef.html index 893876620a4..ab9f1caae69 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -1017,8 +1017,9 @@ declare signext i8 @returns_signed_char()
zeroext
This indicates to the code generator that the parameter or return value - should be zero-extended to a 32-bit value by the caller (for a parameter) - or the callee (for a return value).
+ should be zero-extended to the extent required by the target's ABI (which + is usually 32-bits, but is 8-bits for a i1 on x86-64) by the caller (for a + parameter) or the callee (for a return value).
signext
This indicates to the code generator that the parameter or return value diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 618ed548947..f257b035b8f 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -1287,6 +1287,17 @@ public: return false; } + /// getTypeForExtendedInteger - Return the type that should be used to zero or + /// sign extend a zeroext/signext integer argument or return value. + /// FIXME: Most C calling convention requires the return type to be promoted, + /// but this is not true all the time, e.g. i1 on x86-64. It is also not + /// necessary for non-C calling conventions. The frontend should handle this + /// and include all of the necessary information. + virtual MVT + getTypeForExtendedInteger(EVT VT, ISD::NodeType ExtendKind) const { + return MVT::i32; + } + /// LowerOperationWrapper - This callback is invoked by the type legalizer /// to legalize nodes with an illegal operand type but legal result types. /// It replaces the LowerOperation callback in the type Legalizer. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index aa7009ac395..55483188355 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1128,12 +1128,9 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { else if (F->paramHasAttr(0, Attribute::ZExt)) ExtendKind = ISD::ZERO_EXTEND; - // FIXME: C calling convention requires the return type to be promoted - // to at least 32-bit. But this is not necessary for non-C calling - // conventions. The frontend should mark functions whose return values - // require promoting with signext or zeroext attributes. if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { - EVT MinVT = TLI.getRegisterType(*DAG.getContext(), MVT::i32); + MVT ReturnMVT = TLI.getTypeForExtendedInteger(VT, ExtendKind); + EVT MinVT = TLI.getRegisterType(*DAG.getContext(), ReturnMVT); if (VT.bitsLT(MinVT)) VT = MinVT; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 910ed2abd1f..c1aa7200bef 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1448,6 +1448,15 @@ bool X86TargetLowering::isUsedByReturnOnly(SDNode *N) const { return HasRet; } +MVT +X86TargetLowering::getTypeForExtendedInteger(EVT VT, + ISD::NodeType ExtendKind) const { + // TODO: Is this also valid on 32-bit? + if (Subtarget->is64Bit() && VT == MVT::i1 && ExtendKind == ISD::ZERO_EXTEND) + return MVT::i8; + return MVT::i32; +} + /// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. /// diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 551884b18e4..0857c594b4f 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -843,6 +843,9 @@ namespace llvm { virtual bool isUsedByReturnOnly(SDNode *N) const; + virtual MVT + getTypeForExtendedInteger(EVT VT, ISD::NodeType ExtendKind) const; + virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl &Outs, diff --git a/test/CodeGen/X86/bool-zext.ll b/test/CodeGen/X86/bool-zext.ll index 67168d4bf04..d2c30c64f23 100644 --- a/test/CodeGen/X86/bool-zext.ll +++ b/test/CodeGen/X86/bool-zext.ll @@ -6,7 +6,7 @@ define void @bar1(i1 zeroext %v1) nounwind ssp { entry: %conv = zext i1 %v1 to i32 - %call = tail call i32 (...)* @foo(i32 %conv) nounwind + %call = tail call i32 (...)* @foo1(i32 %conv) nounwind ret void } @@ -16,8 +16,20 @@ entry: define void @bar2(i8 zeroext %v1) nounwind ssp { entry: %conv = zext i8 %v1 to i32 - %call = tail call i32 (...)* @foo(i32 %conv) nounwind + %call = tail call i32 (...)* @foo1(i32 %conv) nounwind ret void } -declare i32 @foo(...) +; CHECK: @bar3 +; CHECK: callq +; CHECK-NOT: movzbl +; CHECK-NOT: and +; CHECK: ret +define zeroext i1 @bar3() nounwind ssp { +entry: + %call = call i1 @foo2() nounwind + ret i1 %call +} + +declare i32 @foo1(...) +declare zeroext i1 @foo2()