Implement support for fast isel of calls of i1 arguments, even though they are illegal,
authorChris Lattner <sabre@nondot.org>
Tue, 19 Apr 2011 05:09:50 +0000 (05:09 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 19 Apr 2011 05:09:50 +0000 (05:09 +0000)
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

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

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

index 8c46d7f39e22b7f550e9977ce8af18dda444240a..0be9dfa06c4469f427b16edbf456545ac1e74274 100644 (file)
@@ -78,10 +78,8 @@ private:
 
   bool X86FastEmitLoad(EVT VT, const X86AddressMode &AM, unsigned &RR);
 
-  bool X86FastEmitStore(EVT VT, const Value *Val,
-                        const X86AddressMode &AM);
-  bool X86FastEmitStore(EVT VT, unsigned Val,
-                        const X86AddressMode &AM);
+  bool X86FastEmitStore(EVT VT, const Value *Val, const X86AddressMode &AM);
+  bool X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM);
 
   bool X86FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT,
                          unsigned &ResultReg);
@@ -225,8 +223,7 @@ bool X86FastISel::X86FastEmitLoad(EVT VT, const X86AddressMode &AM,
 /// and a displacement offset, or a GlobalAddress,
 /// i.e. V. Return true if it is possible.
 bool
-X86FastISel::X86FastEmitStore(EVT VT, unsigned Val,
-                              const X86AddressMode &AM) {
+X86FastISel::X86FastEmitStore(EVT VT, unsigned Val, const X86AddressMode &AM) {
   // Get opcode and regclass of the output for the given store instruction.
   unsigned Opc = 0;
   switch (VT.getSimpleVT().SimpleTy) {
@@ -1537,9 +1534,25 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
       }
     }
     
-    unsigned Arg = getRegForValue(ArgVal);
-    if (Arg == 0)
-      return false;
+    unsigned ArgReg;
+    if (ArgVal->getType()->isIntegerTy(1) && isa<TruncInst>(ArgVal) &&
+        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.
     if (CS.paramHasAttr(AttrInd, Attribute::InReg) ||
@@ -1555,7 +1568,7 @@ bool X86FastISel::X86SelectCall(const Instruction *I) {
     unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy);
     Flags.setOrigAlign(OriginalAlignment);
 
-    Args.push_back(Arg);
+    Args.push_back(ArgReg);
     ArgVals.push_back(ArgVal);
     ArgVTs.push_back(ArgVT);
     ArgFlags.push_back(Flags);
index 2e6bafe0720b700bb79d660b64a1984285ce78b5..508af25772ce53b96db04664ea3a415bd93586a1 100644 (file)
@@ -157,3 +157,16 @@ define void @test13() nounwind {
 ; 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
+}
+