Fix for bug 8281 - Extremely slow assembling and disassembling of ptrtoint

Chenguang Wang w3cing at gmail.com
Wed Dec 10 16:00:12 PST 2014


The constant folder calculates size of structs in a recursive manner,
which works poorly when the struct is not a tree-like structure but a
DAG. Refer to the bugzilla page for more details.

http://reviews.llvm.org/D6594
http://llvm.org/bugs/show_bug.cgi?id=8281

- Chenguang
-------------- next part --------------
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index cdfb41f..962310e 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -18,6 +18,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ConstantFold.h"
+#include "LLVMContextImpl.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"
@@ -336,10 +337,15 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
 ///
 static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
                                  bool Folded) {
+  // check for previously generated folded size Constant.
+  DenseMap<Type *, Constant *> &TFS = Ty->getContext().pImpl->TypeFoldedSizes;
+  if (TFS.find(Ty) != TFS.end())
+    return TFS[Ty];
+
   if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
     Constant *N = ConstantInt::get(DestTy, ATy->getNumElements());
     Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true);
-    return ConstantExpr::getNUWMul(E, N);
+    return TFS[Ty] = ConstantExpr::getNUWMul(E, N);
   }
 
   if (StructType *STy = dyn_cast<StructType>(Ty))
@@ -347,7 +353,7 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
       unsigned NumElems = STy->getNumElements();
       // An empty struct has size zero.
       if (NumElems == 0)
-        return ConstantExpr::getNullValue(DestTy);
+        return TFS[Ty] = ConstantExpr::getNullValue(DestTy);
       // Check for a struct with all members having the same size.
       Constant *MemberSize =
         getFoldedSizeOf(STy->getElementType(0), DestTy, true);
@@ -360,7 +366,7 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
         }
       if (AllSame) {
         Constant *N = ConstantInt::get(DestTy, NumElems);
-        return ConstantExpr::getNUWMul(MemberSize, N);
+        return TFS[Ty] = ConstantExpr::getNUWMul(MemberSize, N);
       }
     }
 
@@ -368,7 +374,7 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
   // to an arbitrary pointee.
   if (PointerType *PTy = dyn_cast<PointerType>(Ty))
     if (!PTy->getElementType()->isIntegerTy(1))
-      return
+      return TFS[Ty] =
         getFoldedSizeOf(PointerType::get(IntegerType::get(PTy->getContext(), 1),
                                          PTy->getAddressSpace()),
                         DestTy, true);
@@ -376,14 +382,14 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
   // If there's no interesting folding happening, bail so that we don't create
   // a constant that looks like it needs folding but really doesn't.
   if (!Folded)
-    return nullptr;
+    return TFS[Ty] = nullptr;
 
   // Base case: Get a regular sizeof expression.
   Constant *C = ConstantExpr::getSizeOf(Ty);
   C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false,
                                                     DestTy, false),
                             C, DestTy);
-  return C;
+  return TFS[Ty] = C;
 }
 
 /// getFoldedAlignOf - Return a ConstantExpr with type DestTy for alignof
diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h
index 41822f0..7495e74 100644
--- a/lib/IR/LLVMContextImpl.h
+++ b/lib/IR/LLVMContextImpl.h
@@ -295,6 +295,8 @@ public:
   ConstantInt *TheFalseVal;
   
   LeakDetectorImpl<Value> LLVMObjects;
+
+  DenseMap<Type *, Constant *> TypeFoldedSizes;
   
   // Basic type instances.
   Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy;


More information about the llvm-commits mailing list