@@ -13,6 +13,8 @@ declare i32 @fn2()
13
13
14
14
declare i32 @fn3 ()
15
15
16
+ declare void @llvm.memcpy.p0i8.p0i8.i64 (ptr , ptr , i64 , i1 ) local_unnamed_addr
17
+
16
18
define void @stores_single_use_gep_constexpr () {
17
19
; CHECK-LABEL: @stores_single_use_gep_constexpr(
18
20
; CHECK-NEXT: entry:
@@ -51,3 +53,89 @@ entry:
51
53
store i32 0 , ptr inttoptr (i64 ptrtoint (ptr @global.20ptr to i64 ) to ptr ), align 8
52
54
ret void
53
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.
62
+ define 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
+ ;
71
+ entry:
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.
85
+ define 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
+ ;
112
+ entry:
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
+
118
+ for.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
+
125
+ if.then: ; preds = %for.body
126
+ call void @fn0 ()
127
+ br label %if.end
128
+
129
+ if.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
+
138
+ for.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
+ }
0 commit comments