brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · ca1852f Raw
190 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt < %s -passes=gvn -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MDEP3; RUN: opt < %s -passes='gvn<memoryssa>' -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MSSA4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"5 6declare void @llvm.experimental.guard(i1, ...)7 8; This is a motivating example on why we prohibit hoisting through guards.9; In the bottom block, we check that the index is within bounds and only access10; the element in this case and deoptimize otherwise. If we hoist the load to a11; place above the guard, it will may lead to out-of-bound array access.12define i32 @test_motivation(ptr %p, ptr %q, i1 %C, i32 %index, i32 %len) {13; CHECK-LABEL: define i32 @test_motivation(14; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i32 [[INDEX:%.*]], i32 [[LEN:%.*]]) {15; CHECK-NEXT:  [[BLOCK1:.*:]]16; CHECK-NEXT:    [[EL1:%.*]] = getelementptr inbounds i32, ptr [[Q]], i32 [[INDEX]]17; CHECK-NEXT:    [[EL2:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[INDEX]]18; CHECK-NEXT:    br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]19; CHECK:       [[BLOCK2]]:20; CHECK-NEXT:    br label %[[BLOCK4:.*]]21; CHECK:       [[BLOCK3]]:22; CHECK-NEXT:    store i32 0, ptr [[EL1]], align 423; CHECK-NEXT:    br label %[[BLOCK4]]24; CHECK:       [[BLOCK4]]:25; CHECK-NEXT:    [[P2:%.*]] = phi ptr [ [[EL2]], %[[BLOCK3]] ], [ [[EL1]], %[[BLOCK2]] ]26; CHECK-NEXT:    [[COND1:%.*]] = icmp sge i32 [[INDEX]], 027; CHECK-NEXT:    [[COND2:%.*]] = icmp slt i32 [[INDEX]], [[LEN]]28; CHECK-NEXT:    [[IN_BOUNDS:%.*]] = and i1 [[COND1]], [[COND2]]29; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[IN_BOUNDS]]) [ "deopt"() ]30; CHECK-NEXT:    [[PRE:%.*]] = load i32, ptr [[P2]], align 431; CHECK-NEXT:    ret i32 [[PRE]]32;33block1:34  %el1 = getelementptr inbounds i32, ptr %q, i32 %index35  %el2 = getelementptr inbounds i32, ptr %p, i32 %index36  br i1 %C, label %block2, label %block337 38block2:39 40  br label %block441 42block3:43  store i32 0, ptr %el144  br label %block445 46block4:47 48 49  %P2 = phi ptr [%el2, %block3], [%el1, %block2]50  %cond1 = icmp sge i32 %index, 051  %cond2 = icmp slt i32 %index, %len52  %in.bounds = and i1 %cond1, %cond253  call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) [ "deopt"() ]54  %PRE = load i32, ptr %P255  ret i32 %PRE56}57 58; Guard in load's block that is above the load should prohibit the PRE.59define i32 @test_guard_01(ptr %p, ptr %q, i1 %C, i1 %G) {60; CHECK-LABEL: define i32 @test_guard_01(61; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {62; CHECK-NEXT:  [[BLOCK1:.*:]]63; CHECK-NEXT:    br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]64; CHECK:       [[BLOCK2]]:65; CHECK-NEXT:    br label %[[BLOCK4:.*]]66; CHECK:       [[BLOCK3]]:67; CHECK-NEXT:    store i32 0, ptr [[P]], align 468; CHECK-NEXT:    br label %[[BLOCK4]]69; CHECK:       [[BLOCK4]]:70; CHECK-NEXT:    [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]71; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]72; CHECK-NEXT:    [[PRE:%.*]] = load i32, ptr [[P2]], align 473; CHECK-NEXT:    ret i32 [[PRE]]74;75block1:76  br i1 %C, label %block2, label %block377 78block2:79 80 81  br label %block482 83block3:84  store i32 0, ptr %p85  br label %block486 87block4:88 89 90  %P2 = phi ptr [%p, %block3], [%q, %block2]91  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]92  %PRE = load i32, ptr %P293  ret i32 %PRE94}95 96; Guard in load's block that is below the load should not prohibit the PRE.97define i32 @test_guard_02(ptr %p, ptr %q, i1 %C, i1 %G) {98; MDEP-LABEL: define i32 @test_guard_02(99; MDEP-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {100; MDEP-NEXT:  [[BLOCK1:.*:]]101; MDEP-NEXT:    br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]102; MDEP:       [[BLOCK2]]:103; MDEP-NEXT:    [[PRE_PRE:%.*]] = load i32, ptr [[Q]], align 4104; MDEP-NEXT:    br label %[[BLOCK4:.*]]105; MDEP:       [[BLOCK3]]:106; MDEP-NEXT:    store i32 0, ptr [[P]], align 4107; MDEP-NEXT:    br label %[[BLOCK4]]108; MDEP:       [[BLOCK4]]:109; MDEP-NEXT:    [[PRE:%.*]] = phi i32 [ 0, %[[BLOCK3]] ], [ [[PRE_PRE]], %[[BLOCK2]] ]110; MDEP-NEXT:    [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]111; MDEP-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]112; MDEP-NEXT:    ret i32 [[PRE]]113;114; MSSA-LABEL: define i32 @test_guard_02(115; MSSA-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {116; MSSA-NEXT:  [[BLOCK1:.*:]]117; MSSA-NEXT:    br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]118; MSSA:       [[BLOCK2]]:119; MSSA-NEXT:    br label %[[BLOCK4:.*]]120; MSSA:       [[BLOCK3]]:121; MSSA-NEXT:    store i32 0, ptr [[P]], align 4122; MSSA-NEXT:    br label %[[BLOCK4]]123; MSSA:       [[BLOCK4]]:124; MSSA-NEXT:    [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]125; MSSA-NEXT:    [[PRE:%.*]] = load i32, ptr [[P2]], align 4126; MSSA-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]127; MSSA-NEXT:    ret i32 [[PRE]]128;129block1:130  br i1 %C, label %block2, label %block3131 132block2:133 134 135  br label %block4136 137block3:138  store i32 0, ptr %p139  br label %block4140 141block4:142 143 144  %P2 = phi ptr [%p, %block3], [%q, %block2]145  %PRE = load i32, ptr %P2146  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]147  ret i32 %PRE148}149 150; Guard above the load's block should prevent PRE from hoisting through it.151define i32 @test_guard_03(ptr %p, ptr %q, i1 %C, i1 %G) {152; CHECK-LABEL: define i32 @test_guard_03(153; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {154; CHECK-NEXT:  [[BLOCK1:.*:]]155; CHECK-NEXT:    br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]156; CHECK:       [[BLOCK2]]:157; CHECK-NEXT:    br label %[[BLOCK4:.*]]158; CHECK:       [[BLOCK3]]:159; CHECK-NEXT:    store i32 0, ptr [[P]], align 4160; CHECK-NEXT:    br label %[[BLOCK4]]161; CHECK:       [[BLOCK4]]:162; CHECK-NEXT:    [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]163; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]164; CHECK-NEXT:    [[PRE:%.*]] = load i32, ptr [[P2]], align 4165; CHECK-NEXT:    ret i32 [[PRE]]166;167block1:168  br i1 %C, label %block2, label %block3169 170block2:171 172 173  br label %block4174 175block3:176  store i32 0, ptr %p177  br label %block4178 179block4:180 181 182  %P2 = phi ptr [%p, %block3], [%q, %block2]183  call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]184  br label %block5185 186block5:187  %PRE = load i32, ptr %P2188  ret i32 %PRE189}190