1; RUN: opt < %s -S -basicaa -licm | FileCheck %s 2; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s 3 4; Check that we can hoist unordered loads 5define i32 @test1(i32* nocapture %y) nounwind uwtable ssp { 6entry: 7 br label %loop 8 9loop: 10 %i = phi i32 [ %inc, %loop ], [ 0, %entry ] 11 %val = load atomic i32, i32* %y unordered, align 4 12 %inc = add nsw i32 %i, 1 13 %exitcond = icmp eq i32 %inc, %val 14 br i1 %exitcond, label %end, label %loop 15 16end: 17 ret i32 %val 18; CHECK-LABEL: define i32 @test1( 19; CHECK: load atomic 20; CHECK-NEXT: br label %loop 21} 22 23; Check that we don't sink/hoist monotonic loads 24; (Strictly speaking, it's not forbidden, but it's supposed to be possible to 25; use monotonic for spinlock-like constructs.) 26define i32 @test2(i32* nocapture %y) nounwind uwtable ssp { 27entry: 28 br label %loop 29 30loop: 31 %val = load atomic i32, i32* %y monotonic, align 4 32 %exitcond = icmp ne i32 %val, 0 33 br i1 %exitcond, label %end, label %loop 34 35end: 36 ret i32 %val 37; CHECK-LABEL: define i32 @test2( 38; CHECK: load atomic 39; CHECK-NEXT: %exitcond = icmp ne 40; CHECK-NEXT: br i1 %exitcond, label %end, label %loop 41} 42 43; Check that we hoist unordered around monotonic. 44; (The noalias shouldn't be necessary in theory, but LICM isn't quite that 45; smart yet.) 46define i32 @test3(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 47entry: 48 br label %loop 49 50loop: 51 %vala = load atomic i32, i32* %y monotonic, align 4 52 %valb = load atomic i32, i32* %x unordered, align 4 53 %exitcond = icmp ne i32 %vala, %valb 54 br i1 %exitcond, label %end, label %loop 55 56end: 57 ret i32 %vala 58; CHECK-LABEL: define i32 @test3( 59; CHECK: load atomic i32, i32* %x unordered 60; CHECK-NEXT: br label %loop 61} 62 63; We can sink an unordered store 64define i32 @test4(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 65entry: 66 br label %loop 67 68loop: 69 %vala = load atomic i32, i32* %y monotonic, align 4 70 store atomic i32 %vala, i32* %x unordered, align 4 71 %exitcond = icmp ne i32 %vala, 0 72 br i1 %exitcond, label %end, label %loop 73 74end: 75 ret i32 %vala 76; CHECK-LABEL: define i32 @test4( 77; CHECK-LABEL: loop: 78; CHECK: load atomic i32, i32* %y monotonic 79; CHECK-NOT: store 80; CHECK-LABEL: end: 81; CHECK-NEXT: %[[LCSSAPHI:.*]] = phi i32 [ %vala 82; CHECK: store atomic i32 %[[LCSSAPHI]], i32* %x unordered, align 4 83} 84 85; We currently don't handle ordered atomics. 86define i32 @test5(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 87entry: 88 br label %loop 89 90loop: 91 %vala = load atomic i32, i32* %y monotonic, align 4 92 store atomic i32 %vala, i32* %x release, align 4 93 %exitcond = icmp ne i32 %vala, 0 94 br i1 %exitcond, label %end, label %loop 95 96end: 97 ret i32 %vala 98; CHECK-LABEL: define i32 @test5( 99; CHECK: load atomic i32, i32* %y monotonic 100; CHECK-NEXT: store atomic 101} 102 103; We currently don't touch volatiles 104define i32 @test6(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 105entry: 106 br label %loop 107 108loop: 109 %vala = load atomic i32, i32* %y monotonic, align 4 110 store volatile i32 %vala, i32* %x, align 4 111 %exitcond = icmp ne i32 %vala, 0 112 br i1 %exitcond, label %end, label %loop 113 114end: 115 ret i32 %vala 116; CHECK-LABEL: define i32 @test6( 117; CHECK: load atomic i32, i32* %y monotonic 118; CHECK-NEXT: store volatile 119} 120 121; We currently don't touch volatiles 122define i32 @test6b(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 123entry: 124 br label %loop 125 126loop: 127 %vala = load atomic i32, i32* %y monotonic, align 4 128 store atomic volatile i32 %vala, i32* %x unordered, align 4 129 %exitcond = icmp ne i32 %vala, 0 130 br i1 %exitcond, label %end, label %loop 131 132end: 133 ret i32 %vala 134; CHECK-LABEL: define i32 @test6b( 135; CHECK: load atomic i32, i32* %y monotonic 136; CHECK-NEXT: store atomic volatile 137} 138 139; Mixing unorder atomics and normal loads/stores is 140; current unimplemented 141define i32 @test7(i32* nocapture noalias %x, i32* nocapture %y) nounwind uwtable ssp { 142entry: 143 br label %loop 144 145loop: 146 store i32 5, i32* %x 147 %vala = load atomic i32, i32* %y monotonic, align 4 148 store atomic i32 %vala, i32* %x unordered, align 4 149 %exitcond = icmp ne i32 %vala, 0 150 br i1 %exitcond, label %end, label %loop 151 152end: 153 ret i32 %vala 154; CHECK-LABEL: define i32 @test7( 155; CHECK: store i32 5, i32* %x 156; CHECK-NEXT: load atomic i32, i32* %y 157; CHECK-NEXT: store atomic i32 158} 159 160; Three provably noalias locations - we can sink normal and unordered, but 161; not monotonic 162define i32 @test7b(i32* nocapture noalias %x, i32* nocapture %y, i32* noalias nocapture %z) nounwind uwtable ssp { 163entry: 164 br label %loop 165 166loop: 167 store i32 5, i32* %x 168 %vala = load atomic i32, i32* %y monotonic, align 4 169 store atomic i32 %vala, i32* %z unordered, align 4 170 %exitcond = icmp ne i32 %vala, 0 171 br i1 %exitcond, label %end, label %loop 172 173end: 174 ret i32 %vala 175; CHECK-LABEL: define i32 @test7b( 176; CHECK: load atomic i32, i32* %y monotonic 177 178; CHECK-LABEL: end: 179; CHECK: store i32 5, i32* %x 180; CHECK: store atomic i32 %{{.+}}, i32* %z unordered, align 4 181} 182 183 184define i32 @test8(i32* nocapture noalias %x, i32* nocapture %y) { 185entry: 186 br label %loop 187 188loop: 189 %vala = load atomic i32, i32* %y monotonic, align 4 190 store atomic i32 %vala, i32* %x unordered, align 4 191 fence release 192 %exitcond = icmp ne i32 %vala, 0 193 br i1 %exitcond, label %end, label %loop 194 195end: 196 ret i32 %vala 197; CHECK-LABEL: define i32 @test8( 198; CHECK-LABEL: loop: 199; CHECK: load atomic i32, i32* %y monotonic 200; CHECK-NEXT: store atomic 201; CHECK-NEXT: fence 202} 203 204; Exact semantics of monotonic accesses are a bit vague in the C++ spec, 205; for the moment, be conservative and don't touch them. 206define i32 @test9(i32* nocapture noalias %x, i32* nocapture %y) { 207entry: 208 br label %loop 209 210loop: 211 %vala = load atomic i32, i32* %y monotonic, align 4 212 store atomic i32 %vala, i32* %x monotonic, align 4 213 %exitcond = icmp ne i32 %vala, 0 214 br i1 %exitcond, label %end, label %loop 215 216end: 217 ret i32 %vala 218; CHECK-LABEL: define i32 @test9( 219; CHECK-LABEL: loop: 220; CHECK: load atomic i32, i32* %y monotonic 221; CHECK-NEXT: store atomic i32 %vala, i32* %x monotonic, align 4 222} 223