The x86-64 ABI says that a bool is only guaranteed to be sign-extended to a byte
authorCameron Zwarich <zwarich@apple.com>
Wed, 16 Mar 2011 22:20:18 +0000 (22:20 +0000)
committerCameron Zwarich <zwarich@apple.com>
Wed, 16 Mar 2011 22:20:18 +0000 (22:20 +0000)
rather than an int. Thankfully, this only causes LLVM to miss optimizations, not
generate incorrect code.

This just fixes the zext at the return. We still insert an i32 ZextAssert when
reading a function's arguments, but it is followed by a truncate and another i8
ZextAssert so it is not optimized.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127766 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.html
include/llvm/Target/TargetLowering.h
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/bool-zext.ll

index 893876620a46a0f98d9a1927c06d3a2b70e383cf..ab9f1caae69638b0f99af0ed75ce51126583d11e 100644 (file)
@@ -1017,8 +1017,9 @@ declare signext i8 @returns_signed_char()
 <dl>
   <dt><tt><b>zeroext</b></tt></dt>
   <dd>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).</dd>
+      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).</dd>
 
   <dt><tt><b>signext</b></tt></dt>
   <dd>This indicates to the code generator that the parameter or return value
index 618ed5489472c192949007ea8ddfefba523e3db3..f257b035b8f5c4e5ce40638ac6866b839d64cb22 100644 (file)
@@ -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.
index aa7009ac39529d7f0dcc11bf953cc34a6825be7a..5548318835567012f4e1cc528d8676f5c4bafc60 100644 (file)
@@ -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;
         }
index 910ed2abd1f93f94157c7c5dbd202543a57dc31a..c1aa7200befcb43eec709ce8466cf99749da3651 100644 (file)
@@ -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.
 ///
index 551884b18e425961a8403c5e45e763778d47d3e1..0857c594b4f1318d1fcdc93860a625f74d765dae 100644 (file)
@@ -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<ISD::OutputArg> &Outs,
index 67168d4bf04f2eb7a15a04a3153abc705db183b9..d2c30c64f23737f3ea2d32b58a90fbdca3be5195 100644 (file)
@@ -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()