Files
TheRock/compiler/amd-llvm/llvm/test/Transforms/GVN/PRE/pre-load-guards.ll
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

178 lines
6.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=gvn -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MDEP
; RUN: opt < %s -passes='gvn<memoryssa>' -enable-load-pre -S | FileCheck %s --check-prefixes=CHECK,MSSA
target 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"
declare void @llvm.experimental.guard(i1, ...)
; This is a motivating example on why we prohibit hoisting through guards.
; In the bottom block, we check that the index is within bounds and only access
; the element in this case and deoptimize otherwise. If we hoist the load to a
; place above the guard, it will may lead to out-of-bound array access.
define i32 @test_motivation(ptr %p, ptr %q, i1 %C, i32 %index, i32 %len) {
; CHECK-LABEL: define i32 @test_motivation(
; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i32 [[INDEX:%.*]], i32 [[LEN:%.*]]) {
; CHECK-NEXT: [[BLOCK1:.*:]]
; CHECK-NEXT: [[EL1:%.*]] = getelementptr inbounds i32, ptr [[Q]], i32 [[INDEX]]
; CHECK-NEXT: [[EL2:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 [[INDEX]]
; CHECK-NEXT: br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
; CHECK: [[BLOCK2]]:
; CHECK-NEXT: br label %[[BLOCK4:.*]]
; CHECK: [[BLOCK3]]:
; CHECK-NEXT: store i32 0, ptr [[EL1]], align 4
; CHECK-NEXT: br label %[[BLOCK4]]
; CHECK: [[BLOCK4]]:
; CHECK-NEXT: [[P2:%.*]] = phi ptr [ [[EL2]], %[[BLOCK3]] ], [ [[EL1]], %[[BLOCK2]] ]
; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[INDEX]], 0
; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[INDEX]], [[LEN]]
; CHECK-NEXT: [[IN_BOUNDS:%.*]] = and i1 [[COND1]], [[COND2]]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[IN_BOUNDS]]) [ "deopt"() ]
; CHECK-NEXT: [[PRE:%.*]] = load i32, ptr [[P2]], align 4
; CHECK-NEXT: ret i32 [[PRE]]
;
block1:
%el1 = getelementptr inbounds i32, ptr %q, i32 %index
%el2 = getelementptr inbounds i32, ptr %p, i32 %index
br i1 %C, label %block2, label %block3
block2:
br label %block4
block3:
store i32 0, ptr %el1
br label %block4
block4:
%P2 = phi ptr [%el2, %block3], [%el1, %block2]
%cond1 = icmp sge i32 %index, 0
%cond2 = icmp slt i32 %index, %len
%in.bounds = and i1 %cond1, %cond2
call void (i1, ...) @llvm.experimental.guard(i1 %in.bounds) [ "deopt"() ]
%PRE = load i32, ptr %P2
ret i32 %PRE
}
; Guard in load's block that is above the load should prohibit the PRE.
define i32 @test_guard_01(ptr %p, ptr %q, i1 %C, i1 %G) {
; CHECK-LABEL: define i32 @test_guard_01(
; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {
; CHECK-NEXT: [[BLOCK1:.*:]]
; CHECK-NEXT: br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
; CHECK: [[BLOCK2]]:
; CHECK-NEXT: br label %[[BLOCK4:.*]]
; CHECK: [[BLOCK3]]:
; CHECK-NEXT: store i32 0, ptr [[P]], align 4
; CHECK-NEXT: br label %[[BLOCK4]]
; CHECK: [[BLOCK4]]:
; CHECK-NEXT: [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]
; CHECK-NEXT: [[PRE:%.*]] = load i32, ptr [[P2]], align 4
; CHECK-NEXT: ret i32 [[PRE]]
;
block1:
br i1 %C, label %block2, label %block3
block2:
br label %block4
block3:
store i32 0, ptr %p
br label %block4
block4:
%P2 = phi ptr [%p, %block3], [%q, %block2]
call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
%PRE = load i32, ptr %P2
ret i32 %PRE
}
; Guard in load's block that is below the load should not prohibit the PRE.
define i32 @test_guard_02(ptr %p, ptr %q, i1 %C, i1 %G) {
; CHECK-LABEL: define i32 @test_guard_02(
; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {
; CHECK-NEXT: [[BLOCK1:.*:]]
; CHECK-NEXT: br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
; CHECK: [[BLOCK2]]:
; CHECK-NEXT: [[PRE_PRE:%.*]] = load i32, ptr [[Q]], align 4
; CHECK-NEXT: br label %[[BLOCK4:.*]]
; CHECK: [[BLOCK3]]:
; CHECK-NEXT: store i32 0, ptr [[P]], align 4
; CHECK-NEXT: br label %[[BLOCK4]]
; CHECK: [[BLOCK4]]:
; CHECK-NEXT: [[PRE:%.*]] = phi i32 [ 0, %[[BLOCK3]] ], [ [[PRE_PRE]], %[[BLOCK2]] ]
; CHECK-NEXT: [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]
; CHECK-NEXT: ret i32 [[PRE]]
;
block1:
br i1 %C, label %block2, label %block3
block2:
br label %block4
block3:
store i32 0, ptr %p
br label %block4
block4:
%P2 = phi ptr [%p, %block3], [%q, %block2]
%PRE = load i32, ptr %P2
call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
ret i32 %PRE
}
; Guard above the load's block should prevent PRE from hoisting through it.
define i32 @test_guard_03(ptr %p, ptr %q, i1 %C, i1 %G) {
; CHECK-LABEL: define i32 @test_guard_03(
; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i1 [[C:%.*]], i1 [[G:%.*]]) {
; CHECK-NEXT: [[BLOCK1:.*:]]
; CHECK-NEXT: br i1 [[C]], label %[[BLOCK2:.*]], label %[[BLOCK3:.*]]
; CHECK: [[BLOCK2]]:
; CHECK-NEXT: br label %[[BLOCK4:.*]]
; CHECK: [[BLOCK3]]:
; CHECK-NEXT: store i32 0, ptr [[P]], align 4
; CHECK-NEXT: br label %[[BLOCK4]]
; CHECK: [[BLOCK4]]:
; CHECK-NEXT: [[P2:%.*]] = phi ptr [ [[P]], %[[BLOCK3]] ], [ [[Q]], %[[BLOCK2]] ]
; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[G]]) [ "deopt"() ]
; CHECK-NEXT: [[PRE:%.*]] = load i32, ptr [[P2]], align 4
; CHECK-NEXT: ret i32 [[PRE]]
;
block1:
br i1 %C, label %block2, label %block3
block2:
br label %block4
block3:
store i32 0, ptr %p
br label %block4
block4:
%P2 = phi ptr [%p, %block3], [%q, %block2]
call void (i1, ...) @llvm.experimental.guard(i1 %G) [ "deopt"() ]
br label %block5
block5:
%PRE = load i32, ptr %P2
ret i32 %PRE
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; MDEP: {{.*}}
; MSSA: {{.*}}