Skip to content

Conversation

@shiltian
Copy link
Contributor

If the range size doesn't match the type size, it might read wrong data.

@shiltian shiltian requested review from jdoerfert and ssahasra July 30, 2025 16:13
Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@shiltian
Copy link
Contributor Author

shiltian commented Jul 30, 2025

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. It then replaces the load with just i8 49, which is completely wrong here.

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?

@shiltian shiltian force-pushed the users/shiltian/check-range-size-before-constant-fold-load branch from 3514320 to 97a51a3 Compare October 15, 2025 18:36
@shiltian shiltian marked this pull request as ready for review October 15, 2025 18:36
@shiltian shiltian changed the title [WIP][Attributor] Check range size before constant fold load [Attributor] Check range size before constant fold load Oct 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 15, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Shilei Tian (shiltian)

Changes

If the range size doesn't match the type size, it might read wrong data.


Full diff: https://github.com/llvm/llvm-project/pull/151359.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/IPO/Attributor.cpp (+3)
  • (added) llvm/test/Transforms/Attributor/range-and-constant-fold.ll (+34)
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 077d29f7499a4..3b59ebbbb9322 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -272,6 +272,9 @@ AA::getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA,
   }
 
   if (RangePtr && !RangePtr->offsetOrSizeAreUnknown()) {
+    int64_t StorageSize = DL.getTypeStoreSize(&Ty);
+    if (StorageSize != RangePtr->Size)
+      return nullptr;
     APInt Offset = APInt(64, RangePtr->Offset);
     return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL);
   }
diff --git a/llvm/test/Transforms/Attributor/range-and-constant-fold.ll b/llvm/test/Transforms/Attributor/range-and-constant-fold.ll
new file mode 100644
index 0000000000000..fcc5e6e0fd52f
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/range-and-constant-fold.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=attributor %s -o - | FileCheck %s
+
+@g = internal unnamed_addr addrspace(4) constant [3 x i8] c"12\00", align 16
+
+define void @foo(i32 %a, i32 %b, ptr %p) {
+; CHECK-LABEL: define void @foo(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], ptr nofree nonnull writeonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[A]], [[B]]
+; CHECK-NEXT:    br i1 [[CMP]], label %[[L1:.*]], label %[[L2:.*]]
+; CHECK:       [[L1]]:
+; CHECK-NEXT:    br label %[[L3:.*]]
+; CHECK:       [[L2]]:
+; CHECK-NEXT:    br label %[[L3]]
+; CHECK:       [[L3]]:
+; CHECK-NEXT:    [[PHI:%.*]] = phi ptr addrspace(4) [ @g, %[[L1]] ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 1), %[[L2]] ]
+; CHECK-NEXT:    [[LOAD:%.*]] = load i8, ptr addrspace(4) [[PHI]], align 1
+; CHECK-NEXT:    store i8 [[LOAD]], ptr [[P]], align 1
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cmp = icmp ne i32 %a, %b
+  br i1 %cmp, label %l1, label %l2
+l1:
+  br label %l3
+l2:
+  br label %l3
+l3:
+  %phi = phi ptr addrspace(4) [ @g, %l1 ], [ getelementptr inbounds nuw (i8, ptr addrspace(4) @g, i64 1), %l2 ]
+  %load = load i8, ptr addrspace(4) %phi
+  store i8 %load, ptr %p
+  ret void
+}

@shiltian
Copy link
Contributor Author

It doesn't seem like this PR causes any changes (except the new test) to the existing test cases so I assume it'd be fine.

@shiltian shiltian requested a review from arsenm October 15, 2025 18:42
@shiltian shiltian requested a review from arsenm October 20, 2025 02:09
@shiltian
Copy link
Contributor Author

ping

If the range size doesn't match the type size, it might read wrong data.
@shiltian shiltian force-pushed the users/shiltian/check-range-size-before-constant-fold-load branch from 97a51a3 to 003c4a9 Compare October 24, 2025 03:15
@shiltian shiltian merged commit 09eea22 into main Oct 25, 2025
10 checks passed
@shiltian shiltian deleted the users/shiltian/check-range-size-before-constant-fold-load branch October 25, 2025 14:36
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 25, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-quick running on linaro-clang-aarch64-quick while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/24524

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'Clangd Unit Tests :: ./ClangdTests/242/335' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/tools/extra/clangd/unittests/./ClangdTests-Clangd Unit Tests-3567922-242-335.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=335 GTEST_SHARD_INDEX=242 /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/tools/extra/clangd/unittests/./ClangdTests
--

