Handle i1/i8/i16 constant integer arguments to calls by prepromoting them.
authorChris Lattner <sabre@nondot.org>
Tue, 19 Apr 2011 04:42:38 +0000 (04:42 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 19 Apr 2011 04:42:38 +0000 (04:42 +0000)
Before we would bail out on i1 arguments all together, now we just bail on
non-constant ones.  Also, we used to emit extraneous code.  e.g. test12 was:

movb $0, %al
movzbl %al, %edi
callq _test12

and test13 was:
movb $0, %al
xorl %edi, %edi
movb %al, 7(%rsp)
callq _test13f

Now we get:

movl $0, %edi
callq _test12
and:
movl $0, %edi
callq _test13f

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

lib/Target/X86/X86FastISel.cpp
test/CodeGen/X86/fast-isel-x86-64.ll

index 77e67a1740c80d2ac333e33c3590e945c04bd09e..8c46d7f39e22b7f550e9977ce8af18dda444240a 100644 (file)
@@ -1457,8 +1457,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
   // Handle only C and fastcc calling conventions for now.
   ImmutableCallSite CS(CI);
   CallingConv::ID CC = CS.getCallingConv();
-  if (CC != CallingConv::C &&
-      CC != CallingConv::Fast &&
+  if (CC != CallingConv::C && CC != CallingConv::Fast &&
       CC != CallingConv::X86_FastCall)
     return false;
 
@@ -1517,9 +1516,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
   ArgFlags.reserve(CS.arg_size());
   for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
        i != e; ++i) {
-    unsigned Arg = getRegForValue(*i);
-    if (Arg == 0)
-      return false;
+    Value *ArgVal = *i;
     ISD::ArgFlagsTy Flags;
     unsigned AttrInd = i - CS.arg_begin() + 1;
     if (CS.paramHasAttr(AttrInd, Attribute::SExt))
@@ -1527,6 +1524,23 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
     if (CS.paramHasAttr(AttrInd, Attribute::ZExt))
       Flags.setZExt();
 
+    // If this is an 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.
+    if (ConstantInt *CI = dyn_cast<ConstantInt>(ArgVal)) {
+      if (CI->getBitWidth() == 1 || CI->getBitWidth() == 8 ||
+          CI->getBitWidth() == 16) {
+        if (Flags.isSExt())
+          ArgVal = ConstantExpr::getSExt(CI,Type::getInt32Ty(CI->getContext()));
+        else
+          ArgVal = ConstantExpr::getZExt(CI,Type::getInt32Ty(CI->getContext()));
+      }
+    }
+    
+    unsigned Arg = getRegForValue(ArgVal);
+    if (Arg == 0)
+      return false;
+
     // FIXME: Only handle *easy* calls for now.
     if (CS.paramHasAttr(AttrInd, Attribute::InReg) ||
         CS.paramHasAttr(AttrInd, Attribute::StructRet) ||
@@ -1534,7 +1548,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
         CS.paramHasAttr(AttrInd, Attribute::ByVal))
       return false;
 
-    const Type *ArgTy = (*i)->getType();
+    const Type *ArgTy = ArgVal->getType();
     MVT ArgVT;
     if (!isTypeLegal(ArgTy, ArgVT))
       return false;
@@ -1542,7 +1556,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
     Flags.setOrigAlign(OriginalAlignment);
 
     Args.push_back(Arg);
-    ArgVals.push_back(*i);
+    ArgVals.push_back(ArgVal);
     ArgVTs.push_back(ArgVT);
     ArgFlags.push_back(Flags);
   }
@@ -1552,9 +1566,8 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
   CCState CCInfo(CC, false, TM, ArgLocs, I->getParent()->getContext());
 
   // Allocate shadow area for Win64
-  if (Subtarget->isTargetWin64()) {
+  if (Subtarget->isTargetWin64())
     CCInfo.AllocateStack(32, 8);
-  }
 
   CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags, CC_X86);
 
index 0c289e37975392e78773dff8e31d74c14eb96aa0..2e6bafe0720b700bb79d660b64a1984285ce78b5 100644 (file)
@@ -143,6 +143,17 @@ if.end:                                           ; preds = %if.then, %entry
 ; CHECK: test12:
 ; CHECK: testb $1,
 ; CHECK-NEXT: je L
-; CHECK-NEXT: movb     $0, %al
+; CHECK-NEXT: movl $0, %edi
+; CHECK-NEXT: callq
+}
+
+declare void @test13f(i1 %X)
+
+define void @test13() nounwind {
+  call void @test13f(i1 0)
+  ret void
+; CHECK: test13:
+; CHECK: movl $0, %edi
+; CHECK-NEXT: callq
 }