[llvm] [GVN] Restrict equality propagation for pointers (PR #82458)

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 23 11:13:36 PDT 2024


================
@@ -710,22 +710,58 @@ Value *llvm::FindAvailableLoadedValue(LoadInst *Load, BatchAAResults &AA,
   return Available;
 }
 
-bool llvm::canReplacePointersIfEqual(Value *A, Value *B, const DataLayout &DL,
-                                     Instruction *CtxI) {
-  Type *Ty = A->getType();
-  assert(Ty == B->getType() && Ty->isPointerTy() &&
-         "values must have matching pointer types");
-
-  // NOTE: The checks in the function are incomplete and currently miss illegal
-  // cases! The current implementation is a starting point and the
-  // implementation should be made stricter over time.
-  if (auto *C = dyn_cast<Constant>(B)) {
-    // Do not allow replacing a pointer with a constant pointer, unless it is
-    // either null or at least one byte is dereferenceable.
-    APInt OneByte(DL.getPointerTypeSizeInBits(Ty), 1);
-    return C->isNullValue() ||
-           isDereferenceableAndAlignedPointer(B, Align(1), OneByte, DL, CtxI);
-  }
+// Returns true if a use is either in an ICmp/PtrToInt or a Phi/Select that only
+// feeds into them.
+static bool isPointerUseReplacable(const Use &U, int MaxLookup = 6) {
+  if (MaxLookup == 0)
+    return false;
+
+  const User *User = U.getUser();
+  if (isa<ICmpInst>(User))
+    return true;
+  if (isa<PtrToIntInst>(User))
+    return true;
+  if (isa<PHINode, SelectInst>(User) &&
+      all_of(User->uses(), [&](const Use &Use) {
+        return isPointerUseReplacable(Use, MaxLookup - 1);
+      }))
----------------
efriedma-quic wrote:

The issue is that it has terrible scaling in edge cases: if you have a PHI with 100 operands, and 99 of them are the PHI itself, you visit 1 trillion times, or something like that.

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


More information about the llvm-commits mailing list