diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2016-01-24 09:11:50 +0000 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2016-01-24 09:11:50 +0000 |
commit | 094773e8cb7d7fbb5e101cfc3270ed5c7eff9d95 (patch) | |
tree | c22ce9dc659223cd1845e0b31b222fe1bb67fcc1 /gcc/fortran/frontend-passes.c | |
parent | d13cd3a614b2b074a2895c15171a6cf842e13a10 (diff) | |
download | gcc-094773e8cb7d7fbb5e101cfc3270ed5c7eff9d95.zip gcc-094773e8cb7d7fbb5e101cfc3270ed5c7eff9d95.tar.gz gcc-094773e8cb7d7fbb5e101cfc3270ed5c7eff9d95.tar.bz2 |
re PR fortran/66094 (Handle transpose(A) in inline matmul)
2016-01-24 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/66094
* frontend-passes.c (enum matrix_case): Add case A2B2T for
MATMUL(A,TRANSPoSE(B)) where A and B are rank 2.
(inline_limit_check): Also add A2B2T.
(matmul_lhs_realloc): Handle A2B2T.
(check_conjg_variable): Rename to
(check_conjg_transpose_variable): and also count TRANSPOSE.
(inline_matmul_assign): Handle A2B2T.
2016-01-24 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/66094
* gfortran.dg/inline_matmul_13.f90: New test.
* gfortran.dg/matmul_bounds_8.f90: New test.
* gfortran.dg/matmul_bounds_9.f90: New test.
* gfortran.dg/matmul_bounds_10.f90: New test.
From-SVN: r232774
Diffstat (limited to 'gcc/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 116 |
1 files changed, 106 insertions, 10 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index 9fad41d..340fd6e 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -106,7 +106,7 @@ static int var_num = 1; /* What sort of matrix we are dealing with when inlining MATMUL. */ -enum matrix_case { none=0, A2B2, A2B1, A1B2 }; +enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T }; /* Keep track of the number of expressions we have inserted so far using create_var. */ @@ -2080,7 +2080,7 @@ inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case) gfc_typespec ts; gfc_expr *cond; - gcc_assert (m_case == A2B2); + gcc_assert (m_case == A2B2 || m_case == A2B2T); /* Calculation is done in real to avoid integer overflow. */ @@ -2240,6 +2240,18 @@ matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b, cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); break; + case A2B2T: + ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1); + ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1); + + ne1 = build_logical_expr (INTRINSIC_NE, + get_array_inq_function (GFC_ISYM_SIZE, c, 1), + get_array_inq_function (GFC_ISYM_SIZE, a, 1)); + ne2 = build_logical_expr (INTRINSIC_NE, + get_array_inq_function (GFC_ISYM_SIZE, c, 2), + get_array_inq_function (GFC_ISYM_SIZE, b, 1)); + cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); + case A2B1: ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1); cond = build_logical_expr (INTRINSIC_NE, @@ -2708,16 +2720,17 @@ has_dimen_vector_ref (gfc_expr *e) /* If handed an expression of the form - CONJG(A) + TRANSPOSE(CONJG(A)) check if A can be handled by matmul and return if there is an uneven number of CONJG calls. Return a pointer to the array when everything is OK, NULL otherwise. The caller has to check for the correct rank. */ static gfc_expr* -check_conjg_variable (gfc_expr *e, bool *conjg) +check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose) { *conjg = false; + *transpose = false; do { @@ -2733,6 +2746,8 @@ check_conjg_variable (gfc_expr *e, bool *conjg) if (e->value.function.isym->id == GFC_ISYM_CONJG) *conjg = !*conjg; + else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE) + *transpose = !*transpose; else return NULL; } else @@ -2789,7 +2804,7 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees, int i; gfc_code *if_limit = NULL; gfc_code **next_code_point; - bool conjg_a, conjg_b; + bool conjg_a, conjg_b, transpose_a, transpose_b; if (co->op != EXEC_ASSIGN) return 0; @@ -2809,12 +2824,12 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees, changed_statement = NULL; a = expr2->value.function.actual; - matrix_a = check_conjg_variable (a->expr, &conjg_a); - if (matrix_a == NULL) + matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a); + if (transpose_a || matrix_a == NULL) return 0; b = a->next; - matrix_b = check_conjg_variable (b->expr, &conjg_b); + matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b); if (matrix_b == NULL) return 0; @@ -2828,10 +2843,28 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees, return 0; if (matrix_a->rank == 2) - m_case = matrix_b->rank == 1 ? A2B1 : A2B2; + { + if (matrix_b->rank == 1) + m_case = A2B1; + else + { + if (transpose_b) + m_case = A2B2T; + else + m_case = A2B2; + } + } else - m_case = A1B2; + { + /* Vector * Transpose(B) not handled yet. */ + if (transpose_b) + m_case = none; + else + m_case = A1B2; + } + if (m_case == none) + return 0; ns = insert_block (); @@ -3002,6 +3035,36 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees, *next_code_point = test; next_code_point = &test->next; } + + if (m_case == A2B2T) + { + c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); + a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); + test = runtime_error_ne (c1, a1, "Incorrect extent in return array in " + "MATMUL intrinsic for dimension 1: " + "is %ld, should be %ld"); + + *next_code_point = test; + next_code_point = &test->next; + + c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); + b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); + test = runtime_error_ne (c2, b1, "Incorrect extent in return array in " + "MATMUL intrinsic for dimension 2: " + "is %ld, should be %ld"); + *next_code_point = test; + next_code_point = &test->next; + + a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); + b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); + + test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in " + "MATMUL intrnisic for dimension 2: " + "is %ld, should be %ld"); + *next_code_point = test; + next_code_point = &test->next; + + } } *next_code_point = assign_zero; @@ -3050,6 +3113,39 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees, break; + case A2B2T: + inline_limit_check (matrix_a, matrix_b, m_case); + + u1 = get_size_m1 (matrix_b, 1); + u2 = get_size_m1 (matrix_a, 2); + u3 = get_size_m1 (matrix_a, 1); + + do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); + do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); + do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns); + + do_1->block->next = do_2; + do_2->block->next = do_3; + do_3->block->next = assign_matmul; + + var_1 = do_1->ext.iterator->var; + var_2 = do_2->ext.iterator->var; + var_3 = do_3->ext.iterator->var; + + list[0] = var_3; + list[1] = var_1; + cscalar = scalarized_expr (co->expr1, list, 2); + + list[0] = var_3; + list[1] = var_2; + ascalar = scalarized_expr (matrix_a, list, 2); + + list[0] = var_1; + list[1] = var_2; + bscalar = scalarized_expr (matrix_b, list, 2); + + break; + case A2B1: u1 = get_size_m1 (matrix_b, 1); u2 = get_size_m1 (matrix_a, 1); |