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
312 lines
9.3 KiB
MLIR
312 lines
9.3 KiB
MLIR
// RUN: mlir-opt %s --pass-pipeline='builtin.module(func.func(mem2reg{region-simplify=false}))' --split-input-file | FileCheck %s
|
|
|
|
// CHECK-LABEL: func.func @basic
|
|
func.func @basic() -> i32 {
|
|
// CHECK-NOT: = memref.alloca
|
|
// CHECK: %[[RES:.*]] = arith.constant 5 : i32
|
|
// CHECK-NOT: = memref.alloca
|
|
%0 = arith.constant 5 : i32
|
|
%1 = memref.alloca() : memref<i32>
|
|
memref.store %0, %1[] : memref<i32>
|
|
%2 = memref.load %1[] : memref<i32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %2 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @basic_default
|
|
func.func @basic_default() -> i32 {
|
|
// CHECK-NOT: = memref.alloca
|
|
// CHECK: %[[RES:.*]] = ub.poison : i32
|
|
// CHECK-NOT: = memref.alloca
|
|
%0 = arith.constant 5 : i32
|
|
%1 = memref.alloca() : memref<i32>
|
|
%2 = memref.load %1[] : memref<i32>
|
|
// CHECK-NOT: memref.store
|
|
memref.store %0, %1[] : memref<i32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %2 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @basic_float
|
|
func.func @basic_float() -> f32 {
|
|
// CHECK-NOT: = memref.alloca
|
|
// CHECK: %[[RES:.*]] = arith.constant {{.*}} : f32
|
|
%0 = arith.constant 5.2 : f32
|
|
// CHECK-NOT: = memref.alloca
|
|
%1 = memref.alloca() : memref<f32>
|
|
memref.store %0, %1[] : memref<f32>
|
|
%2 = memref.load %1[] : memref<f32>
|
|
// CHECK: return %[[RES]] : f32
|
|
return %2 : f32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @basic_ranked
|
|
func.func @basic_ranked() -> i32 {
|
|
// CHECK-NOT: = memref.alloca
|
|
// CHECK: %[[RES:.*]] = arith.constant 5 : i32
|
|
// CHECK-NOT: = memref.alloca
|
|
%0 = arith.constant 0 : index
|
|
%1 = arith.constant 5 : i32
|
|
%2 = memref.alloca() : memref<1x1xi32>
|
|
memref.store %1, %2[%0, %0] : memref<1x1xi32>
|
|
%3 = memref.load %2[%0, %0] : memref<1x1xi32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %3 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @reject_multiple_elements
|
|
func.func @reject_multiple_elements() -> i32 {
|
|
// CHECK: %[[INDEX:.*]] = arith.constant 0 : index
|
|
%0 = arith.constant 0 : index
|
|
// CHECK: %[[STORED:.*]] = arith.constant 5 : i32
|
|
%1 = arith.constant 5 : i32
|
|
// CHECK: %[[ALLOCA:.*]] = memref.alloca()
|
|
%2 = memref.alloca() : memref<1x2xi32>
|
|
// CHECK: memref.store %[[STORED]], %[[ALLOCA]][%[[INDEX]], %[[INDEX]]]
|
|
memref.store %1, %2[%0, %0] : memref<1x2xi32>
|
|
// CHECK: %[[RES:.*]] = memref.load %[[ALLOCA]][%[[INDEX]], %[[INDEX]]]
|
|
%3 = memref.load %2[%0, %0] : memref<1x2xi32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %3 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @cycle
|
|
// CHECK-SAME: (%[[ARG0:.*]]: i64, %[[ARG1:.*]]: i1, %[[ARG2:.*]]: i64)
|
|
func.func @cycle(%arg0: i64, %arg1: i1, %arg2: i64) {
|
|
// CHECK-NOT: = memref.alloca
|
|
%alloca = memref.alloca() : memref<i64>
|
|
memref.store %arg2, %alloca[] : memref<i64>
|
|
// CHECK: cf.cond_br %[[ARG1:.*]], ^[[BB1:.*]](%[[ARG2]] : i64), ^[[BB2:.*]](%[[ARG2]] : i64)
|
|
cf.cond_br %arg1, ^bb1, ^bb2
|
|
// CHECK: ^[[BB1]](%[[USE:.*]]: i64):
|
|
^bb1:
|
|
%use = memref.load %alloca[] : memref<i64>
|
|
// CHECK: call @use(%[[USE]])
|
|
func.call @use(%use) : (i64) -> ()
|
|
memref.store %arg0, %alloca[] : memref<i64>
|
|
// CHECK: cf.br ^[[BB2]](%[[ARG0]] : i64)
|
|
cf.br ^bb2
|
|
// CHECK: ^[[BB2]](%[[FWD:.*]]: i64):
|
|
^bb2:
|
|
// CHECK: cf.br ^[[BB1]](%[[FWD]] : i64)
|
|
cf.br ^bb1
|
|
}
|
|
|
|
func.func @use(%arg: i64) { return }
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @recursive
|
|
// CHECK-SAME: (%[[ARG:.*]]: i64)
|
|
func.func @recursive(%arg: i64) -> i64 {
|
|
// CHECK-NOT: = memref.alloca()
|
|
%alloca0 = memref.alloca() : memref<memref<memref<i64>>>
|
|
%alloca1 = memref.alloca() : memref<memref<i64>>
|
|
%alloca2 = memref.alloca() : memref<i64>
|
|
memref.store %arg, %alloca2[] : memref<i64>
|
|
memref.store %alloca2, %alloca1[] : memref<memref<i64>>
|
|
memref.store %alloca1, %alloca0[] : memref<memref<memref<i64>>>
|
|
%load0 = memref.load %alloca0[] : memref<memref<memref<i64>>>
|
|
%load1 = memref.load %load0[] : memref<memref<i64>>
|
|
%load2 = memref.load %load1[] : memref<i64>
|
|
// CHECK: return %[[ARG]] : i64
|
|
return %load2 : i64
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @deny_store_of_alloca
|
|
// CHECK-SAME: (%[[ARG:.*]]: memref<memref<i32>>)
|
|
func.func @deny_store_of_alloca(%arg: memref<memref<i32>>) -> i32 {
|
|
// CHECK: %[[VALUE:.*]] = arith.constant 5 : i32
|
|
%0 = arith.constant 5 : i32
|
|
// CHECK: %[[ALLOCA:.*]] = memref.alloca
|
|
%1 = memref.alloca() : memref<i32>
|
|
// Storing into the memref is allowed.
|
|
// CHECK: memref.store %[[VALUE]], %[[ALLOCA]][]
|
|
memref.store %0, %1[] : memref<i32>
|
|
// Storing the memref itself is NOT allowed.
|
|
// CHECK: memref.store %[[ALLOCA]], %[[ARG]][]
|
|
memref.store %1, %arg[] : memref<memref<i32>>
|
|
// CHECK: %[[RES:.*]] = memref.load %[[ALLOCA]][]
|
|
%2 = memref.load %1[] : memref<i32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %2 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @promotable_nonpromotable_intertwined
|
|
func.func @promotable_nonpromotable_intertwined() -> i32 {
|
|
// CHECK: %[[NON_PROMOTED:.*]] = memref.alloca() : memref<i32>
|
|
%0 = memref.alloca() : memref<i32>
|
|
// CHECK-NOT: = memref.alloca() : memref<memref<i32>>
|
|
%1 = memref.alloca() : memref<memref<i32>>
|
|
memref.store %0, %1[] : memref<memref<i32>>
|
|
%2 = memref.load %1[] : memref<memref<i32>>
|
|
// CHECK: call @use(%[[NON_PROMOTED]])
|
|
call @use(%0) : (memref<i32>) -> ()
|
|
// CHECK: %[[RES:.*]] = memref.load %[[NON_PROMOTED]][]
|
|
%3 = memref.load %0[] : memref<i32>
|
|
// CHECK: return %[[RES]] : i32
|
|
return %3 : i32
|
|
}
|
|
|
|
func.func @use(%arg: memref<i32>) { return }
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @unused_alloca_store_loop
|
|
func.func @unused_alloca_store_loop() {
|
|
// CHECK-NOT: memref.alloca
|
|
%cst = arith.constant 1 : i32
|
|
%alloca = memref.alloca() : memref<i32>
|
|
// CHECK: cf.br ^[[BB1:.*]]
|
|
cf.br ^bb1
|
|
|
|
// CHECK: ^[[BB1]]:
|
|
^bb1:
|
|
// CHECK-NOT: memref.store
|
|
memref.store %cst, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[BB1]]
|
|
cf.br ^bb1
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: func.func @store_back_to_alloca
|
|
// CHECK-SAME: (%[[COND:.*]]: i1)
|
|
func.func @store_back_to_alloca(%cond: i1) -> i32 {
|
|
// CHECK-NOT: memref.alloca
|
|
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32
|
|
%c0 = arith.constant 0 : i32
|
|
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
|
|
%c1 = arith.constant 1 : i32
|
|
// CHECK-NOT: memref.alloca
|
|
%alloca = memref.alloca() : memref<i32>
|
|
memref.store %c0, %alloca[] : memref<i32>
|
|
%loaded = memref.load %alloca[] : memref<i32>
|
|
// CHECK: cf.cond_br %[[COND]], ^[[STORE_BACK:.*]], ^[[SKIP:.*]]
|
|
cf.cond_br %cond, ^store_back, ^skip
|
|
|
|
// CHECK: ^[[STORE_BACK]]:
|
|
^store_back:
|
|
memref.store %loaded, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE:.*]](%[[C0]] : i32)
|
|
cf.br ^merge
|
|
|
|
// CHECK: ^[[SKIP]]:
|
|
^skip:
|
|
memref.store %c1, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE]](%[[C1]] : i32)
|
|
cf.br ^merge
|
|
|
|
// CHECK: ^[[MERGE]](%[[RESULT:.*]]: i32):
|
|
^merge:
|
|
%result = memref.load %alloca[] : memref<i32>
|
|
// CHECK: return %[[RESULT]] : i32
|
|
return %result : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// Ensure that a merge point used by an erased operation is not considered used.
|
|
|
|
// CHECK-LABEL: func.func @merge_point_used_by_erased_op
|
|
// CHECK-SAME: (%[[COND:.*]]: i1)
|
|
func.func @merge_point_used_by_erased_op(%cond: i1) -> i32 {
|
|
// CHECK-NOT: memref.alloca
|
|
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32
|
|
%c0 = arith.constant 0 : i32
|
|
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
|
|
%c1 = arith.constant 1 : i32
|
|
// CHECK-NOT: memref.alloca
|
|
%alloca = memref.alloca() : memref<i32>
|
|
// CHECK: cf.cond_br %[[COND]], ^[[PRED1:.*]], ^[[PRED2:.*]]
|
|
cf.cond_br %cond, ^pred1, ^pred2
|
|
|
|
// CHECK: ^[[PRED1]]:
|
|
^pred1:
|
|
memref.store %c0, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE:.*]]{{$}}
|
|
cf.br ^merge
|
|
|
|
// CHECK: ^[[PRED2]]:
|
|
^pred2:
|
|
memref.store %c1, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE]]{{$}}
|
|
cf.br ^merge
|
|
|
|
// CHECK: ^[[MERGE]]:
|
|
^merge:
|
|
%result = memref.load %alloca[] : memref<i32>
|
|
memref.store %result, %alloca[] : memref<i32>
|
|
// CHECK: return %[[C0]] : i32
|
|
return %c0 : i32
|
|
}
|
|
|
|
// -----
|
|
|
|
// Two consecutive merge points: pred1 and pred2 merge at merge1, then merge1
|
|
// and pred3 merge at merge2.
|
|
|
|
// CHECK-LABEL: func.func @two_consecutive_merge_points
|
|
// CHECK-SAME: (%[[COND1:.*]]: i1, %[[COND2:.*]]: i1)
|
|
func.func @two_consecutive_merge_points(%cond1: i1, %cond2: i1) -> i32 {
|
|
// CHECK-NOT: memref.alloca
|
|
// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32
|
|
// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
|
|
// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : i32
|
|
// CHECK-NOT: memref.alloca
|
|
%c0 = arith.constant 0 : i32
|
|
%c1 = arith.constant 1 : i32
|
|
%c2 = arith.constant 2 : i32
|
|
%alloca = memref.alloca() : memref<i32>
|
|
// CHECK: cf.cond_br %[[COND1]], ^[[PRED1:.*]], ^[[MID:.*]]
|
|
cf.cond_br %cond1, ^pred1, ^mid
|
|
|
|
// CHECK: ^[[MID]]:
|
|
^mid:
|
|
// CHECK: cf.cond_br %[[COND2]], ^[[PRED2:.*]], ^[[PRED3:.*]]
|
|
cf.cond_br %cond2, ^pred2, ^pred3
|
|
|
|
// CHECK: ^[[PRED1]]:
|
|
^pred1:
|
|
memref.store %c0, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE1:.*]](%[[C0]] : i32)
|
|
cf.br ^merge1
|
|
|
|
// CHECK: ^[[PRED2]]:
|
|
^pred2:
|
|
memref.store %c1, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE1]](%[[C1]] : i32)
|
|
cf.br ^merge1
|
|
|
|
// CHECK: ^[[MERGE1]](%[[MARG:.*]]: i32):
|
|
^merge1:
|
|
// CHECK: cf.br ^[[MERGE2:.*]](%[[MARG]] : i32)
|
|
cf.br ^merge2
|
|
|
|
// CHECK: ^[[PRED3]]:
|
|
^pred3:
|
|
memref.store %c2, %alloca[] : memref<i32>
|
|
// CHECK: cf.br ^[[MERGE2]](%[[C2]] : i32)
|
|
cf.br ^merge2
|
|
|
|
// CHECK: ^[[MERGE2]](%[[RESULT:.*]]: i32):
|
|
^merge2:
|
|
%result = memref.load %alloca[] : memref<i32>
|
|
// CHECK: return %[[RESULT]] : i32
|
|
return %result : i32
|
|
}
|