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