Skip to content

Commit 69e4514

Browse files
authored
[GlobalOpt] Do not fold away addrspacecasts which may be runtime operations (#153753)
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 (CHERIoT-Platform/llvm-project@91afa60), but has been reimplemented with updated conventions, and a testcase constructed from scratch.
1 parent 97d5d48 commit 69e4514

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

llvm/lib/Transforms/IPO/GlobalOpt.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,9 +1133,6 @@ static bool
11331133
optimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
11341134
const DataLayout &DL,
11351135
function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1136-
// Ignore no-op GEPs and bitcasts.
1137-
StoredOnceVal = StoredOnceVal->stripPointerCasts();
1138-
11391136
// If we are dealing with a pointer global that is initialized to null and
11401137
// only has one (non-null) value stored into it, then we can optimize any
11411138
// users of the loaded value (often calls and loads) that would trap if the
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
2+
; RUN: opt -passes=globalopt < %s -S | FileCheck %s
3+
4+
; Test that we do not fold away addresscasts when optimizing once-stored
5+
; globals, as these may be runtime operations.
6+
7+
@g1 = internal global ptr null
8+
@g2 = addrspace(1) global i32 0
9+
10+
;.
11+
; CHECK: @g1 = internal unnamed_addr global ptr null
12+
; CHECK: @g2 = addrspace(1) global i32 0
13+
; CHECK: @g4 = local_unnamed_addr addrspace(1) global i32 0
14+
;.
15+
define i64 @test1() {
16+
; CHECK-LABEL: @test1(
17+
; CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(1) @g2 to ptr
18+
; CHECK-NEXT: store ptr [[TMP1]], ptr @g1, align 8
19+
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr @g1, align 8
20+
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 8
21+
; CHECK-NEXT: ret i64 [[TMP3]]
22+
;
23+
%l1 = addrspacecast ptr addrspace(1) @g2 to ptr
24+
store ptr %l1, ptr @g1, align 8
25+
%l2 = load ptr, ptr @g1, align 8
26+
%l3 = load i64, ptr %l2, align 8
27+
ret i64 %l3
28+
}
29+
30+
@g3 = internal global ptr null
31+
@g4 = addrspace(1) global i32 0
32+
33+
define i64 @test2() {
34+
; CHECK-LABEL: @test2(
35+
; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr addrspacecast (ptr addrspace(1) @g4 to ptr), align 8
36+
; CHECK-NEXT: ret i64 [[TMP1]]
37+
;
38+
store ptr addrspacecast (ptr addrspace(1) @g4 to ptr), ptr @g3, align 8
39+
%l1 = load ptr, ptr @g3, align 8
40+
%l2 = load i64, ptr %l1, align 8
41+
ret i64 %l2
42+
}

0 commit comments

Comments
 (0)