diff options
author | Chris Lattner <sabre@nondot.org> | 2011-04-19 04:42:38 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2011-04-19 04:42:38 +0000 |
commit | e03b8d31624b415805940500a40195a540ca94be (patch) | |
tree | a00dc6a2ad6e4d5e68acd9e9190a3b7fef15fa51 | |
parent | c76d12180765782d6abd0fdeb359c3fec7983e2c (diff) |
Handle i1/i8/i16 constant integer arguments to calls by prepromoting them.
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
-rw-r--r-- | lib/Target/X86/X86FastISel.cpp | 31 | ||||
-rw-r--r-- | test/CodeGen/X86/fast-isel-x86-64.ll | 13 |
2 files changed, 34 insertions, 10 deletions
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 77e67a1740..8c46d7f39e 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -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); diff --git a/test/CodeGen/X86/fast-isel-x86-64.ll b/test/CodeGen/X86/fast-isel-x86-64.ll index 0c289e3797..2e6bafe072 100644 --- a/test/CodeGen/X86/fast-isel-x86-64.ll +++ b/test/CodeGen/X86/fast-isel-x86-64.ll @@ -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 } |