[llvm-commits] [llvm] r69215 - /llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp

Dale Johannesen dalej at apple.com
Wed Apr 15 13:41:03 PDT 2009


Author: johannes
Date: Wed Apr 15 15:41:02 2009
New Revision: 69215

URL: http://llvm.org/viewvc/llvm-project?rev=69215&view=rev
Log:
Eliminate zext over (iv & const) or ((iv+const)&const)
if a longer iv is available.  These subscript forms are
not common; they're a bottleneck in OpenSSL.


Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=69215&r1=69214&r2=69215&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Wed Apr 15 15:41:02 2009
@@ -798,48 +798,106 @@
     if (PN == OrigControllingPHI && PN->getType() != LargestType)
       for (Value::use_iterator UI = PN->use_begin(), UE = PN->use_end();
            UI != UE; ++UI) {
-        if (isa<SExtInst>(UI) && NoSignedWrap) {
+        Instruction *UInst = dyn_cast<Instruction>(*UI);
+        if (UInst && isa<SExtInst>(UInst) && NoSignedWrap) {
           Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType, L, 
-                                            UI->getType(), Rewriter, InsertPt);
-          UI->replaceAllUsesWith(TruncIndVar);
-          if (Instruction *DeadUse = dyn_cast<Instruction>(*UI))
-            DeadInsts.insert(DeadUse);
+                                         UInst->getType(), Rewriter, InsertPt);
+          UInst->replaceAllUsesWith(TruncIndVar);
+          DeadInsts.insert(UInst);
         }
         // See if we can figure out sext(i+constant) doesn't wrap, so we can
         // use a larger add.  This is common in subscripting.
-        Instruction *UInst = dyn_cast<Instruction>(*UI);
         if (UInst && UInst->getOpcode()==Instruction::Add &&
             UInst->hasOneUse() &&
             isa<ConstantInt>(UInst->getOperand(1)) &&
-            isa<SExtInst>(UInst->use_begin()) && NoSignedWrap && LimitVal) {
-          uint64_t numBits = LimitVal->getValue().getBitWidth();
-          ConstantInt* RHS = dyn_cast<ConstantInt>(UInst->getOperand(1));
-          if (((APInt::getSignedMaxValue(numBits) - IncrVal->getValue()) -
-                RHS->getValue()).sgt(LimitVal->getValue())) {
-            SExtInst* oldSext = dyn_cast<SExtInst>(UInst->use_begin());
-            Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType, L,
-                                              oldSext->getType(), Rewriter,
-                                              InsertPt);
-            APInt APcopy = APInt(RHS->getValue());
-            ConstantInt* newRHS = 
-                  ConstantInt::get(APcopy.sext(oldSext->getType()->
-                                               getPrimitiveSizeInBits()));
-            Value *NewAdd = BinaryOperator::CreateAdd(TruncIndVar, newRHS,
-                                                      UInst->getName()+".nosex",
-                                                      UInst);
-            oldSext->replaceAllUsesWith(NewAdd);
-            if (Instruction *DeadUse = dyn_cast<Instruction>(oldSext))
-              DeadInsts.insert(DeadUse);
-            if (Instruction *DeadUse = dyn_cast<Instruction>(UInst))
-              DeadInsts.insert(DeadUse);
+            NoSignedWrap && LimitVal) {
+          uint64_t oldBitSize = LimitVal->getValue().getBitWidth();
+          uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();
+          ConstantInt* AddRHS = dyn_cast<ConstantInt>(UInst->getOperand(1));
+          if (((APInt::getSignedMaxValue(oldBitSize) - IncrVal->getValue()) -
+                AddRHS->getValue()).sgt(LimitVal->getValue())) {
+            // We've determined this is (i+constant) and it won't overflow.
+            if (isa<SExtInst>(UInst->use_begin())) {
+              SExtInst* oldSext = dyn_cast<SExtInst>(UInst->use_begin());
+              Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
+                                                L, oldSext->getType(), Rewriter,
+                                                InsertPt);
+              APInt APcopy = APInt(AddRHS->getValue());
+              ConstantInt* newAddRHS =ConstantInt::get(APcopy.sext(newBitSize));
+              Value *NewAdd = 
+                    BinaryOperator::CreateAdd(TruncIndVar, newAddRHS,
+                                              UInst->getName()+".nosex", UInst);
+              oldSext->replaceAllUsesWith(NewAdd);
+              if (Instruction *DeadUse = dyn_cast<Instruction>(oldSext))
+                DeadInsts.insert(DeadUse);
+              DeadInsts.insert(UInst);
+            }
           }
         }
