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