brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 5320191 Raw
214 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Tests that check our handling of volatile instructions encountered3; when scanning for dependencies4; RUN: opt -passes=gvn -enable-split-backedge-in-load-pre -S < %s | FileCheck %s5 6; Check that we can bypass a volatile load when searching7; for dependencies of a non-volatile load8define 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 412; CHECK-NEXT:    ret i32 013;14entry:15  %x = load i32, ptr %p16  load volatile i32, ptr %q17  %y = load i32, ptr %p18  %add = sub i32 %y, %x19  ret i32 %add20}21 22; We can not value forward if the query instruction is23; volatile, this would be (in effect) removing the volatile load24define 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 428; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, ptr [[P]], align 429; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]30; CHECK-NEXT:    ret i32 [[ADD]]31;32entry:33  %x = load i32, ptr %p34  %y = load volatile i32, ptr %p35  %add = sub i32 %y, %x36  ret i32 %add37}38 39; If the query instruction is itself volatile, we *cannot*40; reorder it even if p and q are noalias41define 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 445; CHECK-NEXT:    [[TMP0:%.*]] = load volatile i32, ptr [[Q:%.*]], align 446; CHECK-NEXT:    [[Y:%.*]] = load volatile i32, ptr [[P]], align 447; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]48; CHECK-NEXT:    ret i32 [[ADD]]49;50entry:51  %x = load i32, ptr %p52  load volatile i32, ptr %q53  %y = load volatile i32, ptr %p54  %add = sub i32 %y, %x55  ret i32 %add56}57 58; If an encountered instruction is both volatile and ordered,59; we need to use the strictest ordering of either.  In this60; 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 465; CHECK-NEXT:    [[TMP0:%.*]] = load atomic volatile i32, ptr [[Q:%.*]] seq_cst, align 466; CHECK-NEXT:    [[Y:%.*]] = load atomic i32, ptr [[P]] seq_cst, align 467; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y]], [[X]]68; CHECK-NEXT:    ret i32 [[ADD]]69;70entry:71  %x = load i32, ptr %p72  load atomic volatile i32, ptr %q seq_cst, align 473  %y = load atomic i32, ptr %p seq_cst, align 474  %add = sub i32 %y, %x75  ret i32 %add76}77 78; Value forwarding from a volatile load is perfectly legal79define 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 483; CHECK-NEXT:    ret i32 084;85entry:86  %x = load volatile i32, ptr %p87  %y = load i32, ptr %p88  %add = sub i32 %y, %x89  ret i32 %add90}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 497; 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 4101; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y1]], [[X]]102; CHECK-NEXT:    [[CND:%.*]] = icmp eq i32 [[ADD]], 0103; CHECK-NEXT:    br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]]104; CHECK:       exit:105; CHECK-NEXT:    ret i32 0106;107entry:108  %y1 = load i32, ptr %p109  call void @use(i32 %y1)110  br label %header111header:112  %x = load volatile i32, ptr %q113  %y = load i32, ptr %p114  %add = sub i32 %y, %x115  %cnd = icmp eq i32 %add, 0116  br i1 %cnd, label %exit, label %header117exit:118  ret i32 %add119}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 4126; 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 4132; CHECK-NEXT:    [[ADD:%.*]] = sub i32 [[Y_PRE]], [[X]]133; CHECK-NEXT:    [[CND:%.*]] = icmp eq i32 [[ADD]], 0134; CHECK-NEXT:    br i1 [[CND]], label [[EXIT:%.*]], label [[HEADER]]135; CHECK:       exit:136; CHECK-NEXT:    ret i32 0137;138entry:139  br i1 %c, label %header, label %skip140skip:141  %y1 = load i32, ptr %p142  call void @use(i32 %y1)143  br label %header144header:145  %x = load volatile i32, ptr %q146  %y = load i32, ptr %p147  %add = sub i32 %y, %x148  %cnd = icmp eq i32 %add, 0149  br i1 %cnd, label %exit, label %header150exit:151  ret i32 %add152}153 154; Another volatile PRE case - two paths through a loop155; load in preheader, one path read only, one not156define 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 4160; 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 4165; 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 4172; 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 %p179  call void @use(i32 %y1)180  br label %header181header:182  %x = load volatile i32, ptr %q183  %y = load i32, ptr %p184  call void @use(i32 %y)185  br i1 %b, label %skip, label %header186skip:187  ; escaping the arguments is explicitly required since we marked188  ; them noalias189  call void @clobber(ptr %p, ptr %q)190  br i1 %c, label %header, label %exit191exit:192  %add = sub i32 %y, %x193  ret i32 %add194}195 196; This test checks that we don't optimize away instructions that are197; 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 poison204;205entry:206  %load = call i32 undef()207  ret i32 %load208}209 210declare void @use(i32) readonly211declare void @clobber(ptr %p, ptr %q)212 213!0 = !{ i32 0, i32 1 }214