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 7 define 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 11 entry: 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 21 define 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 26 entry: 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 35 define 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 40 entry: 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. 51 define 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 56 entry: 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 65 define 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 69 entry: 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? 77 define 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 83 entry: 84 %y1 = load i32, i32* %p 85 call void @use(i32 %y1) 86 br label %header 87 header: 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 93 exit: 94 ret i32 %add 95 } 96 97 ; Does cross block PRE work with volatiles? 98 define 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 108 entry: 109 br i1 %c, label %header, label %skip 110 skip: 111 %y1 = load i32, i32* %p 112 call void @use(i32 %y1) 113 br label %header 114 header: 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 120 exit: 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 126 define 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 136 entry: 137 %y1 = load i32, i32* %p 138 call void @use(i32 %y1) 139 br label %header 140 header: 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 145 skip: 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 150 exit: 151 %add = sub i32 %y, %x 152 ret i32 %add 153 } 154 155 define i32 @test9(i32* %V) { 156 entry: 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 164 declare void @use(i32) readonly 165 declare void @clobber(i32* %p, i32* %q) 166 167 !0 = !{ i32 0, i32 1 } 168