[llvm] Prevent GlobalOpt from folding away addrspacecasts which may be runtime operations. (PR #153753)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 14 23:42:10 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Owen Anderson (resistor)
<details>
<summary>Changes</summary>
Specifically in the context of the once-stored transformation, GlobalOpt would strip
all pointer casts unconditionally, even though addrspacecasts might be runtime operations.
This manifested particularly on CHERI targets.
This patch was inspired by an existing change in CHERI LLVM (https://github.com/CHERIoT-Platform/llvm-project/commit/91afa60f17ea1b91e5cdba21a5c90400024b2b6a), but has been reimplemented with updated conventions, and a testcase constructed from scratch.
---
Full diff: https://github.com/llvm/llvm-project/pull/153753.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/IPO/GlobalOpt.cpp (+3-2)
- (added) llvm/test/Transforms/GlobalOpt/stored-once-addrspacecast.ll (+31)
``````````diff
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index bdda4980c1005..89a811e3f74d5 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -1133,8 +1133,9 @@ static bool
optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
const DataLayout &DL,
function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
- // Ignore no-op GEPs and bitcasts.
- StoredOnceVal = StoredOnceVal->stripPointerCasts();
+ // Ignore no-op GEPs and bitcasts, but not addrspacecasts that may be runtime
+ // operations.
+ StoredOnceVal = StoredOnceVal->stripPointerCastsSameRepresentation();
// If we are dealing with a pointer global that is initialized to null and
// only has one (non-null) value stored into it, then we can optimize any
diff --git a/llvm/test/Transforms/GlobalOpt/stored-once-addrspacecast.ll b/llvm/test/Transforms/GlobalOpt/stored-once-addrspacecast.ll
new file mode 100644
index 0000000000000..cb2fcce51a7ae
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/stored-once-addrspacecast.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
+; RUN: opt -passes=globalopt < %s -S | FileCheck %s
+
+; Test that we do not fold away addresscasts when optimizing once-stored
+; globals, as these may be runtime operations.
+
+%T = type { ptr }
+
+ at 0 = internal global ptr null
+ at 1 = internal addrspace(1) global i32 0
+
+;.
+; CHECK: @[[GLOB0:[0-9]+]] = internal unnamed_addr global ptr null
+; CHECK: @[[GLOB1:[0-9]+]] = internal addrspace(1) global i32 0
+;.
+define void @a() {
+; CHECK-LABEL: @a(
+; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(1) @[[GLOB1]] to ptr
+; CHECK-NEXT: store ptr [[TMP1]], ptr @[[GLOB0]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @[[GLOB0]], align 8
+; CHECK-NEXT: [[TMP3:%.*]] = load atomic i64, ptr [[TMP2]] acquire, align 8
+; CHECK-NEXT: ret void
+;
+ %1 = addrspacecast ptr addrspace(1) @1 to ptr
+ store ptr %1, ptr @0, align 8
+ %2 = load ptr, ptr @0, align 8
+ %3 = load atomic i64, ptr %2 acquire, align 8
+ ret void
+}
+
+declare ptr @_Znwm(i64)
``````````
</details>
https://github.com/llvm/llvm-project/pull/153753
More information about the llvm-commits
mailing list