-        if (isa<ZExtInst>(UI) && NoUnsignedWrap) {
+        if (UInst && isa<ZExtInst>(UInst) && NoUnsignedWrap) {
           Value *TruncIndVar = getZeroExtendedTruncVar(AR, SE, LargestType, L, 
-                                            UI->getType(), Rewriter, InsertPt);
-          UI->replaceAllUsesWith(TruncIndVar);
-          if (Instruction *DeadUse = dyn_cast<Instruction>(*UI))
+                                         UInst->getType(), Rewriter, InsertPt);
+          UInst->replaceAllUsesWith(TruncIndVar);
+          DeadInsts.insert(UInst);
+        }
+        // If we have zext(i&constant), we can use the larger variable.  This
+        // is not common but is a bottleneck in Openssl.
+        // (RHS doesn't have to be constant.  There should be a better approach
+        // than bottom-up pattern matching for this...)
+        if (UInst && UInst->getOpcode()==Instruction::And &&
+            UInst->hasOneUse() &&
+            isa<ConstantInt>(UInst->getOperand(1)) &&
+            isa<ZExtInst>(UInst->use_begin())) {
+          uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();
+          ConstantInt* AndRHS = dyn_cast<ConstantInt>(UInst->getOperand(1));
+          ZExtInst* oldZext = dyn_cast<ZExtInst>(UInst->use_begin());
+          Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
+                                  L, oldZext->getType(), Rewriter, InsertPt);
+          APInt APcopy = APInt(AndRHS->getValue());
+          ConstantInt* newAndRHS = ConstantInt::get(APcopy.zext(newBitSize));
+          Value *NewAnd = 
+                BinaryOperator::CreateAnd(TruncIndVar, newAndRHS,
+                                          UInst->getName()+".nozex", UInst);
+          oldZext->replaceAllUsesWith(NewAnd);
+          if (Instruction *DeadUse = dyn_cast<Instruction>(oldZext))
             DeadInsts.insert(DeadUse);
+          DeadInsts.insert(UInst);
+        }
+        // If we have zext((i+constant)&constant), we can use the larger
+        // variable even if the add does overflow.  This works whenever the
+        // constant being ANDed is the same size as i, which it presumably is.
+        // We don't need to restrict the expression being and'ed to i+const,
+        // but we have to promote everything in it, so it's convenient.
+        if (UInst && UInst->getOpcode()==Instruction::Add &&
+            UInst->hasOneUse() &&
+            isa<ConstantInt>(UInst->getOperand(1))) {
+          uint64_t newBitSize = LargestType->getPrimitiveSizeInBits();
+          ConstantInt* AddRHS = dyn_cast<ConstantInt>(UInst->getOperand(1));
+          Instruction *UInst2 = dyn_cast<Instruction>(UInst->use_begin());
+          if (UInst2 && UInst2->getOpcode() == Instruction::And &&
+              UInst2->hasOneUse() &&
+              isa<ConstantInt>(UInst2->getOperand(1)) &&
+              isa<ZExtInst>(UInst2->use_begin())) {
+            ZExtInst* oldZext = dyn_cast<ZExtInst>(UInst2->use_begin());
+            Value *TruncIndVar = getSignExtendedTruncVar(AR, SE, LargestType,
+                                    L, oldZext->getType(), Rewriter, InsertPt);
+            ConstantInt* AndRHS = dyn_cast<ConstantInt>(UInst2->getOperand(1));
+            APInt APcopy = APInt(AddRHS->getValue());
+            ConstantInt* newAddRHS = ConstantInt::get(APcopy.zext(newBitSize));
+            Value *NewAdd = 
+                  BinaryOperator::CreateAdd(TruncIndVar, newAddRHS,
+                                            UInst->getName()+".nozex", UInst2);
+            APInt APcopy2 = APInt(AndRHS->getValue());
+            ConstantInt* newAndRHS = ConstantInt::get(APcopy2.zext(newBitSize));
+            Value *NewAnd = 
+                  BinaryOperator::CreateAnd(NewAdd, newAndRHS,
+                                            UInst->getName()+".nozex", UInst2);
+            oldZext->replaceAllUsesWith(NewAnd);
+            if (Instruction *DeadUse = dyn_cast<Instruction>(oldZext))
+              DeadInsts.insert(DeadUse);
+            DeadInsts.insert(UInst);
+            DeadInsts.insert(UInst2);
+          }
         }
       }
 





More information about the llvm-commits mailing list