Note: This is test shard 243 of 335.
[==========] Running 4 tests from 4 test suites.
[----------] Global test environment set-up.
[----------] 1 test from SignatureHelp
[ RUN      ] SignatureHelp.TemplateArguments
Built preamble of size 707748 for file /clangd-test/TestTU.cpp version null in 0.29 seconds
Built preamble of size 707748 for file /clangd-test/TestTU.cpp version null in 0.11 seconds
[       OK ] SignatureHelp.TemplateArguments (435 ms)
[----------] 1 test from SignatureHelp (435 ms total)

[----------] 1 test from FormatIncremental
[ RUN      ] FormatIncremental.FormatBrace
[       OK ] FormatIncremental.FormatBrace (100 ms)
[----------] 1 test from FormatIncremental (100 ms total)

[----------] 1 test from CrossFileRenameTests
[ RUN      ] CrossFileRenameTests.WithUpToDateIndex
ASTWorker building file /clangd-test/foo.h version null with command 
[/clangd-test]
clang -xobjective-c++ /clangd-test/foo.h
Driver produced command: cc1 -cc1 -triple aarch64-unknown-linux-gnu -fsyntax-only -disable-free -clear-ast-before-backend -main-file-name foo.h -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -enable-tlsdesc -target-cpu generic -target-feature +v8a -target-feature +fp-armv8 -target-feature +neon -target-abi aapcs -debugger-tuning=gdb -fdebug-compilation-dir=/clangd-test -fcoverage-compilation-dir=/clangd-test -resource-dir lib/clang/22 -internal-isystem lib/clang/22/include -internal-isystem /usr/local/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fobjc-runtime=gcc -fobjc-encode-cxx-class-template-spec -fobjc-exceptions -fcxx-exceptions -fexceptions -no-round-trip-args -target-feature -fmv -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -x objective-c++ /clangd-test/foo.h
Building first preamble for /clangd-test/foo.h version null
Built preamble of size 821236 for file /clangd-test/foo.h version null in 2.55 seconds
indexed preamble AST for /clangd-test/foo.h version null:
  symbol slab: 0 symbols, 120 bytes
  ref slab: 0 symbols, 0 refs, 128 bytes
  relations slab: 0 relations, 24 bytes
indexed file AST for /clangd-test/foo.h version null:
  symbol slab: 3 symbols, 4912 bytes
  ref slab: 3 symbols, 5 refs, 4320 bytes
  relations slab: 0 relations, 24 bytes
Build dynamic index for main-file symbols with estimated memory usage of 12648 bytes
ASTWorker building file /clangd-test/foo.cc version null with command 
[/clangd-test]
clang -xobjective-c++ /clangd-test/foo.cc
Driver produced command: cc1 -cc1 -triple aarch64-unknown-linux-gnu -fsyntax-only -disable-free -clear-ast-before-backend -main-file-name foo.cc -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -enable-tlsdesc -target-cpu generic -target-feature +v8a -target-feature +fp-armv8 -target-feature +neon -target-abi aapcs -debugger-tuning=gdb -fdebug-compilation-dir=/clangd-test -fcoverage-compilation-dir=/clangd-test -resource-dir lib/clang/22 -internal-isystem lib/clang/22/include -internal-isystem /usr/local/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fobjc-runtime=gcc -fobjc-encode-cxx-class-template-spec -fobjc-exceptions -fcxx-exceptions -fexceptions -no-round-trip-args -target-feature -fmv -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -x objective-c++ /clangd-test/foo.cc
Building first preamble for /clangd-test/foo.cc version null
Built preamble of size 824788 for file /clangd-test/foo.cc version null in 1.11 seconds
indexed file AST for /clangd-test/foo.cc version null:
  symbol slab: 3 symbols, 4912 bytes
  ref slab: 4 symbols, 9 refs, 4320 bytes
  relations slab: 0 relations, 24 bytes
Build dynamic index for main-file symbols with estimated memory usage of 22400 bytes
indexed preamble AST for /clangd-test/foo.cc version null:
...

dvbuka pushed a commit to dvbuka/llvm-project that referenced this pull request Oct 27, 2025
If the range size doesn't match the type size, it might read wrong data.
Lukacma pushed a commit to Lukacma/llvm-project that referenced this pull request Oct 29, 2025
If the range size doesn't match the type size, it might read wrong data.
aokblast pushed a commit to aokblast/llvm-project that referenced this pull request Oct 30, 2025
If the range size doesn't match the type size, it might read wrong data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants