[llvm] [WIP][Attributor] Check range size before constant fold load (PR #151359)
Shilei Tian via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 30 10:12:37 PDT 2025
shiltian wrote:
I'm currently trying to resolve an issue that can be demonstrated by the following code.
```
@g = internal unnamed_addr addrspace(4) constant [21 x i8] c"18446744073709551615\00", align 16
define void @foo(...) {
%phi = phi ptr addrspace(4) [ @g, %bb ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 1), %bb.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 2), %bb.1.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 3), %bb.2.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 4), %bb.3.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 5), %bb.4.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 6), %bb.5.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 7), %bb.6.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 8), %bb.7.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 9), %bb.8.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 10), %bb.9.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 11), %bb.10.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 12), %bb.11.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 13), %bb.12.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 14), %bb.13.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 15), %bb.14.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 16), %bb.15.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 17), %bb.16.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 18), %bb.17.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 19), %bb.18.i ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 20), %bb.19.i ]
%load = load i8, ptr addrspace(4) %phi
...
}
```
In this example, we have a constant global variable `@g`, a phi instruction whose incoming values are all GEPs on `@g` with different offset, and a load instruction from the phi.
When we call `getPotentiallyLoadedValues` on the load instruction, it checks all the potential objects of the pointer, which is only `@g` in this case. After that, it checks all interfering access of `@g` via `AAPointerInfo` on `@g`. Inside `forallInterferingAccesses`, it first checks all 21 accesses of `@g` via `State::forallInterferingAccesses` and gets the `Range`. Each access is `Offset:N, Size:1` where `N` is from 0 to 20, corresponding to the 20 GEPs of the phi instruction.
In this case, after `State::forallInterferingAccesses`, `Range` becomes `Offset:0, Size: 21`. However, there is no actual `InterferingAccesses` because all accesses are just GEPs (and `LocalI` is the load on the phi for all of them). The outer `forallInterferingAccesses` simply skips the user call backs and returns true, which makes the caller of `forallInterferingAccesses` think `Range` is a legit one. This leaves a question: is this `Range` legit one? I'm not sure.
Since the user call back is skipped, there is nothing in `NewCopies` at this moment. However, since `@g` has not been written to, and the `Range` is assigned, it then tries to get the initial value for `@g`. The type is an `i8` here, and `Range` is at offset 0, then it gets `i8 49`, which corresponds to the first element `'1'` of the string.
That said, I'm not sure if the fix here is correct. If it is not, what is the semantics of `getInitialValueForObj` if the range size doesn't match the type size?
https://github.com/llvm/llvm-project/pull/151359
More information about the llvm-commits
mailing list