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