1; Tests that check our handling of volatile instructions encountered 2; when scanning for dependencies 3; RUN: opt -basicaa -gvn -S < %s | FileCheck %s 4 5; Check that we can bypass a volatile load when searching 6; for dependencies of a non-volatile load 7define i32 @test1(i32* nocapture %p, i32* nocapture %q) { 8; CHECK-LABEL: test1 9; CHECK: %0 = load volatile i32, i32* %q 10; CHECK-NEXT: ret i32 0 11entry: 12 %x = load i32, i32* %p 13 load volatile i32, i32* %q 14 %y = load i32, i32* %p 15 %add = sub i32 %y, %x 16 ret i32 %add 17} 18 19; We can not value forward if the query instruction is 20; volatile, this would be (in effect) removing the volatile load 21define i32 @test2(i32* nocapture %p, i32* nocapture %q) { 22; CHECK-LABEL: test2 23; CHECK: %x = load i32, i32* %p 24; CHECK-NEXT: %y = load volatile i32, i32* %p 25; CHECK-NEXT: %add = sub i32 %y, %x 26entry: 27 %x = load i32, i32* %p 28 %y = load volatile i32, i32* %p 29 %add = sub i32 %y, %x 30 ret i32 %add 31} 32 33; If the query instruction is itself volatile, we *cannot* 34; reorder it even if p and q are noalias 35define i32 @test3(i32* noalias nocapture %p, i32* noalias nocapture %q) { 36; CHECK-LABEL: test3 37; CHECK: %x = load i32, i32* %p 38; CHECK-NEXT: %0 = load volatile i32, i32* %q 39; CHECK-NEXT: %y = load volatile i32, i32* %p 40entry: 41 %x = load i32, i32* %p 42 load volatile i32, i32* %q 43 %y = load volatile i32, i32* %p 44 %add = sub i32 %y, %x 45 ret i32 %add 46} 47 48; If an encountered instruction is both volatile and ordered, 49; we need to use the strictest ordering of either. In this 50; case, the ordering prevents forwarding. 51define i32 @test4(i32* noalias nocapture %p, i32* noalias nocapture %q) { 52; CHECK-LABEL: test4 53; CHECK: %x = load i32, i32* %p 54; CHECK-NEXT: %0 = load atomic volatile i32, i32* %q seq_cst 55; CHECK-NEXT: %y = load atomic i32, i32* %p seq_cst 56entry: 57 %x = load i32, i32* %p 58 load atomic volatile i32, i32* %q seq_cst, align 4 59 %y = load atomic i32, i32* %p seq_cst, align 4 60 %add = sub i32 %y, %x 61 ret i32 %add 62} 63 64; Value forwarding from a volatile load is perfectly legal 65define i32 @test5(i32* nocapture %p, i32* nocapture %q) { 66; CHECK-LABEL: test5 67; CHECK: %x = load volatile i32, i32* %p 68; CHECK-NEXT: ret i32 0 69entry: 70 %x = load volatile i32, i32* %p 71 %y = load i32, i32* %p 72 %add = sub i32 %y, %x 73 ret i32 %add 74} 75 76; Does cross block redundancy elimination work with volatiles? 77define i32 @test6(i32* noalias nocapture %p, i32* noalias nocapture %q) { 78; CHECK-LABEL: test6 79; CHECK: %y1 = load i32, i32* %p 80; CHECK-LABEL: header 81; CHECK: %x = load volatile i32, i32* %q 82; CHECK-NEXT: %add = sub i32 %y1, %x 83entry: 84 %y1 = load i32, i32* %p 85 call void @use(i32 %y1) 86 br label %header 87header: 88 %x = load volatile i32, i32* %q 89 %y = load i32, i32* %p 90 %add = sub i32 %y, %x 91 %cnd = icmp eq i32 %add, 0 92 br i1 %cnd, label %exit, label %header 93exit: 94 ret i32 %add 95} 96 97; Does cross block PRE work with volatiles? 98define i32 @test7(i1 %c, i32* noalias nocapture %p, i32* noalias nocapture %q) { 99; CHECK-LABEL: test7 100; CHECK-LABEL: entry.header_crit_edge: 101; CHECK: %y.pre = load i32, i32* %p 102; CHECK-LABEL: skip: 103; CHECK: %y1 = load i32, i32* %p 104; CHECK-LABEL: header: 105; CHECK: %y = phi i32 106; CHECK-NEXT: %x = load volatile i32, i32* %q 107; CHECK-NEXT: %add = sub i32 %y, %x 108entry: 109 br i1 %c, label %header, label %skip 110skip: 111 %y1 = load i32, i32* %p 112 call void @use(i32 %y1) 113 br label %header 114header: 115 %x = load volatile i32, i32* %q 116 %y = load i32, i32* %p 117 %add = sub i32 %y, %x 118 %cnd = icmp eq i32 %add, 0 119 br i1 %cnd, label %exit, label %header 120exit: 121 ret i32 %add 122} 123 124; Another volatile PRE case - two paths through a loop 125; load in preheader, one path read only, one not 126define i32 @test8(i1 %b, i1 %c, i32* noalias %p, i32* noalias %q) { 127; CHECK-LABEL: test8 128; CHECK-LABEL: entry 129; CHECK: %y1 = load i32, i32* %p 130; CHECK-LABEL: header: 131; CHECK: %y = phi i32 132; CHECK-NEXT: %x = load volatile i32, i32* %q 133; CHECK-NOT: load 134; CHECK-LABEL: skip.header_crit_edge: 135; CHECK: %y.pre = load i32, i32* %p 136entry: 137 %y1 = load i32, i32* %p 138 call void @use(i32 %y1) 139 br label %header 140header: 141 %x = load volatile i32, i32* %q 142 %y = load i32, i32* %p 143 call void @use(i32 %y) 144 br i1 %b, label %skip, label %header 145skip: 146 ; escaping the arguments is explicitly required since we marked 147 ; them noalias 148 call void @clobber(i32* %p, i32* %q) 149 br i1 %c, label %header, label %exit 150exit: 151 %add = sub i32 %y, %x 152 ret i32 %add 153} 154 155define i32 @test9(i32* %V) { 156entry: 157 %load = load volatile i32, i32* %V, !range !0 158 ret i32 %load 159} 160; CHECK-LABEL: test9 161; CHECK: load volatile 162; CHECK: ret i32 0 163 164declare void @use(i32) readonly 165declare void @clobber(i32* %p, i32* %q) 166 167!0 = !{ i32 0, i32 1 } 168