From 8146bb588770d63c8f4a2ca2a1eb31d3643b71bc Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Mon, 30 Nov 2009 20:35:41 +0000 Subject: [PATCH] re PR fortran/42131 (Weird translation of DO loops) 2009-11-30 Thomas Koenig PR fortran/42131 * trans-stmt.c (gfc_trans_do): Calculate loop count without if statements. From-SVN: r154839 --- gcc/fortran/ChangeLog | 6 +++++ gcc/fortran/trans-stmt.c | 57 ++++++++++++++++++++++++++-------------- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 8b6c4ce6a9cf..03c15484dc25 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2009-11-30 Thomas Koenig + + PR fortran/42131 + * trans-stmt.c (gfc_trans_do): Calculate loop count + without if statements. + 2009-11-28 Jakub Jelinek * trans-common.c (create_common): Remove unused offset variable. diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 9b2a62308530..04115885773d 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1009,44 +1009,61 @@ gfc_trans_do (gfc_code * code) /* Initialize loop count and jump to exit label if the loop is empty. This code is executed before we enter the loop body. We generate: + step_sign = sign(1,step); if (step > 0) { - if (to < from) goto exit_label; - countm1 = (to - from) / step; + if (to < from) + goto exit_label; } else { - if (to > from) goto exit_label; - countm1 = (from - to) / -step; - } */ + if (to > from) + goto exit_label; + } + countm1 = (to*step_sign - from*step_sign) / (step*step_sign); + + */ + if (TREE_CODE (type) == INTEGER_TYPE) { - tree pos, neg; + tree pos, neg, step_sign, to2, from2, step2; + + /* Calculate SIGN (1,step) */ + + tmp = fold_build2 (RSHIFT_EXPR, type, step, + build_int_cst (type, + TYPE_PRECISION (type) - 1)); + + tmp = fold_build2 (MULT_EXPR, type, tmp, + build_int_cst (type, 2)); + + step_sign = fold_build2 (PLUS_EXPR, type, tmp, + fold_convert (type, integer_one_node)); tmp = fold_build2 (LT_EXPR, boolean_type_node, to, from); pos = fold_build3 (COND_EXPR, void_type_node, tmp, build1_v (GOTO_EXPR, exit_label), build_empty_stmt (input_location)); - tmp = fold_build2 (MINUS_EXPR, type, to, from); - tmp = fold_convert (utype, tmp); - tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp, - fold_convert (utype, step)); - tmp = fold_build2 (MODIFY_EXPR, void_type_node, countm1, tmp); - pos = fold_build2 (COMPOUND_EXPR, void_type_node, pos, tmp); tmp = fold_build2 (GT_EXPR, boolean_type_node, to, from); neg = fold_build3 (COND_EXPR, void_type_node, tmp, build1_v (GOTO_EXPR, exit_label), build_empty_stmt (input_location)); - tmp = fold_build2 (MINUS_EXPR, type, from, to); - tmp = fold_convert (utype, tmp); - tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp, - fold_convert (utype, fold_build1 (NEGATE_EXPR, - type, step))); - tmp = fold_build2 (MODIFY_EXPR, void_type_node, countm1, tmp); - neg = fold_build2 (COMPOUND_EXPR, void_type_node, neg, tmp); - tmp = fold_build3 (COND_EXPR, void_type_node, pos_step, pos, neg); + + gfc_add_expr_to_block (&block, tmp); + + /* Calculate the loop count. to-from can overflow, so + we cast to unsigned. */ + + to2 = fold_build2 (MULT_EXPR, type, step_sign, to); + from2 = fold_build2 (MULT_EXPR, type, step_sign, from); + step2 = fold_build2 (MULT_EXPR, type, step_sign, step); + step2 = fold_convert (utype, step2); + tmp = fold_build2 (MINUS_EXPR, type, to2, from2); + tmp = fold_convert (utype, tmp); + tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp, step2); + tmp = fold_build2 (MODIFY_EXPR, void_type_node, countm1, tmp); gfc_add_expr_to_block (&block, tmp); } else