1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -S -early-cse | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test12( 4*9880d681SAndroid Build Coastguard Workerdefine i32 @test12(i1 %B, i32* %P1, i32* %P2) { 5*9880d681SAndroid Build Coastguard Worker %load0 = load i32, i32* %P1 6*9880d681SAndroid Build Coastguard Worker %1 = load atomic i32, i32* %P2 seq_cst, align 4 7*9880d681SAndroid Build Coastguard Worker %load1 = load i32, i32* %P1 8*9880d681SAndroid Build Coastguard Worker %sel = select i1 %B, i32 %load0, i32 %load1 9*9880d681SAndroid Build Coastguard Worker ret i32 %sel 10*9880d681SAndroid Build Coastguard Worker ; CHECK: load i32, i32* %P1 11*9880d681SAndroid Build Coastguard Worker ; CHECK: load i32, i32* %P1 12*9880d681SAndroid Build Coastguard Worker} 13*9880d681SAndroid Build Coastguard Worker 14*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test13( 15*9880d681SAndroid Build Coastguard Worker; atomic to non-atomic forwarding is legal 16*9880d681SAndroid Build Coastguard Workerdefine i32 @test13(i1 %B, i32* %P1) { 17*9880d681SAndroid Build Coastguard Worker %a = load atomic i32, i32* %P1 seq_cst, align 4 18*9880d681SAndroid Build Coastguard Worker %b = load i32, i32* %P1 19*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 20*9880d681SAndroid Build Coastguard Worker ret i32 %res 21*9880d681SAndroid Build Coastguard Worker ; CHECK: load atomic i32, i32* %P1 22*9880d681SAndroid Build Coastguard Worker ; CHECK: ret i32 0 23*9880d681SAndroid Build Coastguard Worker} 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test14( 26*9880d681SAndroid Build Coastguard Worker; atomic to unordered atomic forwarding is legal 27*9880d681SAndroid Build Coastguard Workerdefine i32 @test14(i1 %B, i32* %P1) { 28*9880d681SAndroid Build Coastguard Worker %a = load atomic i32, i32* %P1 seq_cst, align 4 29*9880d681SAndroid Build Coastguard Worker %b = load atomic i32, i32* %P1 unordered, align 4 30*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 31*9880d681SAndroid Build Coastguard Worker ret i32 %res 32*9880d681SAndroid Build Coastguard Worker ; CHECK: load atomic i32, i32* %P1 seq_cst 33*9880d681SAndroid Build Coastguard Worker ; CHECK-NEXT: ret i32 0 34*9880d681SAndroid Build Coastguard Worker} 35*9880d681SAndroid Build Coastguard Worker 36*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test15( 37*9880d681SAndroid Build Coastguard Worker; implementation restriction: can't forward to stonger 38*9880d681SAndroid Build Coastguard Worker; than unordered 39*9880d681SAndroid Build Coastguard Workerdefine i32 @test15(i1 %B, i32* %P1, i32* %P2) { 40*9880d681SAndroid Build Coastguard Worker %a = load atomic i32, i32* %P1 seq_cst, align 4 41*9880d681SAndroid Build Coastguard Worker %b = load atomic i32, i32* %P1 seq_cst, align 4 42*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 43*9880d681SAndroid Build Coastguard Worker ret i32 %res 44*9880d681SAndroid Build Coastguard Worker ; CHECK: load atomic i32, i32* %P1 45*9880d681SAndroid Build Coastguard Worker ; CHECK: load atomic i32, i32* %P1 46*9880d681SAndroid Build Coastguard Worker} 47*9880d681SAndroid Build Coastguard Worker 48*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test16( 49*9880d681SAndroid Build Coastguard Worker; forwarding non-atomic to atomic is wrong! (However, 50*9880d681SAndroid Build Coastguard Worker; it would be legal to use the later value in place of the 51*9880d681SAndroid Build Coastguard Worker; former in this particular example. We just don't 52*9880d681SAndroid Build Coastguard Worker; do that right now.) 53*9880d681SAndroid Build Coastguard Workerdefine i32 @test16(i1 %B, i32* %P1, i32* %P2) { 54*9880d681SAndroid Build Coastguard Worker %a = load i32, i32* %P1, align 4 55*9880d681SAndroid Build Coastguard Worker %b = load atomic i32, i32* %P1 unordered, align 4 56*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 57*9880d681SAndroid Build Coastguard Worker ret i32 %res 58*9880d681SAndroid Build Coastguard Worker ; CHECK: load i32, i32* %P1 59*9880d681SAndroid Build Coastguard Worker ; CHECK: load atomic i32, i32* %P1 60*9880d681SAndroid Build Coastguard Worker} 61*9880d681SAndroid Build Coastguard Worker 62*9880d681SAndroid Build Coastguard Worker; Can't DSE across a full fence 63*9880d681SAndroid Build Coastguard Workerdefine void @fence_seq_cst_store(i1 %B, i32* %P1, i32* %P2) { 64*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @fence_seq_cst_store 65*9880d681SAndroid Build Coastguard Worker; CHECK: store 66*9880d681SAndroid Build Coastguard Worker; CHECK: store atomic 67*9880d681SAndroid Build Coastguard Worker; CHECK: store 68*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 69*9880d681SAndroid Build Coastguard Worker store atomic i32 0, i32* %P2 seq_cst, align 4 70*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 71*9880d681SAndroid Build Coastguard Worker ret void 72*9880d681SAndroid Build Coastguard Worker} 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker; Can't DSE across a full fence 75*9880d681SAndroid Build Coastguard Workerdefine void @fence_seq_cst(i1 %B, i32* %P1, i32* %P2) { 76*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @fence_seq_cst 77*9880d681SAndroid Build Coastguard Worker; CHECK: store 78*9880d681SAndroid Build Coastguard Worker; CHECK: fence seq_cst 79*9880d681SAndroid Build Coastguard Worker; CHECK: store 80*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 81*9880d681SAndroid Build Coastguard Worker fence seq_cst 82*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 83*9880d681SAndroid Build Coastguard Worker ret void 84*9880d681SAndroid Build Coastguard Worker} 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker; Can't DSE across a full fence 87*9880d681SAndroid Build Coastguard Workerdefine void @fence_asm_sideeffect(i1 %B, i32* %P1, i32* %P2) { 88*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @fence_asm_sideeffect 89*9880d681SAndroid Build Coastguard Worker; CHECK: store 90*9880d681SAndroid Build Coastguard Worker; CHECK: call void asm sideeffect 91*9880d681SAndroid Build Coastguard Worker; CHECK: store 92*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 93*9880d681SAndroid Build Coastguard Worker call void asm sideeffect "", ""() 94*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 95*9880d681SAndroid Build Coastguard Worker ret void 96*9880d681SAndroid Build Coastguard Worker} 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Worker; Can't DSE across a full fence 99*9880d681SAndroid Build Coastguard Workerdefine void @fence_asm_memory(i1 %B, i32* %P1, i32* %P2) { 100*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @fence_asm_memory 101*9880d681SAndroid Build Coastguard Worker; CHECK: store 102*9880d681SAndroid Build Coastguard Worker; CHECK: call void asm 103*9880d681SAndroid Build Coastguard Worker; CHECK: store 104*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 105*9880d681SAndroid Build Coastguard Worker call void asm "", "~{memory}"() 106*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 107*9880d681SAndroid Build Coastguard Worker ret void 108*9880d681SAndroid Build Coastguard Worker} 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker; Can't remove a volatile load 111*9880d681SAndroid Build Coastguard Workerdefine i32 @volatile_load(i1 %B, i32* %P1, i32* %P2) { 112*9880d681SAndroid Build Coastguard Worker %a = load i32, i32* %P1, align 4 113*9880d681SAndroid Build Coastguard Worker %b = load volatile i32, i32* %P1, align 4 114*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 115*9880d681SAndroid Build Coastguard Worker ret i32 %res 116*9880d681SAndroid Build Coastguard Worker ; CHECK-LABEL: @volatile_load 117*9880d681SAndroid Build Coastguard Worker ; CHECK: load i32, i32* %P1 118*9880d681SAndroid Build Coastguard Worker ; CHECK: load volatile i32, i32* %P1 119*9880d681SAndroid Build Coastguard Worker} 120*9880d681SAndroid Build Coastguard Worker 121*9880d681SAndroid Build Coastguard Worker; Can't remove redundant volatile loads 122*9880d681SAndroid Build Coastguard Workerdefine i32 @redundant_volatile_load(i1 %B, i32* %P1, i32* %P2) { 123*9880d681SAndroid Build Coastguard Worker %a = load volatile i32, i32* %P1, align 4 124*9880d681SAndroid Build Coastguard Worker %b = load volatile i32, i32* %P1, align 4 125*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 126*9880d681SAndroid Build Coastguard Worker ret i32 %res 127*9880d681SAndroid Build Coastguard Worker ; CHECK-LABEL: @redundant_volatile_load 128*9880d681SAndroid Build Coastguard Worker ; CHECK: load volatile i32, i32* %P1 129*9880d681SAndroid Build Coastguard Worker ; CHECK: load volatile i32, i32* %P1 130*9880d681SAndroid Build Coastguard Worker ; CHECK: sub 131*9880d681SAndroid Build Coastguard Worker} 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker; Can't DSE a volatile store 134*9880d681SAndroid Build Coastguard Workerdefine void @volatile_store(i1 %B, i32* %P1, i32* %P2) { 135*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @volatile_store 136*9880d681SAndroid Build Coastguard Worker; CHECK: store volatile 137*9880d681SAndroid Build Coastguard Worker; CHECK: store 138*9880d681SAndroid Build Coastguard Worker store volatile i32 0, i32* %P1, align 4 139*9880d681SAndroid Build Coastguard Worker store i32 3, i32* %P1, align 4 140*9880d681SAndroid Build Coastguard Worker ret void 141*9880d681SAndroid Build Coastguard Worker} 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Worker; Can't DSE a redundant volatile store 144*9880d681SAndroid Build Coastguard Workerdefine void @redundant_volatile_store(i1 %B, i32* %P1, i32* %P2) { 145*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @redundant_volatile_store 146*9880d681SAndroid Build Coastguard Worker; CHECK: store volatile 147*9880d681SAndroid Build Coastguard Worker; CHECK: store volatile 148*9880d681SAndroid Build Coastguard Worker store volatile i32 0, i32* %P1, align 4 149*9880d681SAndroid Build Coastguard Worker store volatile i32 0, i32* %P1, align 4 150*9880d681SAndroid Build Coastguard Worker ret void 151*9880d681SAndroid Build Coastguard Worker} 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker; Can value forward from volatiles 154*9880d681SAndroid Build Coastguard Workerdefine i32 @test20(i1 %B, i32* %P1, i32* %P2) { 155*9880d681SAndroid Build Coastguard Worker %a = load volatile i32, i32* %P1, align 4 156*9880d681SAndroid Build Coastguard Worker %b = load i32, i32* %P1, align 4 157*9880d681SAndroid Build Coastguard Worker %res = sub i32 %a, %b 158*9880d681SAndroid Build Coastguard Worker ret i32 %res 159*9880d681SAndroid Build Coastguard Worker ; CHECK-LABEL: @test20 160*9880d681SAndroid Build Coastguard Worker ; CHECK: load volatile i32, i32* %P1 161*9880d681SAndroid Build Coastguard Worker ; CHECK: ret i32 0 162*9880d681SAndroid Build Coastguard Worker} 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker; Can DSE a non-volatile store in favor of a volatile one 165*9880d681SAndroid Build Coastguard Worker; currently a missed optimization 166*9880d681SAndroid Build Coastguard Workerdefine void @test21(i1 %B, i32* %P1, i32* %P2) { 167*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test21 168*9880d681SAndroid Build Coastguard Worker; CHECK: store 169*9880d681SAndroid Build Coastguard Worker; CHECK: store volatile 170*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 171*9880d681SAndroid Build Coastguard Worker store volatile i32 3, i32* %P1, align 4 172*9880d681SAndroid Build Coastguard Worker ret void 173*9880d681SAndroid Build Coastguard Worker} 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker; Can DSE a normal store in favor of a unordered one 176*9880d681SAndroid Build Coastguard Workerdefine void @test22(i1 %B, i32* %P1, i32* %P2) { 177*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test22 178*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic 179*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 180*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 unordered, align 4 181*9880d681SAndroid Build Coastguard Worker ret void 182*9880d681SAndroid Build Coastguard Worker} 183*9880d681SAndroid Build Coastguard Worker 184*9880d681SAndroid Build Coastguard Worker; Can also DSE a unordered store in favor of a normal one 185*9880d681SAndroid Build Coastguard Workerdefine void @test23(i1 %B, i32* %P1, i32* %P2) { 186*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test23 187*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store i32 0 188*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 unordered, align 4 189*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 190*9880d681SAndroid Build Coastguard Worker ret void 191*9880d681SAndroid Build Coastguard Worker} 192*9880d681SAndroid Build Coastguard Worker 193*9880d681SAndroid Build Coastguard Worker; As an implementation limitation, can't remove ordered stores 194*9880d681SAndroid Build Coastguard Worker; Note that we could remove the earlier store if we could 195*9880d681SAndroid Build Coastguard Worker; represent the required ordering. 196*9880d681SAndroid Build Coastguard Workerdefine void @test24(i1 %B, i32* %P1, i32* %P2) { 197*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test24 198*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic 199*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store i32 0 200*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 release, align 4 201*9880d681SAndroid Build Coastguard Worker store i32 0, i32* %P1, align 4 202*9880d681SAndroid Build Coastguard Worker ret void 203*9880d681SAndroid Build Coastguard Worker} 204*9880d681SAndroid Build Coastguard Worker 205*9880d681SAndroid Build Coastguard Worker; Can't remove volatile stores - each is independently observable and 206*9880d681SAndroid Build Coastguard Worker; the count of such stores is an observable program side effect. 207*9880d681SAndroid Build Coastguard Workerdefine void @test25(i1 %B, i32* %P1, i32* %P2) { 208*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test25 209*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store volatile 210*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store volatile 211*9880d681SAndroid Build Coastguard Worker store volatile i32 3, i32* %P1, align 4 212*9880d681SAndroid Build Coastguard Worker store volatile i32 0, i32* %P1, align 4 213*9880d681SAndroid Build Coastguard Worker ret void 214*9880d681SAndroid Build Coastguard Worker} 215*9880d681SAndroid Build Coastguard Worker 216*9880d681SAndroid Build Coastguard Worker; Can DSE a unordered store in favor of a unordered one 217*9880d681SAndroid Build Coastguard Workerdefine void @test26(i1 %B, i32* %P1, i32* %P2) { 218*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test26 219*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic i32 3, i32* %P1 unordered, align 4 220*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret 221*9880d681SAndroid Build Coastguard Worker store atomic i32 0, i32* %P1 unordered, align 4 222*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 unordered, align 4 223*9880d681SAndroid Build Coastguard Worker ret void 224*9880d681SAndroid Build Coastguard Worker} 225*9880d681SAndroid Build Coastguard Worker 226*9880d681SAndroid Build Coastguard Worker; Can DSE a unordered store in favor of a ordered one, 227*9880d681SAndroid Build Coastguard Worker; but current don't due to implementation limits 228*9880d681SAndroid Build Coastguard Workerdefine void @test27(i1 %B, i32* %P1, i32* %P2) { 229*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test27 230*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4 231*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4 232*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret 233*9880d681SAndroid Build Coastguard Worker store atomic i32 0, i32* %P1 unordered, align 4 234*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 release, align 4 235*9880d681SAndroid Build Coastguard Worker ret void 236*9880d681SAndroid Build Coastguard Worker} 237*9880d681SAndroid Build Coastguard Worker 238*9880d681SAndroid Build Coastguard Worker; Can DSE an unordered atomic store in favor of an 239*9880d681SAndroid Build Coastguard Worker; ordered one, but current don't due to implementation limits 240*9880d681SAndroid Build Coastguard Workerdefine void @test28(i1 %B, i32* %P1, i32* %P2) { 241*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test28 242*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic i32 0, i32* %P1 unordered, align 4 243*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic i32 3, i32* %P1 release, align 4 244*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret 245*9880d681SAndroid Build Coastguard Worker store atomic i32 0, i32* %P1 unordered, align 4 246*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 release, align 4 247*9880d681SAndroid Build Coastguard Worker ret void 248*9880d681SAndroid Build Coastguard Worker} 249*9880d681SAndroid Build Coastguard Worker 250*9880d681SAndroid Build Coastguard Worker; As an implementation limitation, can't remove ordered stores 251*9880d681SAndroid Build Coastguard Worker; see also: @test24 252*9880d681SAndroid Build Coastguard Workerdefine void @test29(i1 %B, i32* %P1, i32* %P2) { 253*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test29 254*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic 255*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: store atomic 256*9880d681SAndroid Build Coastguard Worker store atomic i32 3, i32* %P1 release, align 4 257*9880d681SAndroid Build Coastguard Worker store atomic i32 0, i32* %P1 unordered, align 4 258*9880d681SAndroid Build Coastguard Worker ret void 259*9880d681SAndroid Build Coastguard Worker} 260