diff --git a/flang/test/HLFIR/mul_transpose.f90 b/flang/test/HLFIR/mul_transpose.f90 new file mode 100644 --- /dev/null +++ b/flang/test/HLFIR/mul_transpose.f90 @@ -0,0 +1,83 @@ +! RUN: bbc -emit-fir -hlfir %s -o - | FileCheck --check-prefix CHECK-BASE --check-prefix CHECK-ALL %s +! RUN: bbc -emit-fir -hlfir %s -o - | fir-opt --lower-hlfir-intrinsics | FileCheck --check-prefix CHECK-LOWERING --check-prefix CHECK-ALL %s +! RUN: bbc -emit-fir -hlfir %s -o - | fir-opt --lower-hlfir-intrinsics | fir-opt --bufferize-hlfir | FileCheck --check-prefix CHECK-BUFFERING --check-prefix CHECK-ALL %s + +! Test passing a hlfir.expr from one intrinsic to another +subroutine mul_transpose(a, b, res) + real a(2,1), b(2,2), res(1,2) + res = MATMUL(TRANSPOSE(a), b) +endsubroutine + +! CHECK-ALL-LABEL: func.func @_QPmul_transpose +! CHECK-ALL: %[[A_ARG:.*]]: !fir.ref> {fir.bindc_name = "a"} +! CHECK-ALL: %[[B_ARG:.*]]: !fir.ref> {fir.bindc_name = "b"} +! CHECK-ALL: %[[RES_ARG:.*]]: !fir.ref> {fir.bindc_name = "res"} +! CHECK-ALL-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %[[A_ARG]] +! CHECK-ALL-DAG: %[[B_DECL:.*]]:2 = hlfir.declare %[[B_ARG]] +! CHECK-ALL-DAG: %[[RES_DECL:.*]]:2 = hlfir.declare %[[RES_ARG]] + +! CHECK-BASE: %[[TRANSPOSE_RES:.*]] = hlfir.transpose %[[A_DECL]]#0 : (!fir.ref>) -> !hlfir.expr<1x2xf32> +! CHECK-BASE-NEXT: %[[MATMUL_RES:.*]] = hlfir.matmul %[[TRANSPOSE_RES]] %[[B_DECL]]#0 {{.*}}: (!hlfir.expr<1x2xf32>, !fir.ref>) -> !hlfir.expr<1x2xf32> +! CHECK-BASE-NEXT: hlfir.assign %[[MATMUL_RES]] to %[[RES_DECL]]#0 : !hlfir.expr<1x2xf32>, !fir.ref> +! CHECK-BASE-NEXT: hlfir.destroy %[[MATMUL_RES]] +! CHECK-BASE-NEXT: hlfir.destroy %[[TRANSPOSE_RES]] + +! CHECK-LOWERING: %[[A_BOX:.*]] = fir.embox %[[A_DECL]]#1(%{{.*}}) +! CHECK-LOWERING: %[[TRANSPOSE_CONV_RES:.*]] = fir.convert %[[TRANSPOSE_RES_BOX:.*]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-LOWERING: %[[A_BOX_CONV:.*]] = fir.convert %[[A_BOX]] : (!fir.box>) -> !fir.box +! CHECK-LOWERING: fir.call @_FortranATranspose(%[[TRANSPOSE_CONV_RES]], %[[A_BOX_CONV]], %[[LOC_STR1:.*]], %[[LOC_N1:.*]]) +! CHECK-LOWERING: %[[TRANSPOSE_RES_LD:.*]] = fir.load %[[TRANSPOSE_RES_BOX:.*]] +! CHECK-LOWERING: %[[TRANSPOSE_RES_ADDR:.*]] = fir.box_addr %[[TRANSPOSE_RES_LD]] +! CHECK-LOWERING: %[[TRANSPOSE_RES_VAR:.*]]:2 = hlfir.declare %[[TRANSPOSE_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"} +! CHECK-LOWERING: %[[TRUE:.*]] = arith.constant true +! CHECK-LOWERING: %[[TRANSPOSE_EXPR:.*]] = hlfir.as_expr %[[TRANSPOSE_RES_VAR]]#0 move %[[TRUE]] : (!fir.box>, i1) -> !hlfir.expr +! CHECK-LOWERING: %[[TRANSPOSE_ASSOC:.*]]:3 = hlfir.associate %[[TRANSPOSE_EXPR]]({{.*}}) {uniq_name = "adapt.valuebyref"} +! CHECK-LOWERING: (!hlfir.expr, !fir.shape<2>) -> (!fir.box>, !fir.ref>, i1) + +! CHECK-LOWERING: %[[LHS_BOX:.*]] = fir.embox %[[TRANSPOSE_ASSOC]]#1 +! CHECK-LOWERING: %[[B_BOX:.*]] = fir.embox %[[B_DECL]]#1(%{{.*}}) +! CHECK-LOWERING: %[[MUL_CONV_RES:.*]] = fir.convert %[[MUL_RES_BOX:.*]] : (!fir.ref>>>) -> !fir.ref> +! CHECK-LOWERING: %[[LHS_CONV:.*]] = fir.convert %[[LHS_BOX]] : (!fir.box>) -> !fir.box +! CHECK-LOWERING: %[[B_BOX_CONV:.*]] = fir.convert %[[B_BOX]] : (!fir.box>) -> !fir.box +! CHECK-LOWERING: fir.call @_FortranAMatmul(%[[MUL_CONV_RES]], %[[LHS_CONV]], %[[B_BOX_CONV]], %[[LOC_STR2:.*]], %[[LOC_N2:.*]]) +! CHECK-LOWERING: %[[MUL_RES_LD:.*]] = fir.load %[[MUL_RES_BOX:.*]] +! CHECK-LOWERING: %[[MUL_RES_ADDR:.*]] = fir.box_addr %[[MUL_RES_LD]] +! CHECK-LOWERING: %[[MUL_RES_VAR:.*]]:2 = hlfir.declare %[[MUL_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"} +! CHECK-LOWERING: %[[TRUE2:.*]] = arith.constant true +! CHECK-LOWERING: %[[MUL_EXPR:.*]] = hlfir.as_expr %[[MUL_RES_VAR]]#0 move %[[TRUE2]] : (!fir.box>, i1) -> !hlfir.expr + +! CHECK-LOWERING: hlfir.end_associate %[[TRANSPOSE_ASSOC]]#1, %[[TRANSPOSE_ASSOC]]#2 : !fir.ref>, i1 +! CHECK-LOWERING-NEXT: hlfir.assign %[[MUL_EXPR]] to %[[RES_DECL]]#0 : !hlfir.expr, !fir.ref> +! CHECK-LOWERING-NEXT: hlfir.destroy %[[MUL_EXPR]] +! CHECK-LOWERING-NEXT: hlfir.destroy %[[TRANSPOSE_EXPR]] + +! [argument handling unchanged] +! CHECK-BUFFERING: fir.call @_FortranATranspose( +! CHECK-BUFFERING: %[[TRANSPOSE_RES_LD:.*]] = fir.load %[[TRANSPOSE_RES_BOX:.*]] +! CHECK-BUFFERING: %[[TRANSPOSE_RES_ADDR:.*]] = fir.box_addr %[[TRANSPOSE_RES_LD]] +! CHECK-BUFFERING: %[[TRANSPOSE_RES_VAR:.*]]:2 = hlfir.declare %[[TRANSPOSE_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"} +! CHECK-BUFFERING: %[[TRUE:.*]] = arith.constant true +! CHECK-BUFFERING: %[[TUPLE0:.*]] = fir.undefined tuple>, i1> +! CHECK-BUFFERING: %[[TUPLE1:.*]] = fir.insert_value %[[TUPLE0]], %[[TRUE]], [1 : index] +! CHECK-BUFFERING: %[[TUPLE2:.*]] = fir.insert_value %[[TUPLE1]], %[[TRANSPOSE_RES_VAR]]#0, [0 : index] + +! CHECK-BUFFERING: %[[TRANSPOSE_RES_REF:.*]] = fir.convert %[[TRANSPOSE_RES_VAR]]#1 : (!fir.heap>) -> !fir.ref> +! CHECK-BUFFERING: %[[TRANSPOSE_RES_BOX:.*]] = fir.embox %[[TRANSPOSE_RES_REF]]({{.*}}) +! CHECK-BUFFERING: %[[LHS_CONV:.*]] = fir.convert %[[TRANSPOSE_RES_BOX]] : (!fir.box>) -> !fir.box +! [argument handling unchanged] +! CHECK-BUFFERING: fir.call @_FortranAMatmul( +! CHECK-BUFFERING: %[[MUL_RES_LD:.*]] = fir.load %[[MUL_RES_BOX:.*]] +! CHECK-BUFFERING: %[[MUL_RES_ADDR:.*]] = fir.box_addr %[[MUL_RES_LD]] +! CHECK-BUFFERING: %[[MUL_RES_VAR:.*]]:2 = hlfir.declare %[[MUL_RES_ADDR]]({{.*}}) {uniq_name = ".tmp.intrinsic_result"} +! CHECK-BUFFERING: %[[TRUE2:.*]] = arith.constant true +! CHECK-BUFFERING: %[[TUPLE3:.*]] = fir.undefined tuple>, i1> +! CHECK-BUFFERING: %[[TUPLE4:.*]] = fir.insert_value %[[TUPLE3]], %[[TRUE2]], [1 : index] +! CHECK-BUFFERING: %[[TUPLE5:.*]] = fir.insert_value %[[TUPLE4]], %[[MUL_RES_VAR]]#0, [0 : index] + +! CHECK-BUFFERING: %[[TRANSPOSE_RES_HEAP:.*]] = fir.convert %[[TRANSPOSE_RES_REF]] : (!fir.ref>) -> !fir.heap> +! CHECK-BUFFERING-NEXT: fir.freemem %[[TRANSPOSE_RES_HEAP]] +! CHECK-BUFFERING-NEXT: hlfir.assign %[[MUL_RES_VAR]]#0 to %[[RES_DECL]]#0 : !fir.box>, !fir.ref> +! CHECK-BUFFERING-NEXT: fir.freemem %[[MUL_RES_VAR]]#1 + +! CHECK-ALL-NEXT: return +! CHECK-ALL-NEXT: }