xref: /llvm-project/llvm/test/Transforms/GlobalOpt/cleanup-pointer-root-users-gep-constexpr.ll (revision 39bfdb7f33f7f53ab662c5cea25129c45a9b4c11)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=globalopt -S %s | FileCheck %s
3
4%struct.global.20ptr = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }
5
6@global.20ptr = internal unnamed_addr global %struct.global.20ptr zeroinitializer
7
8declare i32 @fn0()
9
10declare i32 @fn1()
11
12declare i32 @fn2()
13
14declare i32 @fn3()
15
16declare void @llvm.memcpy.p0i8.p0i8.i64(ptr, ptr, i64, i1) local_unnamed_addr
17
18define void @stores_single_use_gep_constexpr() {
19; CHECK-LABEL: @stores_single_use_gep_constexpr(
20; CHECK-NEXT:  entry:
21; CHECK-NEXT:    ret void
22;
23entry:
24  store ptr @fn0, ptr @global.20ptr, align 8
25  store ptr @fn1, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 1), align 8
26  store ptr @fn2, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 2), align 8
27  store ptr @fn3, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 3), align 8
28  store ptr @fn0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 4), align 8
29  store ptr @fn1, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 5), align 8
30  store ptr @fn2, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 6), align 8
31  store ptr @fn3, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 7), align 8
32  store ptr @fn0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 8), align 8
33  ret void
34}
35
36define void @stores_multi_use_gep_constexpr() {
37; CHECK-LABEL: @stores_multi_use_gep_constexpr(
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    ret void
40;
41entry:
42  store i32 0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 16), align 8
43  store i32 0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 16), align 8
44  ret void
45}
46
47define void @stores_ptrtoint_constexpr() {
48; CHECK-LABEL: @stores_ptrtoint_constexpr(
49; CHECK-NEXT:  entry:
50; CHECK-NEXT:    ret void
51;
52entry:
53  store i32 0, ptr inttoptr (i64 ptrtoint (ptr @global.20ptr to i64) to ptr), align 8
54  ret void
55}
56
57@gv = internal unnamed_addr global [3 x ptr] zeroinitializer, align 16
58@gv2 = internal unnamed_addr global i32 0, align 4
59
60;; This is a negative test which includes a load from @gv. No stores
61;; or memintrinsics with destination @gv should be removed.
62define i32 @load_from_gv_no_remove() local_unnamed_addr {
63; CHECK-LABEL: @load_from_gv_no_remove(
64; CHECK-NEXT:  entry:
65; CHECK-NEXT:    [[E:%.*]] = alloca i32, align 4
66; CHECK-NEXT:    store ptr [[E]], ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16
67; CHECK-NEXT:    [[LOAD_B:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16
68; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr @gv, ptr @gv2, i64 8, i1 false)
69; CHECK-NEXT:    ret i32 0
70;
71entry:
72  %e = alloca i32, align 4
73  store ptr %e, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16
74  %load.b = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16
75  call void @llvm.memcpy.p0i8.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 0), ptr @gv2, i64 8, i1 false)
76  ret i32 0
77}
78
79@a = internal unnamed_addr global i32 0, align 4
80@b = internal unnamed_addr global [3 x ptr] zeroinitializer, align 16
81
82;; This test is extracted from the issue reported in #64680, with an
83;; additional memcpy and a memset. Ensure all stores and memintrinsics with
84;; destination @b are removed as @b is dead.
85define i32 @load_gv_from_op_remove_store(ptr %p) local_unnamed_addr {
86; CHECK-LABEL: @load_gv_from_op_remove_store(
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    [[E:%.*]] = alloca i32, align 4
89; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, ptr @a, align 4
90; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[DOTPR]], 3
91; CHECK-NEXT:    br i1 [[CMP1]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
92; CHECK:       for.body:
93; CHECK-NEXT:    store i32 8, ptr [[E]], align 4
94; CHECK-NEXT:    call void @fn1()
95; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[E]], align 4
96; CHECK-NEXT:    [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP0]], 0
97; CHECK-NEXT:    br i1 [[TOBOOL_NOT]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
98; CHECK:       if.then:
99; CHECK-NEXT:    call void @fn0()
100; CHECK-NEXT:    br label [[IF_END]]
101; CHECK:       if.end:
102; CHECK-NEXT:    store ptr [[E]], ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 2), align 16
103; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr @a, align 4
104; CHECK-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP1]], 1
105; CHECK-NEXT:    store i32 [[INC]], ptr @a, align 4
106; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2
107; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
108; CHECK:       for.end:
109; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr @b, ptr [[P:%.*]], i64 8, i1 false)
110; CHECK-NEXT:    ret i32 0
111;
112entry:
113  %e = alloca i32, align 4
114  %.pr = load i32, ptr @a, align 4
115  %cmp1 = icmp slt i32 %.pr, 3
116  br i1 %cmp1, label %for.body, label %for.end
117
118for.body:                                         ; preds = %entry, %if.end
119  store i32 8, ptr %e, align 4
120  call void @fn1()
121  %0 = load i32, ptr %e, align 4
122  %tobool.not = icmp eq i32 %0, 0
123  br i1 %tobool.not, label %if.then, label %if.end
124
125if.then:                                          ; preds = %for.body
126  call void @fn0()
127  br label %if.end
128
129if.end:                                           ; preds = %if.then, %for.body
130  store ptr %e, ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 2), align 16
131  %1 = load i32, ptr @a, align 4
132  %inc = add nsw i32 %1, 1
133  store i32 %inc, ptr @a, align 4
134  %cmp = icmp slt i32 %1, 2
135  call void @llvm.memset.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 0), i8 0, i64 8, i1 false)
136  br i1 %cmp, label %for.body, label %for.end
137
138for.end:                                          ; preds = %if.end, %entry
139  call void @llvm.memcpy.p0i8.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 0), ptr %p, i64 8, i1 false)
140  ret i32 0
141}
142