/* Translation of isl AST to Gimple.
- Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
Contributed by Roman Gareev <gareevroman@gmail.com>.
This file is part of GCC.
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
-#include "params.h"
#include "fold-const.h"
#include "gimple-fold.h"
#include "gimple-iterator.h"
{
codegen_error = true;
gcc_assert (! flag_checking
- || PARAM_VALUE (PARAM_GRAPHITE_ALLOW_CODEGEN_ERRORS));
+ || param_graphite_allow_codegen_errors);
}
bool is_constant (tree op) const
/* 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
+ if ((expr_type == isl_ast_op_pdiv_r
+ || expr_type == isl_ast_op_zdiv_r
+ || expr_type == isl_ast_op_add)
&& 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)))
if (codegen_error_p ())
return NULL_TREE;
- return fold_build3 (COND_EXPR, type, a, b, c);
+ return fold_build3 (COND_EXPR, type, a,
+ rewrite_to_non_trapping_overflow (b),
+ rewrite_to_non_trapping_overflow (c));
}
/* Converts a unary isl_ast_expr_op expression E to a GCC expression tree of
ub = integer_zero_node;
edge last_e = single_succ_edge (split_edge (next_e));
+
+ /* Compensate for the fact that we emit a do { } while loop from
+ a for ISL AST.
+ ??? We often miss constraints on niter because the SESE region
+ doesn't cover loop header copies. Ideally we'd add constraints
+ for all relevant dominating conditions. */
+ if (TREE_CODE (lb) == INTEGER_CST && TREE_CODE (ub) == INTEGER_CST
+ && tree_int_cst_compare (lb, ub) <= 0)
+ ;
+ else
+ {
+ tree one = build_one_cst (POINTER_TYPE_P (type) ? sizetype : type);
+ /* Adding +1 and using LT_EXPR helps with loop latches that have a
+ loop iteration count of "PARAMETER - 1". For PARAMETER == 0 this
+ becomes 2^k-1 due to integer overflow, and the condition lb <= ub
+ is true, even if we do not want this. However lb < ub + 1 is false,
+ as expected. */
+ tree ub_one = fold_build2 (POINTER_TYPE_P (type)
+ ? POINTER_PLUS_EXPR : PLUS_EXPR,
+ type, unshare_expr (ub), one);
+ create_empty_if_region_on_edge (next_e,
+ fold_build2 (LT_EXPR, boolean_type_node,
+ unshare_expr (lb), ub_one));
+ next_e = get_true_edge_from_guard_bb (next_e->dest);
+ }
+
translate_isl_ast_for_loop (context_loop, node, next_e,
type, lb, ub, ip);
return last_e;
FOR_EACH_VEC_ELT (stmts, i, use_stmt)
{
gcc_assert (gimple_code (use_stmt) != GIMPLE_PHI);
- gimple_stmt_iterator gsi_def_stmt = gsi_start_bb_nondebug (begin_bb);
+ gimple_stmt_iterator gsi_def_stmt = gsi_start_nondebug_bb (begin_bb);
use_operand_p use_p;
ssa_op_iter op_iter;
else if (gimple_code (gsi_stmt (gsi_def_stmt)) == GIMPLE_PHI)
{
gimple_stmt_iterator bsi
- = gsi_start_bb_nondebug (gsi_bb (gsi_def_stmt));
+ = gsi_start_nondebug_bb (gsi_bb (gsi_def_stmt));
/* Insert right after the PHI statements. */
gsi_insert_before (&bsi, use_stmt, GSI_NEW_STMT);
}
get_rename_from_scev (tree old_name, gimple_seq *stmts, loop_p loop,
vec<tree> iv_map)
{
- tree scev = scalar_evolution_in_region (region->region, loop, old_name);
+ tree scev = cached_scalar_evolution_in_region (region->region,
+ loop, old_name);
/* At this point we should know the exact scev for each
scalar SSA_NAME used in the scop: all the other scalar
if (is_gimple_assign (stmt)
&& (lhs = gimple_assign_lhs (stmt))
&& TREE_CODE (lhs) == SSA_NAME
- && is_gimple_reg (lhs)
- && scev_analyzable_p (lhs, region->region))
+ && scev_analyzable_p (lhs, region->region)
+ /* But to code-generate liveouts - liveout PHI generation is
+ in generic sese.c code that cannot do code generation. */
+ && ! bitmap_bit_p (region->liveout, SSA_NAME_VERSION (lhs)))
return false;
return true;
{
if (gimple_debug_bind_p (copy))
gimple_debug_bind_reset_value (copy);
- else if (gimple_debug_source_bind_p (copy))
+ else if (gimple_debug_source_bind_p (copy)
+ || gimple_debug_nonbind_marker_p (copy))
;
else
gcc_unreachable ();
{
int old_err = isl_options_get_on_error (scop->isl_context);
int old_max_operations = isl_ctx_get_max_operations (scop->isl_context);
- int max_operations = PARAM_VALUE (PARAM_MAX_ISL_OPERATIONS);
+ int max_operations = param_max_isl_operations;
if (max_operations)
isl_ctx_set_max_operations (scop->isl_context, max_operations);
isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
isl_ctx_set_max_operations (scop->isl_context, old_max_operations);
if (isl_ctx_last_error (scop->isl_context) != isl_error_none)
{
- location_t loc = find_loop_location
- (scop->scop_info->region.entry->dest->loop_father);
- if (isl_ctx_last_error (scop->isl_context) == isl_error_quota)
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
- "loop nest not optimized, AST generation timed out "
- "after %d operations [--param max-isl-operations]\n",
- max_operations);
- else
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
- "loop nest not optimized, ISL AST generation "
- "signalled an error\n");
+ if (dump_enabled_p ())
+ {
+ dump_user_location_t loc = find_loop_location
+ (scop->scop_info->region.entry->dest->loop_father);
+ if (isl_ctx_last_error (scop->isl_context) == isl_error_quota)
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "loop nest not optimized, AST generation timed out "
+ "after %d operations [--param max-isl-operations]\n",
+ max_operations);
+ else
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "loop nest not optimized, ISL AST generation "
+ "signalled an error\n");
+ }
isl_ast_node_free (ast_isl);
return NULL;
}
if (t.codegen_error_p ())
{
- location_t loc = find_loop_location
- (scop->scop_info->region.entry->dest->loop_father);
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
- "loop nest not optimized, code generation error\n");
+ if (dump_enabled_p ())
+ {
+ dump_user_location_t loc = find_loop_location
+ (scop->scop_info->region.entry->dest->loop_father);
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
+ "loop nest not optimized, code generation error\n");
+ }
/* Remove the unreachable region. */
remove_edge_and_dominated_blocks (if_region->true_region->region.entry);