[llvm-branch-commits] [llvm-branch] r113668 - in /llvm/branches/ggreif/waymark-64: lib/Transforms/Scalar/CodeGenPrepare.cpp test/CodeGen/X86/switch-and.ll

Gabor Greif ggreif at gmail.com
Fri Sep 10 17:01:51 PDT 2010


Author: ggreif
Date: Fri Sep 10 19:01:51 2010
New Revision: 113668

URL: http://llvm.org/viewvc/llvm-project?rev=113668&view=rev
Log:
half-baked solution for the 'je after and' optimization:

        andl    , %ebx
        je      .LBB0_5

because the peephole optimizer recognizes the test immediately after the and.

The transformation helps the peephole to hoist out the zero-branch from a switch
immediately behind the (assembly) and.

Added:
    llvm/branches/ggreif/waymark-64/test/CodeGen/X86/switch-and.ll
Modified:
    llvm/branches/ggreif/waymark-64/lib/Transforms/Scalar/CodeGenPrepare.cpp

Modified: llvm/branches/ggreif/waymark-64/lib/Transforms/Scalar/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/ggreif/waymark-64/lib/Transforms/Scalar/CodeGenPrepare.cpp?rev=113668&r1=113667&r2=113668&view=diff
==============================================================================
--- llvm/branches/ggreif/waymark-64/lib/Transforms/Scalar/CodeGenPrepare.cpp (original)
+++ llvm/branches/ggreif/waymark-64/lib/Transforms/Scalar/CodeGenPrepare.cpp Fri Sep 10 19:01:51 2010
@@ -884,6 +884,55 @@
   return MadeChange;
 }
 
+
+static bool OptimizeSwitchInst(SwitchInst *I, Value *condition) {
+  BasicBlock *Old = I->getParent();
+
+  if (Instruction *C = dyn_cast<TruncInst>(condition)) {
+    if (Old != C->getParent())
+      return false;
+  }
+  else
+    return false;
+
+  if (condition != --BasicBlock::iterator(I))
+    return false;
+
+  static bool once(true);
+  const Type *Ty = condition->getType();
+
+
+
+  if (TruncInst *T = dyn_cast<TruncInst>(condition)) {
+    condition = T->getOperand(0); 
+    if (condition != --BasicBlock::iterator(T)/*&& TODO: CHEAP TRUNCATES*/)
+      return false;
+  }
+
+  if (BinaryOperator *A = dyn_cast<BinaryOperator>(condition)) {
+    if (A->getOpcode() == Instruction::And) {
+      ConstantInt *Zero(cast<ConstantInt>(ConstantInt::get(Ty, 0)));
+      if (unsigned Leg = I->findCaseValue(Zero)) {
+      //  I->removeCase(Leg);
+BasicBlock *New = Old->splitBasicBlock(I, Old->getName()+".switch");        
+TerminatorInst *T = Old->getTerminator();
+T->eraseFromParent();
+Instruction *Cmp = new ICmpInst(*Old, CmpInst::ICMP_EQ, I->getCondition(), Zero, "tst");
+BranchInst::Create(I->getSuccessor(Leg), New, Cmp, Old);
+I->removeCase(Leg);
+return true;
+      }
+    }
+  }
+
+
+// unsigned 	findCaseValue (const ConstantInt *C) const
+//void 	removeCase (unsigned idx)
+
+  return false; // once | (once = false);
+}
+
+
 // In this pass we look for GEP and cast instructions that are used
 // across basic blocks and rewrite them to improve basic-block-at-a-time
 // selection.
@@ -939,6 +988,10 @@
         MadeChange |= OptimizeMemoryInst(I, SI->getOperand(1),
                                          SI->getOperand(0)->getType(),
                                          SunkAddrs);
+    } else if (SwitchInst *SwI = dyn_cast<SwitchInst>(I)) {
+      if (TLI)
+        /*MadeChange |=*/ if (OptimizeSwitchInst(SwI, SwI->getCondition()))
+          return true;
     } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
       if (GEPI->hasAllZeroIndices()) {
         /// The GEP operand must be a pointer, so must its result -> BitCast

Added: llvm/branches/ggreif/waymark-64/test/CodeGen/X86/switch-and.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/ggreif/waymark-64/test/CodeGen/X86/switch-and.ll?rev=113668&view=auto
==============================================================================
--- llvm/branches/ggreif/waymark-64/test/CodeGen/X86/switch-and.ll (added)
+++ llvm/branches/ggreif/waymark-64/test/CodeGen/X86/switch-and.ll Fri Sep 10 19:01:51 2010
@@ -0,0 +1,43 @@
+%struct.Foo = type { i8* }
+
+define %struct.Foo* @_ZN3Foo7collectEj(%struct.Foo* %this, i32 %acc) nounwind
+readonly align 2 {
+entry:
+ br label %tailrecurse
+
+tailrecurse:                                      ; preds = %sw.bb, %entry
+ %indvar = phi i64 [ %indvar.next, %sw.bb ], [ 0, %entry ]
+ %acc.tr = phi i32 [ %or, %sw.bb ], [ %acc, %entry ]
+ %tmp = getelementptr inbounds %struct.Foo* %this, i64 %indvar, i32 0
+ %tmp2 = load i8** %tmp, align 8
+ %0 = ptrtoint i8* %tmp2 to i64
+ %and = and i64 %0, 3
+ %conv = trunc i64 %and to i32
+ switch i32 %conv, label %sw.epilog [
+   i32 0, label %sw.bb
+   i32 1, label %sw.bb
+   i32 3, label %sw.bb6
+   i32 2, label %sw.bb8
+ ]
+
+sw.bb:                                            ; preds = %tailrecurse
+ %shl = shl i32 %acc.tr, 1
+ %or = or i32 %conv, %shl
+ %indvar.next = add i64 %indvar, 1
+ br label %tailrecurse
+
+sw.bb6:                                           ; preds = %tailrecurse
+ %this.tr.sum21 = add i64 %indvar, 1
+ %add.ptr7 = getelementptr inbounds %struct.Foo* %this, i64 %this.tr.sum21
+ ret %struct.Foo* %add.ptr7
+
+sw.bb8:                                           ; preds = %tailrecurse
+ %idx.ext = zext i32 %acc.tr to i64
+ %add.ptr9.sum = add i64 %idx.ext, 1
+ %this.tr.sum = add i64 %indvar, %add.ptr9.sum
+ %add.ptr11 = getelementptr inbounds %struct.Foo* %this, i64 %this.tr.sum
+ ret %struct.Foo* %add.ptr11
+
+sw.epilog:                                        ; preds = %tailrecurse
+ ret %struct.Foo* undef
+}





More information about the llvm-branch-commits mailing list