1; RUN: opt < %s -S -early-cse | FileCheck %s 2; RUN: opt < %s -S -passes=early-cse | FileCheck %s 3 4declare void @llvm.assume(i1) nounwind 5 6; CHECK-LABEL: @test1( 7define void @test1(i8 %V, i32 *%P) { 8 %A = bitcast i64 42 to double ;; dead 9 %B = add i32 4, 19 ;; constant folds 10 store i32 %B, i32* %P 11 ; CHECK-NEXT: store i32 23, i32* %P 12 13 %C = zext i8 %V to i32 14 %D = zext i8 %V to i32 ;; CSE 15 store volatile i32 %C, i32* %P 16 store volatile i32 %D, i32* %P 17 ; CHECK-NEXT: %C = zext i8 %V to i32 18 ; CHECK-NEXT: store volatile i32 %C 19 ; CHECK-NEXT: store volatile i32 %C 20 21 %E = add i32 %C, %C 22 %F = add i32 %C, %C 23 store volatile i32 %E, i32* %P 24 store volatile i32 %F, i32* %P 25 ; CHECK-NEXT: %E = add i32 %C, %C 26 ; CHECK-NEXT: store volatile i32 %E 27 ; CHECK-NEXT: store volatile i32 %E 28 29 %G = add nuw i32 %C, %C ;; not a CSE with E 30 store volatile i32 %G, i32* %P 31 ; CHECK-NEXT: %G = add nuw i32 %C, %C 32 ; CHECK-NEXT: store volatile i32 %G 33 ret void 34} 35 36 37;; Simple load value numbering. 38; CHECK-LABEL: @test2( 39define i32 @test2(i32 *%P) { 40 %V1 = load i32, i32* %P 41 %V2 = load i32, i32* %P 42 %Diff = sub i32 %V1, %V2 43 ret i32 %Diff 44 ; CHECK: ret i32 0 45} 46 47; CHECK-LABEL: @test2a( 48define i32 @test2a(i32 *%P, i1 %b) { 49 %V1 = load i32, i32* %P 50 tail call void @llvm.assume(i1 %b) 51 %V2 = load i32, i32* %P 52 %Diff = sub i32 %V1, %V2 53 ret i32 %Diff 54 ; CHECK: ret i32 0 55} 56 57;; Cross block load value numbering. 58; CHECK-LABEL: @test3( 59define i32 @test3(i32 *%P, i1 %Cond) { 60 %V1 = load i32, i32* %P 61 br i1 %Cond, label %T, label %F 62T: 63 store i32 4, i32* %P 64 ret i32 42 65F: 66 %V2 = load i32, i32* %P 67 %Diff = sub i32 %V1, %V2 68 ret i32 %Diff 69 ; CHECK: F: 70 ; CHECK: ret i32 0 71} 72 73; CHECK-LABEL: @test3a( 74define i32 @test3a(i32 *%P, i1 %Cond, i1 %b) { 75 %V1 = load i32, i32* %P 76 br i1 %Cond, label %T, label %F 77T: 78 store i32 4, i32* %P 79 ret i32 42 80F: 81 tail call void @llvm.assume(i1 %b) 82 %V2 = load i32, i32* %P 83 %Diff = sub i32 %V1, %V2 84 ret i32 %Diff 85 ; CHECK: F: 86 ; CHECK: ret i32 0 87} 88 89;; Cross block load value numbering stops when stores happen. 90; CHECK-LABEL: @test4( 91define i32 @test4(i32 *%P, i1 %Cond) { 92 %V1 = load i32, i32* %P 93 br i1 %Cond, label %T, label %F 94T: 95 ret i32 42 96F: 97 ; Clobbers V1 98 store i32 42, i32* %P 99 100 %V2 = load i32, i32* %P 101 %Diff = sub i32 %V1, %V2 102 ret i32 %Diff 103 ; CHECK: F: 104 ; CHECK: ret i32 %Diff 105} 106 107declare i32 @func(i32 *%P) readonly 108 109;; Simple call CSE'ing. 110; CHECK-LABEL: @test5( 111define i32 @test5(i32 *%P) { 112 %V1 = call i32 @func(i32* %P) 113 %V2 = call i32 @func(i32* %P) 114 %Diff = sub i32 %V1, %V2 115 ret i32 %Diff 116 ; CHECK: ret i32 0 117} 118 119;; Trivial Store->load forwarding 120; CHECK-LABEL: @test6( 121define i32 @test6(i32 *%P) { 122 store i32 42, i32* %P 123 %V1 = load i32, i32* %P 124 ret i32 %V1 125 ; CHECK: ret i32 42 126} 127 128; CHECK-LABEL: @test6a( 129define i32 @test6a(i32 *%P, i1 %b) { 130 store i32 42, i32* %P 131 tail call void @llvm.assume(i1 %b) 132 %V1 = load i32, i32* %P 133 ret i32 %V1 134 ; CHECK: ret i32 42 135} 136 137;; Trivial dead store elimination. 138; CHECK-LABEL: @test7( 139define void @test7(i32 *%P) { 140 store i32 42, i32* %P 141 store i32 45, i32* %P 142 ret void 143 ; CHECK-NEXT: store i32 45 144 ; CHECK-NEXT: ret void 145} 146 147;; Readnone functions aren't invalidated by stores. 148; CHECK-LABEL: @test8( 149define i32 @test8(i32 *%P) { 150 %V1 = call i32 @func(i32* %P) readnone 151 store i32 4, i32* %P 152 %V2 = call i32 @func(i32* %P) readnone 153 %Diff = sub i32 %V1, %V2 154 ret i32 %Diff 155 ; CHECK: ret i32 0 156} 157 158;; Trivial DSE can't be performed across a readonly call. The call 159;; can observe the earlier write. 160; CHECK-LABEL: @test9( 161define i32 @test9(i32 *%P) { 162 store i32 4, i32* %P 163 %V1 = call i32 @func(i32* %P) readonly 164 store i32 5, i32* %P 165 ret i32 %V1 166 ; CHECK: store i32 4, i32* %P 167 ; CHECK-NEXT: %V1 = call i32 @func(i32* %P) 168 ; CHECK-NEXT: store i32 5, i32* %P 169 ; CHECK-NEXT: ret i32 %V1 170} 171 172;; Trivial DSE can be performed across a readnone call. 173; CHECK-LABEL: @test10 174define i32 @test10(i32 *%P) { 175 store i32 4, i32* %P 176 %V1 = call i32 @func(i32* %P) readnone 177 store i32 5, i32* %P 178 ret i32 %V1 179 ; CHECK-NEXT: %V1 = call i32 @func(i32* %P) 180 ; CHECK-NEXT: store i32 5, i32* %P 181 ; CHECK-NEXT: ret i32 %V1 182} 183 184;; Trivial dead store elimination - should work for an entire series of dead stores too. 185; CHECK-LABEL: @test11( 186define void @test11(i32 *%P) { 187 store i32 42, i32* %P 188 store i32 43, i32* %P 189 store i32 44, i32* %P 190 store i32 45, i32* %P 191 ret void 192 ; CHECK-NEXT: store i32 45 193 ; CHECK-NEXT: ret void 194} 195 196; CHECK-LABEL: @test12( 197define i32 @test12(i1 %B, i32* %P1, i32* %P2) { 198 %load0 = load i32, i32* %P1 199 %1 = load atomic i32, i32* %P2 seq_cst, align 4 200 %load1 = load i32, i32* %P1 201 %sel = select i1 %B, i32 %load0, i32 %load1 202 ret i32 %sel 203 ; CHECK: load i32, i32* %P1 204 ; CHECK: load i32, i32* %P1 205} 206 207define void @dse1(i32 *%P) { 208; CHECK-LABEL: @dse1 209; CHECK-NOT: store 210 %v = load i32, i32* %P 211 store i32 %v, i32* %P 212 ret void 213} 214 215define void @dse2(i32 *%P) { 216; CHECK-LABEL: @dse2 217; CHECK-NOT: store 218 %v = load atomic i32, i32* %P seq_cst, align 4 219 store i32 %v, i32* %P 220 ret void 221} 222 223define void @dse3(i32 *%P) { 224; CHECK-LABEL: @dse3 225; CHECK-NOT: store 226 %v = load atomic i32, i32* %P seq_cst, align 4 227 store atomic i32 %v, i32* %P unordered, align 4 228 ret void 229} 230 231define i32 @dse4(i32 *%P, i32 *%Q) { 232; CHECK-LABEL: @dse4 233; CHECK-NOT: store 234; CHECK: ret i32 0 235 %a = load i32, i32* %Q 236 %v = load atomic i32, i32* %P unordered, align 4 237 store atomic i32 %v, i32* %P unordered, align 4 238 %b = load i32, i32* %Q 239 %res = sub i32 %a, %b 240 ret i32 %res 241} 242 243; Note that in this example, %P and %Q could in fact be the same 244; pointer. %v could be different than the value observed for %a 245; and that's okay because we're using relaxed memory ordering. 246; The only guarantee we have to provide is that each of the loads 247; has to observe some value written to that location. We do 248; not have to respect the order in which those writes were done. 249define i32 @dse5(i32 *%P, i32 *%Q) { 250; CHECK-LABEL: @dse5 251; CHECK-NOT: store 252; CHECK: ret i32 0 253 %v = load atomic i32, i32* %P unordered, align 4 254 %a = load atomic i32, i32* %Q unordered, align 4 255 store atomic i32 %v, i32* %P unordered, align 4 256 %b = load atomic i32, i32* %Q unordered, align 4 257 %res = sub i32 %a, %b 258 ret i32 %res 259} 260 261 262define void @dse_neg1(i32 *%P) { 263; CHECK-LABEL: @dse_neg1 264; CHECK: store 265 %v = load i32, i32* %P 266 store i32 5, i32* %P 267 ret void 268} 269 270; Could remove the store, but only if ordering was somehow 271; encoded. 272define void @dse_neg2(i32 *%P) { 273; CHECK-LABEL: @dse_neg2 274; CHECK: store 275 %v = load i32, i32* %P 276 store atomic i32 %v, i32* %P seq_cst, align 4 277 ret void 278} 279 280