[PATCH] D142680: [ConstFolding] Modified algorithm of `ConstantFoldConstantImpl` to be iterative

Kolya Panchenko via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 26 17:46:01 PST 2023


nikolaypanchenko created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
nikolaypanchenko added a reviewer: arsenm.
nikolaypanchenko published this revision for review.
Herald added subscribers: llvm-commits, wdng.
Herald added a project: LLVM.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142680

Files:
  llvm/lib/Analysis/ConstantFolding.cpp


Index: llvm/lib/Analysis/ConstantFolding.cpp
===================================================================
--- llvm/lib/Analysis/ConstantFolding.cpp
+++ llvm/lib/Analysis/ConstantFolding.cpp
@@ -1121,36 +1121,58 @@
 ConstantFoldConstantImpl(const Constant *C, const DataLayout &DL,
                          const TargetLibraryInfo *TLI,
                          SmallDenseMap<Constant *, Constant *> &FoldedOps) {
-  if (!isa<ConstantVector>(C) && !isa<ConstantExpr>(C))
-    return const_cast<Constant *>(C);
+  SmallVector<Constant *> Worklist = {const_cast<Constant *>(C)};
+
+  // "Recursively" iterate over all users of the constant. Try to fold constant
+  // if all its operand were processed before.
+  while (!Worklist.empty()) {
+    Constant *CurrentC = Worklist.back();
+    if (FoldedOps.count(CurrentC)) {
+      Worklist.pop_back();
+      continue;
+    }
 
-  SmallVector<Constant *, 8> Ops;
-  for (const Use &OldU : C->operands()) {
-    Constant *OldC = cast<Constant>(&OldU);
-    Constant *NewC = OldC;
-    // Recursively fold the ConstantExpr's operands. If we have already folded
-    // a ConstantExpr, we don't have to process it again.
-    if (isa<ConstantVector>(OldC) || isa<ConstantExpr>(OldC)) {
-      auto It = FoldedOps.find(OldC);
-      if (It == FoldedOps.end()) {
-        NewC = ConstantFoldConstantImpl(OldC, DL, TLI, FoldedOps);
-        FoldedOps.insert({OldC, NewC});
-      } else {
-        NewC = It->second;
+    if (!isa<ConstantVector>(CurrentC) && !isa<ConstantExpr>(CurrentC)) {
+      Worklist.pop_back();
+      FoldedOps.try_emplace(CurrentC, CurrentC);
+      continue;
+    }
+
+    SmallVector<Constant *, 8> Ops;
+    for (const Use &U : CurrentC->operands()) {
+      Constant *OldC = cast<Constant>(&U);
+      Constant *NewC = OldC;
+      if (isa<ConstantVector>(OldC) || isa<ConstantExpr>(OldC)) {
+        auto It = FoldedOps.find(OldC);
+        if (It == FoldedOps.end()) {
+          NewC = nullptr;
+          Worklist.push_back(OldC);
+        } else {
+          NewC = It->second;
+        }
       }
+      if (NewC)
+        Ops.push_back(NewC);
     }
-    Ops.push_back(NewC);
-  }
 
-  if (auto *CE = dyn_cast<ConstantExpr>(C)) {
-    if (Constant *Res =
-            ConstantFoldInstOperandsImpl(CE, CE->getOpcode(), Ops, DL, TLI))
-      return Res;
-    return const_cast<Constant *>(C);
-  }
+    // If all operands of the constant were processed, try to fold them
+    if (Ops.size() == CurrentC->getNumOperands()) {
+      assert(Worklist.back() == CurrentC &&
+             "Some operand of the Constant was added to the Worklist.");
+      Worklist.pop_back();
 
-  assert(isa<ConstantVector>(C));
-  return ConstantVector::get(Ops);
+      if (auto *CE = dyn_cast<ConstantExpr>(CurrentC)) {
+        if (Constant *Res =
+                ConstantFoldInstOperandsImpl(CE, CE->getOpcode(), Ops, DL, TLI))
+          FoldedOps.try_emplace(CurrentC, Res);
+        else
+          FoldedOps.try_emplace(CurrentC, CurrentC);
+      } else {
+        FoldedOps.try_emplace(CurrentC, ConstantVector::get(Ops));
+      }
+    }
+  }
+  return FoldedOps.find(C)->second;
 }
 
 } // end anonymous namespace


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142680.492615.patch
Type: text/x-patch
Size: 3191 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230127/281a22ee/attachment.bin>


More information about the llvm-commits mailing list