[llvm] [GVN] Restrict equality propagation for pointers (PR #82458)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 23 18:17:22 PDT 2024
================
@@ -68,35 +68,49 @@ TEST(LoadsTest, CanReplacePointersIfEqual) {
R"IR(
@y = common global [1 x i32] zeroinitializer, align 4
@x = common global [1 x i32] zeroinitializer, align 4
-
declare void @use(i32*)
-define void @f(i32* %p) {
+define void @f(i32* %p1, i32* %p2, i64 %i) {
call void @use(i32* getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0))
- call void @use(i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @x, i64 0, i64 0), i64 1))
+
+ %p1_idx = getelementptr inbounds i32, i32* %p1, i64 %i
+ call void @use(i32* %p1_idx)
+
+ %icmp = icmp eq i32* %p1, getelementptr inbounds ([1 x i32], [1 x i32]* @y, i64 0, i64 0)
+ %ptrInt = ptrtoint i32* %p1 to i64
ret void
}
)IR");
- const auto &DL = M->getDataLayout();
+ const DataLayout &DL = M->getDataLayout();
auto *GV = M->getNamedValue("f");
ASSERT_TRUE(GV);
auto *F = dyn_cast<Function>(GV);
ASSERT_TRUE(F);
- // NOTE: the implementation of canReplacePointersIfEqual is incomplete.
- // Currently the only the cases it returns false for are really sound and
- // returning true means unknown.
- Value *P = &*F->arg_begin();
+ Value *P1 = &*F->arg_begin();
+ Value *P2 = F->getArg(1);
+ Value *NullPtr = Constant::getNullValue(P1->getType());
auto InstIter = F->front().begin();
- Value *ConstDerefPtr = *cast<CallInst>(&*InstIter)->arg_begin();
- // ConstDerefPtr is a constant pointer that is provably de-referenceable. We
- // can replace an arbitrary pointer with it.
- EXPECT_TRUE(canReplacePointersIfEqual(P, ConstDerefPtr, DL, nullptr));
+ CallInst *UserOfY = cast<CallInst>(&*InstIter);
+ Value *ConstDerefPtr = UserOfY->getArgOperand(0);
+ // We cannot replace two pointers in arbitrary instructions unless we are
+ // replacing with null, a constant dereferencable pointer or they have the
+ // same underlying object.
+ EXPECT_FALSE(canReplacePointersIfEqual(ConstDerefPtr, P1, DL));
+ EXPECT_FALSE(canReplacePointersIfEqual(P1, P2, DL));
+ EXPECT_TRUE(canReplacePointersIfEqual(P1, ConstDerefPtr, DL));
+ EXPECT_TRUE(canReplacePointersIfEqual(P1, NullPtr, DL));
+
+ GetElementPtrInst *BasedOnP1 = cast<GetElementPtrInst>(&*++InstIter);
+ EXPECT_TRUE(canReplacePointersIfEqual(BasedOnP1, P1, DL));
+ EXPECT_FALSE(canReplacePointersIfEqual(BasedOnP1, P2, DL));
- ++InstIter;
- Value *ConstUnDerefPtr = *cast<CallInst>(&*InstIter)->arg_begin();
- // ConstUndDerefPtr is a constant pointer that is provably not
- // de-referenceable. We cannot replace an arbitrary pointer with it.
- EXPECT_FALSE(
- canReplacePointersIfEqual(ConstDerefPtr, ConstUnDerefPtr, DL, nullptr));
+ // // We can replace two arbitrary pointers in icmp and ptrtoint instructions.
----------------
nikic wrote:
```suggestion
// We can replace two arbitrary pointers in icmp and ptrtoint instructions.
```
https://github.com/llvm/llvm-project/pull/82458
More information about the llvm-commits
mailing list