@@ -13,6 +13,8 @@ declare i32 @fn2()
1313
1414declare i32 @fn3 ()
1515
16+ declare void @llvm.memcpy.p0i8.p0i8.i64 (ptr , ptr , i64 , i1 ) local_unnamed_addr
17+
1618define void @stores_single_use_gep_constexpr () {
1719; CHECK-LABEL: @stores_single_use_gep_constexpr(
1820; CHECK-NEXT: entry:
@@ -51,3 +53,89 @@ entry:
5153 store i32 0 , ptr inttoptr (i64 ptrtoint (ptr @global.20ptr to i64 ) to ptr ), align 8
5254 ret void
5355}
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 @main_with_load_from_b () local_unnamed_addr {
63+ ; CHECK-LABEL: @main_with_load_from_b(
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 @main (ptr %p ) local_unnamed_addr {
86+ ; CHECK-LABEL: @main(
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