Implement support for fast isel of calls of i1 arguments, even though they are illegal,

when they are a truncate from something else.  This eliminates fully half of all the 
fastisel rejections on a test c++ file I'm working with, which should make a substantial
improvement for -O0 compile of c++ code.

This fixed rdar://9297003 - fast isel bails out on all functions taking bools

llvm-svn: 129752
This commit is contained in:
Chris Lattner 2011-04-19 05:09:50 +00:00
parent d7f7c93914
commit 5f4b783426
2 changed files with 36 additions and 10 deletions

View File

@ -78,10 +78,8 @@ private:
bool X86FastEmitLoad(EVT VT, const X86AddressMode &AM, unsigned &RR); bool X86FastEmitLoad(EVT VT, const X86AddressMode &AM, unsigned &RR);
bool X86FastEmitStore(EVT VT, const Value *Val, bool X86FastEmitStore(EVT VT, const Value *Val, const X86AddressMode &AM);
const X86AddressMode &AM); bool X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM);
bool X86FastEmitStore(EVT VT, unsigned Val,
const X86AddressMode &AM);
bool X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT, bool X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT,
unsigned &ResultReg); unsigned &ResultReg);
@ -225,8 +223,7 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM,
/// and a displacement offset, or a GlobalAddress, /// and a displacement offset, or a GlobalAddress,
/// i.e. V. Return true if it is possible. /// i.e. V. Return true if it is possible.
bool bool
X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM) {
const X86AddressMode &AM) {
// Get opcode and regclass of the output for the given store instruction. // Get opcode and regclass of the output for the given store instruction.
unsigned Opc = 0; unsigned Opc = 0;
switch (VT.getSimpleVT().SimpleTy) { switch (VT.getSimpleVT().SimpleTy) {
@ -1537,9 +1534,25 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
} }
} }
unsigned Arg = getRegForValue(ArgVal); unsigned ArgReg;
if (Arg == 0) if (ArgVal->getType()->isIntegerTy(1) && isa<TruncInst>(ArgVal) &&
return false; cast<TruncInst>(ArgVal)->getParent() == I->getParent() &&
ArgVal->hasOneUse()) {
// Passing bools around ends up doing a trunc to i1 and passing it.
// Codegen this as an argument + "and 1".
ArgVal = cast<TruncInst>(ArgVal)->getOperand(0);
ArgReg = getRegForValue(ArgVal);
if (ArgReg == 0) return false;
MVT ArgVT;
if (!isTypeLegal(ArgVal->getType(), ArgVT)) return false;
ArgReg = FastEmit_ri(ArgVT, ArgVT, ISD::AND, ArgReg,
ArgVal->hasOneUse(), 1);
} else {
ArgReg = getRegForValue(ArgVal);
if (ArgReg == 0) return false;
}
// FIXME: Only handle *easy* calls for now. // FIXME: Only handle *easy* calls for now.
if (CS.paramHasAttr(AttrInd, Attribute::InReg) || if (CS.paramHasAttr(AttrInd, Attribute::InReg) ||
@ -1555,7 +1568,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy); unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy);
Flags.setOrigAlign(OriginalAlignment); Flags.setOrigAlign(OriginalAlignment);
Args.push_back(Arg); Args.push_back(ArgReg);
ArgVals.push_back(ArgVal); ArgVals.push_back(ArgVal);
ArgVTs.push_back(ArgVT); ArgVTs.push_back(ArgVT);
ArgFlags.push_back(Flags); ArgFlags.push_back(Flags);

View File

@ -157,3 +157,16 @@ define void @test13() nounwind {
; CHECK-NEXT: callq ; CHECK-NEXT: callq
} }
; rdar://9297003 - fast isel bails out on all functions taking bools
define void @test14(i8 %tmp) nounwind ssp noredzone {
entry:
%tobool = trunc i8 %tmp to i1
call void @test13f(i1 zeroext %tobool) noredzone
ret void
; CHECK: test14:
; CHECK: andb $1,
; CHECK: callq
}