diff --git a/gcc/match.pd b/gcc/match.pd index 3680b89713d..c68eed70a26 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -425,12 +425,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { build_minus_one_cst (type); }))) /* For unsigned integral types, FLOOR_DIV_EXPR is the same as - TRUNC_DIV_EXPR. Rewrite into the latter in this case. */ -(simplify - (floor_div @0 @1) - (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) - && TYPE_UNSIGNED (type)) - (trunc_div @0 @1))) + TRUNC_DIV_EXPR. Rewrite into the latter in this case. Similarly + for MOD instead of DIV. */ +(for floor_divmod (floor_div floor_mod) + trunc_divmod (trunc_div trunc_mod) + (simplify + (floor_divmod @0 @1) + (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) + && TYPE_UNSIGNED (type)) + (trunc_divmod @0 @1)))) /* Combine two successive divisions. Note that combining ceil_div and floor_div is trickier and combining round_div even more so. */ diff --git a/gcc/optabs-tree.cc b/gcc/optabs-tree.cc index 78e388d82f6..8383fe820b0 100644 --- a/gcc/optabs-tree.cc +++ b/gcc/optabs-tree.cc @@ -56,17 +56,32 @@ optab_for_tree_code (enum tree_code code, const_tree type, case MULT_HIGHPART_EXPR: return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab; - case TRUNC_MOD_EXPR: case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case ROUND_MOD_EXPR: + /* {s,u}mod_optab implements TRUNC_MOD_EXPR. For scalar modes, + expansion has code to adjust TRUNC_MOD_EXPR into the desired other + modes, but for vector modes it does not. The adjustment code + should be instead emitted in tree-vect-patterns.cc. */ + if (TREE_CODE (type) == VECTOR_TYPE) + return unknown_optab; + /* FALLTHRU */ + case TRUNC_MOD_EXPR: return TYPE_UNSIGNED (type) ? umod_optab : smod_optab; - case RDIV_EXPR: - case TRUNC_DIV_EXPR: case CEIL_DIV_EXPR: case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: + /* {,u}{s,u}div_optab implements {TRUNC,EXACT}_DIV_EXPR or RDIV_EXPR. + For scalar modes, expansion has code to adjust TRUNC_DIV_EXPR + into the desired other modes, but for vector modes it does not. + The adjustment code should be instead emitted in + tree-vect-patterns.cc. */ + if (TREE_CODE (type) == VECTOR_TYPE) + return unknown_optab; + /* FALLTHRU */ + case RDIV_EXPR: + case TRUNC_DIV_EXPR: case EXACT_DIV_EXPR: if (TYPE_SATURATING (type)) return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab; diff --git a/gcc/testsuite/gfortran.dg/pr102860.f90 b/gcc/testsuite/gfortran.dg/pr102860.f90 new file mode 100644 index 00000000000..d0a7356c0f5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr102860.f90 @@ -0,0 +1,10 @@ +! PR middle-end/102860 +! { dg-do compile { target { powerpc*-*-* } } } +! { dg-require-effective-target powerpc_vsx_ok } +! { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power10" } } +! { dg-options "-O2 -mcpu=power10" } + +function foo(a) + integer(kind=4) :: a(1024) + a(:) = modulo (a(:), 39) +end function