Commit 1163f058 by Richard Biener Committed by Richard Biener

re PR tree-optimization/82525 ([GRAPHITE] codegen error for modulo operations we cannot represent)

2017-10-13  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82525
	* graphite-isl-ast-to-gimple.c
	(translate_isl_ast_to_gimple::widest_int_from_isl_expr_int): Split
	out from ...
	(translate_isl_ast_to_gimple::gcc_expression_from_isl_expr_int): Here.
	Fail code generation when we cannot represent the isl integer.
	(binary_op_to_tree): Elide modulo operations that are no-ops
	in the type we code generate.  Remove now superfluous code
	generation errors.

	* gcc.dg/graphite/id-30.c: New testcase.
	* gfortran.dg/graphite/id-28.f90: Likewise.

From-SVN: r253706
parent cae827b1
2017-10-13 Richard Biener <rguenther@suse.de> 2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82525
* graphite-isl-ast-to-gimple.c
(translate_isl_ast_to_gimple::widest_int_from_isl_expr_int): Split
out from ...
(translate_isl_ast_to_gimple::gcc_expression_from_isl_expr_int): Here.
Fail code generation when we cannot represent the isl integer.
(binary_op_to_tree): Elide modulo operations that are no-ops
in the type we code generate. Remove now superfluous code
generation errors.
2017-10-13 Richard Biener <rguenther@suse.de>
* graphite-scop-detection.c (loop_ivs_can_be_represented): Remove. * graphite-scop-detection.c (loop_ivs_can_be_represented): Remove.
(scop_detection::harmful_loop_in_region): Remove premature (scop_detection::harmful_loop_in_region): Remove premature
IV type restriction. IV type restriction.
...@@ -177,6 +177,7 @@ class translate_isl_ast_to_gimple ...@@ -177,6 +177,7 @@ class translate_isl_ast_to_gimple
tree gcc_expression_from_isl_ast_expr_id (tree type, tree gcc_expression_from_isl_ast_expr_id (tree type,
__isl_keep isl_ast_expr *expr_id, __isl_keep isl_ast_expr *expr_id,
ivs_params &ip); ivs_params &ip);
widest_int widest_int_from_isl_expr_int (__isl_keep isl_ast_expr *expr);
tree gcc_expression_from_isl_expr_int (tree type, tree gcc_expression_from_isl_expr_int (tree type,
__isl_take isl_ast_expr *expr); __isl_take isl_ast_expr *expr);
tree gcc_expression_from_isl_expr_op (tree type, tree gcc_expression_from_isl_expr_op (tree type,
...@@ -265,29 +266,46 @@ gcc_expression_from_isl_ast_expr_id (tree type, ...@@ -265,29 +266,46 @@ gcc_expression_from_isl_ast_expr_id (tree type,
return fold_convert (type, *val); return fold_convert (type, *val);
} }
/* Converts an isl_ast_expr_int expression E to a GCC expression tree of /* Converts an isl_ast_expr_int expression E to a widest_int.
type TYPE. */ Raises a code generation error when the constant doesn't fit. */
tree translate_isl_ast_to_gimple:: widest_int translate_isl_ast_to_gimple::
gcc_expression_from_isl_expr_int (tree type, __isl_take isl_ast_expr *expr) widest_int_from_isl_expr_int (__isl_keep isl_ast_expr *expr)
{ {
gcc_assert (isl_ast_expr_get_type (expr) == isl_ast_expr_int); gcc_assert (isl_ast_expr_get_type (expr) == isl_ast_expr_int);
isl_val *val = isl_ast_expr_get_val (expr); isl_val *val = isl_ast_expr_get_val (expr);
size_t n = isl_val_n_abs_num_chunks (val, sizeof (HOST_WIDE_INT)); size_t n = isl_val_n_abs_num_chunks (val, sizeof (HOST_WIDE_INT));
HOST_WIDE_INT *chunks = XALLOCAVEC (HOST_WIDE_INT, n); HOST_WIDE_INT *chunks = XALLOCAVEC (HOST_WIDE_INT, n);
tree res; if (n > WIDE_INT_MAX_ELTS
if (isl_val_get_abs_num_chunks (val, sizeof (HOST_WIDE_INT), chunks) == -1) || isl_val_get_abs_num_chunks (val, sizeof (HOST_WIDE_INT), chunks) == -1)
res = NULL_TREE;
else
{ {
widest_int wi = widest_int::from_array (chunks, n, true); isl_val_free (val);
if (isl_val_is_neg (val)) set_codegen_error ();
wi = -wi; return 0;
res = wide_int_to_tree (type, wi);
} }
widest_int wi = widest_int::from_array (chunks, n, true);
if (isl_val_is_neg (val))
wi = -wi;
isl_val_free (val); isl_val_free (val);
return wi;
}
/* Converts an isl_ast_expr_int expression E to a GCC expression tree of
type TYPE. Raises a code generation error when the constant doesn't fit. */
tree translate_isl_ast_to_gimple::
gcc_expression_from_isl_expr_int (tree type, __isl_take isl_ast_expr *expr)
{
widest_int wi = widest_int_from_isl_expr_int (expr);
isl_ast_expr_free (expr); isl_ast_expr_free (expr);
return res; if (codegen_error_p ())
return NULL_TREE;
if (wi::min_precision (wi, TYPE_SIGN (type)) > TYPE_PRECISION (type))
{
set_codegen_error ();
return NULL_TREE;
}
return wide_int_to_tree (type, wi);
} }
/* Converts a binary isl_ast_expr_op expression E to a GCC expression tree of /* Converts a binary isl_ast_expr_op expression E to a GCC expression tree of
...@@ -296,14 +314,25 @@ gcc_expression_from_isl_expr_int (tree type, __isl_take isl_ast_expr *expr) ...@@ -296,14 +314,25 @@ gcc_expression_from_isl_expr_int (tree type, __isl_take isl_ast_expr *expr)
tree translate_isl_ast_to_gimple:: tree translate_isl_ast_to_gimple::
binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip) binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
{ {
enum isl_ast_op_type expr_type = isl_ast_expr_get_op_type (expr);
isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0); isl_ast_expr *arg_expr = isl_ast_expr_get_op_arg (expr, 0);
tree tree_lhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip); tree tree_lhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
arg_expr = isl_ast_expr_get_op_arg (expr, 1); arg_expr = isl_ast_expr_get_op_arg (expr, 1);
tree tree_rhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
enum isl_ast_op_type expr_type = isl_ast_expr_get_op_type (expr);
isl_ast_expr_free (expr); isl_ast_expr_free (expr);
/* From our constraint generation we may get modulo operations that
we cannot represent explicitely but that are no-ops for TYPE.
Elide those. */
if (expr_type == isl_ast_op_pdiv_r
&& isl_ast_expr_get_type (arg_expr) == isl_ast_expr_int
&& (wi::exact_log2 (widest_int_from_isl_expr_int (arg_expr))
>= TYPE_PRECISION (type)))
{
isl_ast_expr_free (arg_expr);
return tree_lhs_expr;
}
tree tree_rhs_expr = gcc_expression_from_isl_expression (type, arg_expr, ip);
if (codegen_error_p ()) if (codegen_error_p ())
return NULL_TREE; return NULL_TREE;
...@@ -319,44 +348,16 @@ binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip) ...@@ -319,44 +348,16 @@ binary_op_to_tree (tree type, __isl_take isl_ast_expr *expr, ivs_params &ip)
return fold_build2 (MULT_EXPR, type, tree_lhs_expr, tree_rhs_expr); return fold_build2 (MULT_EXPR, type, tree_lhs_expr, tree_rhs_expr);
case isl_ast_op_div: case isl_ast_op_div:
/* As isl operates on arbitrary precision numbers, we may end up with
division by 2^64 that is folded to 0. */
if (integer_zerop (tree_rhs_expr))
{
set_codegen_error ();
return NULL_TREE;
}
return fold_build2 (EXACT_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr); return fold_build2 (EXACT_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
case isl_ast_op_pdiv_q: case isl_ast_op_pdiv_q:
/* As isl operates on arbitrary precision numbers, we may end up with
division by 2^64 that is folded to 0. */
if (integer_zerop (tree_rhs_expr))
{
set_codegen_error ();
return NULL_TREE;
}
return fold_build2 (TRUNC_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr); return fold_build2 (TRUNC_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
case isl_ast_op_zdiv_r: case isl_ast_op_zdiv_r:
case isl_ast_op_pdiv_r: case isl_ast_op_pdiv_r:
/* As isl operates on arbitrary precision numbers, we may end up with
division by 2^64 that is folded to 0. */
if (integer_zerop (tree_rhs_expr))
{
set_codegen_error ();
return NULL_TREE;
}
return fold_build2 (TRUNC_MOD_EXPR, type, tree_lhs_expr, tree_rhs_expr); return fold_build2 (TRUNC_MOD_EXPR, type, tree_lhs_expr, tree_rhs_expr);
case isl_ast_op_fdiv_q: case isl_ast_op_fdiv_q:
/* As isl operates on arbitrary precision numbers, we may end up with
division by 2^64 that is folded to 0. */
if (integer_zerop (tree_rhs_expr))
{
set_codegen_error ();
return NULL_TREE;
}
return fold_build2 (FLOOR_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr); return fold_build2 (FLOOR_DIV_EXPR, type, tree_lhs_expr, tree_rhs_expr);
case isl_ast_op_and: case isl_ast_op_and:
......
2017-10-13 Richard Biener <rguenther@suse.de>
PR tree-optimization/82525
* gcc.dg/graphite/id-30.c: New testcase.
* gfortran.dg/graphite/id-28.f90: Likewise.
2017-10-13 Alan Modra <amodra@gmail.com> 2017-10-13 Alan Modra <amodra@gmail.com>
* gcc.target/i386/asm-mem.c: New test. * gcc.target/i386/asm-mem.c: New test.
......
/* The modulo constraints we generate for the niter expression
(unsinged long)ubound - (unsigned long)lbound
end up with a modulo that we cannot represent in the expression
type we are using (int64_t), so we run into the codegen error
where ISL generates a modulo/divide by sth that doesn't fit the
type we code-generate with. Verify we properly elide those. */
void foo (double *a, long int lbound0, long int ubound0,
long int lbound1, long int ubound1, long int stride1)
{
if (lbound0 < ubound0)
for (long int i = lbound0; i <= ubound0; ++i)
if (lbound1 < ubound1)
for (long int j = lbound1; j <= ubound1; ++j)
a[i*stride1 + j] = 0.;
}
! Verify we elide modulo operations we cannot represent
module OPMATRIX_MODULE
implicit none
type opmatrix_type
real(kind=kind(1.0d0)), dimension(:,:), pointer :: restricted
end type
interface zero_
module procedure zero
end interface
contains
subroutine zero(self)
type(opmatrix_type) :: self
self%restricted = 0.0d0
end subroutine
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment