1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; FIXME: This is technically incorrect because it might overwrite a poison 5; value. Stop folding it once #52930 is resolved. 6define void @store_of_undef(ptr %P) { 7; CHECK-LABEL: @store_of_undef( 8; CHECK-NEXT: ret void 9; 10 store i32 undef, ptr %P 11 ret void 12} 13 14define void @store_of_poison(ptr %P) { 15; CHECK-LABEL: @store_of_poison( 16; CHECK-NEXT: ret void 17; 18 store i32 poison, ptr %P 19 ret void 20} 21 22define void @store_into_undef(ptr %P) { 23; CHECK-LABEL: @store_into_undef( 24; CHECK-NEXT: store i32 123, ptr undef, align 4 25; CHECK-NEXT: ret void 26; 27 store i32 123, ptr undef 28 ret void 29} 30 31define void @store_into_null(ptr %P) { 32; CHECK-LABEL: @store_into_null( 33; CHECK-NEXT: store i32 poison, ptr null, align 4 34; CHECK-NEXT: ret void 35; 36 store i32 124, ptr null 37 ret void 38} 39 40define void @test2(ptr %P) { 41; CHECK-LABEL: @test2( 42; CHECK-NEXT: ret void 43; 44 %X = load i32, ptr %P 45 %Y = add i32 %X, 0 46 store i32 %Y, ptr %P 47 ret void 48} 49 50define void @store_at_gep_off_null_inbounds(i64 %offset) { 51; CHECK-LABEL: @store_at_gep_off_null_inbounds( 52; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, ptr null, i64 [[OFFSET:%.*]] 53; CHECK-NEXT: store i32 poison, ptr [[PTR]], align 4 54; CHECK-NEXT: ret void 55; 56 %ptr = getelementptr inbounds i32, ptr null, i64 %offset 57 store i32 24, ptr %ptr 58 ret void 59} 60 61define void @store_at_gep_off_null_not_inbounds(i64 %offset) { 62; CHECK-LABEL: @store_at_gep_off_null_not_inbounds( 63; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr null, i64 [[OFFSET:%.*]] 64; CHECK-NEXT: store i32 poison, ptr [[PTR]], align 4 65; CHECK-NEXT: ret void 66; 67 %ptr = getelementptr i32, ptr null, i64 %offset 68 store i32 24, ptr %ptr 69 ret void 70} 71 72define void @store_at_gep_off_no_null_opt(i64 %offset) #0 { 73; CHECK-LABEL: @store_at_gep_off_no_null_opt( 74; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i32, ptr null, i64 [[OFFSET:%.*]] 75; CHECK-NEXT: store i32 24, ptr [[PTR]], align 4 76; CHECK-NEXT: ret void 77; 78 %ptr = getelementptr inbounds i32, ptr null, i64 %offset 79 store i32 24, ptr %ptr 80 ret void 81} 82 83attributes #0 = { null_pointer_is_valid } 84 85;; Simple sinking tests 86 87; "if then else" 88define i32 @test3(i1 %C) { 89; CHECK-LABEL: @test3( 90; CHECK-NEXT: br i1 [[C:%.*]], label [[COND:%.*]], label [[COND2:%.*]] 91; CHECK: Cond: 92; CHECK-NEXT: br label [[CONT:%.*]] 93; CHECK: Cond2: 94; CHECK-NEXT: br label [[CONT]] 95; CHECK: Cont: 96; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ 47, [[COND2]] ], [ -987654321, [[COND]] ] 97; CHECK-NEXT: ret i32 [[STOREMERGE]] 98; 99 %A = alloca i32 100 br i1 %C, label %Cond, label %Cond2 101 102Cond: 103 store i32 -987654321, ptr %A 104 br label %Cont 105 106Cond2: 107 store i32 47, ptr %A 108 br label %Cont 109 110Cont: 111 %V = load i32, ptr %A 112 ret i32 %V 113} 114 115; "if then" 116define i32 @test4(i1 %C) { 117; CHECK-LABEL: @test4( 118; CHECK-NEXT: br i1 [[C:%.*]], label [[COND:%.*]], label [[CONT:%.*]] 119; CHECK: Cond: 120; CHECK-NEXT: br label [[CONT]] 121; CHECK: Cont: 122; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ -987654321, [[COND]] ], [ 47, [[TMP0:%.*]] ] 123; CHECK-NEXT: ret i32 [[STOREMERGE]] 124; 125 %A = alloca i32 126 store i32 47, ptr %A 127 br i1 %C, label %Cond, label %Cont 128 129Cond: 130 store i32 -987654321, ptr %A 131 br label %Cont 132 133Cont: 134 %V = load i32, ptr %A 135 ret i32 %V 136} 137 138; "if then" 139define void @test5(i1 %C, ptr %P) { 140; CHECK-LABEL: @test5( 141; CHECK-NEXT: br i1 [[C:%.*]], label [[COND:%.*]], label [[CONT:%.*]] 142; CHECK: Cond: 143; CHECK-NEXT: br label [[CONT]] 144; CHECK: Cont: 145; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ -987654321, [[COND]] ], [ 47, [[TMP0:%.*]] ] 146; CHECK-NEXT: store i32 [[STOREMERGE]], ptr [[P:%.*]], align 1 147; CHECK-NEXT: ret void 148; 149 store i32 47, ptr %P, align 1 150 br i1 %C, label %Cond, label %Cont 151 152Cond: 153 store i32 -987654321, ptr %P, align 1 154 br label %Cont 155 156Cont: 157 ret void 158} 159 160 161; PR14753 - merging two stores should preserve the TBAA tag. 162define void @test6(i32 %n, ptr %a, ptr %gi) nounwind uwtable ssp { 163; CHECK-LABEL: @test6( 164; CHECK-NEXT: entry: 165; CHECK-NEXT: br label [[FOR_COND:%.*]] 166; CHECK: for.cond: 167; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ 42, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ] 168; CHECK-NEXT: store i32 [[STOREMERGE]], ptr [[GI:%.*]], align 4, !tbaa [[TBAA0:![0-9]+]] 169; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[STOREMERGE]], [[N:%.*]] 170; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 171; CHECK: for.body: 172; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[STOREMERGE]] to i64 173; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[A:%.*]], i64 [[IDXPROM]] 174; CHECK-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA4:![0-9]+]] 175; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[GI]], align 4, !tbaa [[TBAA0]] 176; CHECK-NEXT: [[INC]] = add nsw i32 [[TMP0]], 1 177; CHECK-NEXT: br label [[FOR_COND]] 178; CHECK: for.end: 179; CHECK-NEXT: ret void 180; 181entry: 182 store i32 42, ptr %gi, align 4, !tbaa !0 183 br label %for.cond 184 185for.cond: 186 %storemerge = phi i32 [ 0, %entry ], [ %inc, %for.body ] 187 %0 = load i32, ptr %gi, align 4, !tbaa !0 188 %cmp = icmp slt i32 %0, %n 189 br i1 %cmp, label %for.body, label %for.end 190 191for.body: 192 %idxprom = sext i32 %0 to i64 193 %arrayidx = getelementptr inbounds float, ptr %a, i64 %idxprom 194 store float 0.000000e+00, ptr %arrayidx, align 4, !tbaa !3 195 %1 = load i32, ptr %gi, align 4, !tbaa !0 196 %inc = add nsw i32 %1, 1 197 store i32 %inc, ptr %gi, align 4, !tbaa !0 198 br label %for.cond 199 200for.end: 201 ret void 202} 203 204define void @dse1(ptr %p) { 205; CHECK-LABEL: @dse1( 206; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 207; CHECK-NEXT: ret void 208; 209 store i32 0, ptr %p 210 store i32 0, ptr %p 211 ret void 212} 213 214; Slightly subtle: if we're mixing atomic and non-atomic access to the 215; same location, then the contents of the location are undefined if there's 216; an actual race. As such, we're free to pick either store under the 217; assumption that we're not racing with any other thread. 218define void @dse2(ptr %p) { 219; CHECK-LABEL: @dse2( 220; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 4 221; CHECK-NEXT: ret void 222; 223 store atomic i32 0, ptr %p unordered, align 4 224 store i32 0, ptr %p 225 ret void 226} 227 228define void @dse3(ptr %p) { 229; CHECK-LABEL: @dse3( 230; CHECK-NEXT: store atomic i32 0, ptr [[P:%.*]] unordered, align 4 231; CHECK-NEXT: ret void 232; 233 store i32 0, ptr %p 234 store atomic i32 0, ptr %p unordered, align 4 235 ret void 236} 237 238define void @dse4(ptr %p) { 239; CHECK-LABEL: @dse4( 240; CHECK-NEXT: store atomic i32 0, ptr [[P:%.*]] unordered, align 4 241; CHECK-NEXT: ret void 242; 243 store atomic i32 0, ptr %p unordered, align 4 244 store atomic i32 0, ptr %p unordered, align 4 245 ret void 246} 247 248; Implementation limit - could remove unordered store here, but 249; currently don't. 250define void @dse5(ptr %p) { 251; CHECK-LABEL: @dse5( 252; CHECK-NEXT: store atomic i32 0, ptr [[P:%.*]] unordered, align 4 253; CHECK-NEXT: store atomic i32 0, ptr [[P]] seq_cst, align 4 254; CHECK-NEXT: ret void 255; 256 store atomic i32 0, ptr %p unordered, align 4 257 store atomic i32 0, ptr %p seq_cst, align 4 258 ret void 259} 260 261define void @write_back1(ptr %p) { 262; CHECK-LABEL: @write_back1( 263; CHECK-NEXT: ret void 264; 265 %v = load i32, ptr %p 266 store i32 %v, ptr %p 267 ret void 268} 269 270define void @write_back2(ptr %p) { 271; CHECK-LABEL: @write_back2( 272; CHECK-NEXT: ret void 273; 274 %v = load atomic i32, ptr %p unordered, align 4 275 store i32 %v, ptr %p 276 ret void 277} 278 279define void @write_back3(ptr %p) { 280; CHECK-LABEL: @write_back3( 281; CHECK-NEXT: ret void 282; 283 %v = load i32, ptr %p 284 store atomic i32 %v, ptr %p unordered, align 4 285 ret void 286} 287 288define void @write_back4(ptr %p) { 289; CHECK-LABEL: @write_back4( 290; CHECK-NEXT: ret void 291; 292 %v = load atomic i32, ptr %p unordered, align 4 293 store atomic i32 %v, ptr %p unordered, align 4 294 ret void 295} 296 297; Can't remove store due to ordering side effect 298define void @write_back5(ptr %p) { 299; CHECK-LABEL: @write_back5( 300; CHECK-NEXT: [[V:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 4 301; CHECK-NEXT: store atomic i32 [[V]], ptr [[P]] seq_cst, align 4 302; CHECK-NEXT: ret void 303; 304 %v = load atomic i32, ptr %p unordered, align 4 305 store atomic i32 %v, ptr %p seq_cst, align 4 306 ret void 307} 308 309define void @write_back6(ptr %p) { 310; CHECK-LABEL: @write_back6( 311; CHECK-NEXT: [[V:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4 312; CHECK-NEXT: ret void 313; 314 %v = load atomic i32, ptr %p seq_cst, align 4 315 store atomic i32 %v, ptr %p unordered, align 4 316 ret void 317} 318 319define void @write_back7(ptr %p) { 320; CHECK-LABEL: @write_back7( 321; CHECK-NEXT: [[V:%.*]] = load atomic volatile i32, ptr [[P:%.*]] seq_cst, align 4 322; CHECK-NEXT: ret void 323; 324 %v = load atomic volatile i32, ptr %p seq_cst, align 4 325 store atomic i32 %v, ptr %p unordered, align 4 326 ret void 327} 328 329@Unknown = external constant i32 330 331define void @store_to_constant() { 332; CHECK-LABEL: @store_to_constant( 333; CHECK-NEXT: ret void 334; 335 store i32 0, ptr @Unknown 336 ret void 337} 338 339; Delete stores to readonly noalias pointers. 340define void @store_to_readonly_noalias(ptr readonly noalias %0) { 341; CHECK-LABEL: @store_to_readonly_noalias( 342; CHECK-NEXT: ret void 343; 344 store i32 3, ptr %0, align 4 345 ret void 346} 347 348!0 = !{!4, !4, i64 0} 349!1 = !{!"omnipotent char", !2} 350!2 = !{!"Simple C/C++ TBAA"} 351!3 = !{!"float", !1} 352!4 = !{!"int", !1} 353