1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Tests that check our handling of volatile instructions encountered 3; when scanning for dependencies 4; RUN: opt -passes=gvn -enable-split-backedge-in-load-pre -S < %s | FileCheck %s 5 6; Check that we can bypass a volatile load when searching 7; for dependencies of a non-volatile load 8define i32 @test1(ptr nocapture %p, ptr nocapture %q) { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4 12; CHECK-NEXT: ret i32 0 13; 14entry: 15 %x = load i32, ptr %p 16 load volatile i32, ptr %q 17 %y = load i32, ptr %p 18 %add = sub i32 %y, %x 19 ret i32 %add 20} 21 22; We can not value forward if the query instruction is 23; volatile, this would be (in effect) removing the volatile load 24define i32 @test2(ptr nocapture %p, ptr nocapture %q) { 25; CHECK-LABEL: @test2( 26; CHECK-NEXT: entry: 27; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4 28; CHECK-NEXT: [[Y:%.*]] = load volatile i32, ptr [[P]], align 4 29; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]] 30; CHECK-NEXT: ret i32 [[ADD]] 31; 32entry: 33 %x = load i32, ptr %p 34 %y = load volatile i32, ptr %p 35 %add = sub i32 %y, %x 36 ret i32 %add 37} 38 39; If the query instruction is itself volatile, we *cannot* 40; reorder it even if p and q are noalias 41define i32 @test3(ptr noalias nocapture %p, ptr noalias nocapture %q) { 42; CHECK-LABEL: @test3( 43; CHECK-NEXT: entry: 44; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4 45; CHECK-NEXT: [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4 46; CHECK-NEXT: [[Y:%.*]] = load volatile i32, ptr [[P]], align 4 47; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]] 48; CHECK-NEXT: ret i32 [[ADD]] 49; 50entry: 51 %x = load i32, ptr %p 52 load volatile i32, ptr %q 53 %y = load volatile i32, ptr %p 54 %add = sub i32 %y, %x 55 ret i32 %add 56} 57 58; If an encountered instruction is both volatile and ordered, 59; we need to use the strictest ordering of either. In this 60; case, the ordering prevents forwarding. 61define i32 @test4(ptr noalias nocapture %p, ptr noalias nocapture %q) { 62; CHECK-LABEL: @test4( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P:%.*]], align 4 65; CHECK-NEXT: [[TMP0:%.*]] = load atomic volatile i32, ptr [[Q:%.*]] seq_cst, align 4 66; CHECK-NEXT: [[Y:%.*]] = load atomic i32, ptr [[P]] seq_cst, align 4 67; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]] 68; CHECK-NEXT: ret i32 [[ADD]] 69; 70entry: 71 %x = load i32, ptr %p 72 load atomic volatile i32, ptr %q seq_cst, align 4 73 %y = load atomic i32, ptr %p seq_cst, align 4 74 %add = sub i32 %y, %x 75 ret i32 %add 76} 77 78; Value forwarding from a volatile load is perfectly legal 79define i32 @test5(ptr nocapture %p, ptr nocapture %q) { 80; CHECK-LABEL: @test5( 81; CHECK-NEXT: entry: 82; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[P:%.*]], align 4 83; CHECK-NEXT: ret i32 0 84; 85entry: 86 %x = load volatile i32, ptr %p 87 %y = load i32, ptr %p 88 %add = sub i32 %y, %x 89 ret i32 %add 90} 91 92; Does cross block redundancy elimination work with volatiles? 93define i32 @test6(ptr noalias nocapture %p, ptr noalias nocapture %q) { 94; CHECK-LABEL: @test6( 95; CHECK-NEXT: entry: 96; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4 97; CHECK-NEXT: call void @use(i32 [[Y1]]) 98; CHECK-NEXT: br label [[HEADER:%.*]] 99; CHECK: header: 100; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4 101; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y1]], [[X]] 102; CHECK-NEXT: [[CND:%.*]] = icmp eq i32 [[ADD]], 0 103; CHECK-NEXT: br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]] 104; CHECK: exit: 105; CHECK-NEXT: ret i32 0 106; 107entry: 108 %y1 = load i32, ptr %p 109 call void @use(i32 %y1) 110 br label %header 111header: 112 %x = load volatile i32, ptr %q 113 %y = load i32, ptr %p 114 %add = sub i32 %y, %x 115 %cnd = icmp eq i32 %add, 0 116 br i1 %cnd, label %exit, label %header 117exit: 118 ret i32 %add 119} 120 121; Does cross block PRE work with volatiles? 122define i32 @test7(i1 %c, ptr noalias nocapture %p, ptr noalias nocapture %q) { 123; CHECK-LABEL: @test7( 124; CHECK-NEXT: entry: 125; CHECK-NEXT: [[Y_PRE:%.*]] = load i32, ptr [[P:%.*]], align 4 126; CHECK-NEXT: br i1 [[C:%.*]], label [[HEADER:%.*]], label [[SKIP:%.*]] 127; CHECK: skip: 128; CHECK-NEXT: call void @use(i32 [[Y_PRE]]) 129; CHECK-NEXT: br label [[HEADER]] 130; CHECK: header: 131; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4 132; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y_PRE]], [[X]] 133; CHECK-NEXT: [[CND:%.*]] = icmp eq i32 [[ADD]], 0 134; CHECK-NEXT: br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]] 135; CHECK: exit: 136; CHECK-NEXT: ret i32 0 137; 138entry: 139 br i1 %c, label %header, label %skip 140skip: 141 %y1 = load i32, ptr %p 142 call void @use(i32 %y1) 143 br label %header 144header: 145 %x = load volatile i32, ptr %q 146 %y = load i32, ptr %p 147 %add = sub i32 %y, %x 148 %cnd = icmp eq i32 %add, 0 149 br i1 %cnd, label %exit, label %header 150exit: 151 ret i32 %add 152} 153 154; Another volatile PRE case - two paths through a loop 155; load in preheader, one path read only, one not 156define i32 @test8(i1 %b, i1 %c, ptr noalias %p, ptr noalias %q) { 157; CHECK-LABEL: @test8( 158; CHECK-NEXT: entry: 159; CHECK-NEXT: [[Y1:%.*]] = load i32, ptr [[P:%.*]], align 4 160; CHECK-NEXT: call void @use(i32 [[Y1]]) 161; CHECK-NEXT: br label [[HEADER:%.*]] 162; CHECK: header: 163; CHECK-NEXT: [[Y:%.*]] = phi i32 [ [[Y_PRE:%.*]], [[SKIP_HEADER_CRIT_EDGE:%.*]] ], [ [[Y]], [[HEADER]] ], [ [[Y1]], [[ENTRY:%.*]] ] 164; CHECK-NEXT: [[X:%.*]] = load volatile i32, ptr [[Q:%.*]], align 4 165; CHECK-NEXT: call void @use(i32 [[Y]]) 166; CHECK-NEXT: br i1 [[B:%.*]], label [[SKIP:%.*]], label [[HEADER]] 167; CHECK: skip: 168; CHECK-NEXT: call void @clobber(ptr [[P]], ptr [[Q]]) 169; CHECK-NEXT: br i1 [[C:%.*]], label [[SKIP_HEADER_CRIT_EDGE]], label [[EXIT:%.*]] 170; CHECK: skip.header_crit_edge: 171; CHECK-NEXT: [[Y_PRE]] = load i32, ptr [[P]], align 4 172; CHECK-NEXT: br label [[HEADER]] 173; CHECK: exit: 174; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[Y]], [[X]] 175; CHECK-NEXT: ret i32 [[ADD]] 176; 177entry: 178 %y1 = load i32, ptr %p 179 call void @use(i32 %y1) 180 br label %header 181header: 182 %x = load volatile i32, ptr %q 183 %y = load i32, ptr %p 184 call void @use(i32 %y) 185 br i1 %b, label %skip, label %header 186skip: 187 ; escaping the arguments is explicitly required since we marked 188 ; them noalias 189 call void @clobber(ptr %p, ptr %q) 190 br i1 %c, label %header, label %exit 191exit: 192 %add = sub i32 %y, %x 193 ret i32 %add 194} 195 196; This test checks that we don't optimize away instructions that are 197; simplified by SimplifyInstruction(), but are not trivially dead. 198 199define i32 @test9(ptr %V) { 200; CHECK-LABEL: @test9( 201; CHECK-NEXT: entry: 202; CHECK-NEXT: [[LOAD:%.*]] = call i32 undef() 203; CHECK-NEXT: ret i32 poison 204; 205entry: 206 %load = call i32 undef() 207 ret i32 %load 208} 209 210declare void @use(i32) readonly 211declare void @clobber(ptr %p, ptr %q) 212 213!0 = !{ i32 0, i32 1 } 214