[llvm] [ArgPromotion] Handle pointer arguments of recursive calls (PR #78735)

Vedant Paranjape via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 12 12:07:11 PDT 2024


================
@@ -610,15 +614,80 @@ static bool findArgParts(Argument *Arg, const DataLayout &DL, AAResults &AAR,
       // unknown users
     }
 
+    auto *CB = dyn_cast<CallBase>(V);
+    Value *PtrArg = cast<Value>(U);
+    if (IsRecursive && CB && PtrArg) {
+      Type *PtrTy = PtrArg->getType();
+      APInt Offset(DL.getIndexTypeSizeInBits(PtrTy), 0);
+      PtrArg = PtrArg->stripAndAccumulateConstantOffsets(
+          DL, Offset,
+          /* AllowNonInbounds= */ true);
+      if (PtrArg != Arg)
+        return false;
+
+      if (Offset.getSignificantBits() >= 64)
+        return false;
+
+      // If this is a recursive function and one of the argument types is a
+      // pointer that isn't loaded to a non pointer type, it can lead to
+      // recursive promotion. Look for any Load candidates above the function
+      // call that load a non pointer type from this argument pointer. If we
+      // don't find even one such use, return false. For reference, you can
+      // refer to Transforms/ArgumentPromotion/pr42028-recursion.ll and
+      // Transforms/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
+      // testcases.
+      bool doesPointerResolve = false;
+      for (auto Load : Loads)
+        if (Load->getPointerOperand() == PtrArg &&
+            !Load->getType()->isPointerTy())
+          doesPointerResolve = true;
+
+      if (!doesPointerResolve)
+        return false;
+
+      int64_t Off = Offset.getSExtValue();
+      if (Off)
+        LLVM_DEBUG(dbgs() << "ArgPromotion of " << *Arg << " failed: "
+                          << "pointer offset is not equal to zero\n");
----------------
vedantparanjape-amd wrote:

> Say you have something like:
> 
> ```
> define void func(ptr %a, ptr %b) {
>     ...
>     ...
>     call @func(ptr %b, ptr %a)
>     ...
> }
> ```
> 
> In this case, you can't promote %a on its own, because %a and %b are intertwined. So we need to bail out. (In theory, you could handle some subset of cases like this, but let's leave that for a different patch.)
> 
> I don't see how that's related to the "doesPointerResolve" check, which... isn't actually a correctness check in that sense. It's there to ensure the optimization itself terminates.

I implemented this, it was rather simple. lmk if it seems correct.

https://github.com/llvm/llvm-project/pull/78735


More information about the llvm-commits mailing list