[llvm] a0757d8 - Patch by @wecing (Chenguang Wang).

Tim Shen via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 19 12:44:55 PST 2021


Author: Tim Shen
Date: 2021-02-19T12:44:17-08:00
New Revision: a0757d8ebdefa1c54896d70d2a04f68fc23f7916

URL: https://github.com/llvm/llvm-project/commit/a0757d8ebdefa1c54896d70d2a04f68fc23f7916
DIFF: https://github.com/llvm/llvm-project/commit/a0757d8ebdefa1c54896d70d2a04f68fc23f7916.diff

LOG: Patch by @wecing (Chenguang Wang).

The current getFoldedSizeOf() implementation uses naive recursion, which
could be really slow when the input structure type is too complex.

This issue was first brought up in
http://llvm.org/bugs/show_bug.cgi?id=8281; this change fixes it by
adding memoization.

Differential Revision: https://reviews.llvm.org/D6594

Added: 
    llvm/test/tools/llvm-as/slow-ptrtoint.ll

Modified: 
    llvm/lib/IR/ConstantFold.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 95dd55237e5f..6d2770af8322 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -348,14 +348,22 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
   }
 }
 
+/// Wrapper around getFoldedSizeOfImpl() that adds caching.
+static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded,
+                                 DenseMap<Type *, Constant *> &Cache);
+
 /// Return a ConstantExpr with type DestTy for sizeof on Ty, with any known
 /// factors factored out. If Folded is false, return null if no factoring was
 /// possible, to avoid endlessly bouncing an unfoldable expression back into the
 /// top-level folder.
-static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
+static Constant *getFoldedSizeOfImpl(Type *Ty, Type *DestTy, bool Folded,
+                                     DenseMap<Type *, Constant *> &Cache) {
+  // This is the actual implementation of getFoldedSizeOf(). To get the caching
+  // behavior, we need to call getFoldedSizeOf() when we recurse.
+
   if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
     Constant *N = ConstantInt::get(DestTy, ATy->getNumElements());
-    Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true);
+    Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true, Cache);
     return ConstantExpr::getNUWMul(E, N);
   }
 
@@ -367,11 +375,11 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
         return ConstantExpr::getNullValue(DestTy);
       // Check for a struct with all members having the same size.
       Constant *MemberSize =
-        getFoldedSizeOf(STy->getElementType(0), DestTy, true);
+          getFoldedSizeOf(STy->getElementType(0), DestTy, true, Cache);
       bool AllSame = true;
       for (unsigned i = 1; i != NumElems; ++i)
         if (MemberSize !=
-            getFoldedSizeOf(STy->getElementType(i), DestTy, true)) {
+            getFoldedSizeOf(STy->getElementType(i), DestTy, true, Cache)) {
           AllSame = false;
           break;
         }
@@ -385,10 +393,10 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
   // to an arbitrary pointee.
   if (PointerType *PTy = dyn_cast<PointerType>(Ty))
     if (!PTy->getElementType()->isIntegerTy(1))
-      return
-        getFoldedSizeOf(PointerType::get(IntegerType::get(PTy->getContext(), 1),
-                                         PTy->getAddressSpace()),
-                        DestTy, true);
+      return getFoldedSizeOf(
+          PointerType::get(IntegerType::get(PTy->getContext(), 1),
+                           PTy->getAddressSpace()),
+          DestTy, true, Cache);
 
   // 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.
@@ -403,6 +411,20 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
   return C;
 }
 
+static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded,
+                                 DenseMap<Type *, Constant *> &Cache) {
+  // Check for previously generated folded size constant.
+  auto It = Cache.find(Ty);
+  if (It != Cache.end())
+    return It->second;
+  return Cache[Ty] = getFoldedSizeOfImpl(Ty, DestTy, Folded, Cache);
+}
+
+static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
+  DenseMap<Type *, Constant *> Cache;
+  return getFoldedSizeOf(Ty, DestTy, Folded, Cache);
+}
+
 /// Return a ConstantExpr with type DestTy for alignof on Ty, with any known
 /// factors factored out. If Folded is false, return null if no factoring was
 /// possible, to avoid endlessly bouncing an unfoldable expression back into the

diff  --git a/llvm/test/tools/llvm-as/slow-ptrtoint.ll b/llvm/test/tools/llvm-as/slow-ptrtoint.ll
new file mode 100644
index 000000000000..5f5b72685751
--- /dev/null
+++ b/llvm/test/tools/llvm-as/slow-ptrtoint.ll
@@ -0,0 +1,30 @@
+; RUN: llvm-as %s -o - | llvm-dis -o - | FileCheck %s
+
+%0 = type { %1, %1, %1, %1, %1, %1, %1, %1 }
+%1 = type { %2, %2, %2, %2, %2, %2, %2, %2 }
+%2 = type { %3, %3, %3, %3, %3, %3, %3, %3 }
+%3 = type { %4, %4, %4, %4, %4, %4, %4, %4 }
+%4 = type { %5, %5, %5, %5, %5, %5, %5, %5 }
+%5 = type { %6, %6, %6, %6, %6, %6, %6, %6 }
+%6 = type { %7, %7, %7, %7, %7, %7, %7, %7 }
+%7 = type { %8, %8, %8, %8, %8, %8, %8, %8 }
+%8 = type { %9, %9, %9, %9, %9, %9, %9, %9 }
+%9 = type { %10, %10, %10, %10, %10, %10, %10, %10 }
+%10 = type { %11, %11, %11, %11, %11, %11, %11, %11 }
+%11 = type { %12, %12, %12, %12, %12, %12, %12, %12 }
+%12 = type { %13, %13, %13, %13, %13, %13, %13, %13 }
+%13 = type { i32, i32 }
+
+; it would take a naive recursive implementation ~4 days
+; to constant fold the size of %0
+define i64 @f_i64() {
+; CHECK-LABEL: @f_i64
+; CHECK:         ret i64 mul (i64 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64), i64 1099511627776)
+  ret i64 ptrtoint (%0* getelementptr (%0, %0* null, i32 1) to i64)
+}
+
+define i32 @f_i32() {
+; CHECK-LABEL: @f_i32
+; CHECK:         ret i32 mul (i32 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i32), i32 -2147483648)
+  ret i32 ptrtoint (%3* getelementptr (%3, %3* null, i32 1) to i32)
+}


        


More information about the llvm-commits mailing list