165 lines
5.3 KiB
MLIR
165 lines
5.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:.*]] = arith.constant 0 : 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 }
|