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