From 70826cbbef8e6392e3d961e0054af937bcb56a16 Mon Sep 17 00:00:00 2001 From: Sebastian Pop Date: Thu, 21 Jun 2007 21:25:27 +0000 Subject: [PATCH] re PR middle-end/20623 (ICE: fold check: original tree changed by fold with --enable-checking=fold) PR middle-end/20623 * tree.h (debug_fold_checksum): Declared. * fold-const.c (build_fold_addr_expr_with_type_1): New. (build_fold_addr_expr_with_type, build_fold_addr_expr): Use build_fold_addr_expr_with_type_1. (fold_addr_expr, debug_fold_checksum): New. (fold_checksum_tree): Don't fold TREE_CHAIN of an SSA_NAME. (fold_unary, fold_comparison, split_address_to_core_and_offset): Use fold_addr_expr. From-SVN: r125929 --- gcc/ChangeLog | 12 ++++ gcc/fold-const.c | 145 +++++++++++++++++++++++++++++++++-------------- gcc/tree.h | 1 + 3 files changed, 114 insertions(+), 44 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17997e9309b..bafa24edd1b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2007-06-21 Sebastian Pop + + PR middle-end/20623 + * tree.h (debug_fold_checksum): Declared. + * fold-const.c (build_fold_addr_expr_with_type_1): New. + (build_fold_addr_expr_with_type, build_fold_addr_expr): Use + build_fold_addr_expr_with_type_1. + (fold_addr_expr, debug_fold_checksum): New. + (fold_checksum_tree): Don't fold TREE_CHAIN of an SSA_NAME. + (fold_unary, fold_comparison, split_address_to_core_and_offset): + Use fold_addr_expr. + 2007-06-21 Sebastian Pop PR tree-optimization/19590 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 9c6690ccfaa..c3b77d47e0c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7552,6 +7552,77 @@ fold_view_convert_expr (tree type, tree expr) return native_interpret_expr (type, buffer, len); } +/* Build an expression for the address of T. Folds away INDIRECT_REF + to avoid confusing the gimplify process. When IN_FOLD is true + avoid modifications of T. */ + +static tree +build_fold_addr_expr_with_type_1 (tree t, tree ptrtype, bool in_fold) +{ + /* The size of the object is not relevant when talking about its address. */ + if (TREE_CODE (t) == WITH_SIZE_EXPR) + t = TREE_OPERAND (t, 0); + + /* Note: doesn't apply to ALIGN_INDIRECT_REF */ + if (TREE_CODE (t) == INDIRECT_REF + || TREE_CODE (t) == MISALIGNED_INDIRECT_REF) + { + t = TREE_OPERAND (t, 0); + + if (TREE_TYPE (t) != ptrtype) + t = build1 (NOP_EXPR, ptrtype, t); + } + else if (!in_fold) + { + tree base = t; + + while (handled_component_p (base)) + base = TREE_OPERAND (base, 0); + + if (DECL_P (base)) + TREE_ADDRESSABLE (base) = 1; + + t = build1 (ADDR_EXPR, ptrtype, t); + } + else + t = build1 (ADDR_EXPR, ptrtype, t); + + return t; +} + +/* Build an expression for the address of T with type PTRTYPE. This + function modifies the input parameter 'T' by sometimes setting the + TREE_ADDRESSABLE flag. */ + +tree +build_fold_addr_expr_with_type (tree t, tree ptrtype) +{ + return build_fold_addr_expr_with_type_1 (t, ptrtype, false); +} + +/* Build an expression for the address of T. This function modifies + the input parameter 'T' by sometimes setting the TREE_ADDRESSABLE + flag. When called from fold functions, use fold_addr_expr instead. */ + +tree +build_fold_addr_expr (tree t) +{ + return build_fold_addr_expr_with_type_1 (t, + build_pointer_type (TREE_TYPE (t)), + false); +} + +/* Same as build_fold_addr_expr, builds an expression for the address + of T, but avoids touching the input node 't'. Fold functions + should use this version. */ + +static tree +fold_addr_expr (tree t) +{ + tree ptrtype = build_pointer_type (TREE_TYPE (t)); + + return build_fold_addr_expr_with_type_1 (t, ptrtype, true); +} /* Fold a unary expression of code CODE and type TYPE with operand OP0. Return the folded expression if folding is successful. @@ -7787,7 +7858,7 @@ fold_unary (enum tree_code code, tree type, tree op0) if (! offset && bitpos == 0 && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == TYPE_MAIN_VARIANT (TREE_TYPE (base))) - return fold_convert (type, build_fold_addr_expr (base)); + return fold_convert (type, fold_addr_expr (base)); } if ((TREE_CODE (op0) == MODIFY_EXPR @@ -8864,8 +8935,8 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) tree op0 = TREE_OPERAND (cref0, 0); tree op1 = TREE_OPERAND (cref1, 0); return fold_build2 (code, type, - build_fold_addr_expr (op0), - build_fold_addr_expr (op1)); + fold_addr_expr (op0), + fold_addr_expr (op1)); } } @@ -12775,7 +12846,8 @@ recursive_label: fold_checksum_tree (TREE_TYPE (expr), ctx, ht); if (TREE_CODE_CLASS (code) != tcc_type && TREE_CODE_CLASS (code) != tcc_declaration - && code != TREE_LIST) + && code != TREE_LIST + && code != SSA_NAME) fold_checksum_tree (TREE_CHAIN (expr), ctx, ht); switch (TREE_CODE_CLASS (code)) { @@ -12910,6 +12982,30 @@ fold_build1_stat (enum tree_code code, tree type, tree op0 MEM_STAT_DECL) return tem; } +/* Helper function for outputting the checksum of a tree T. When + debugging with gdb, you can "define mynext" to be "next" followed + by "call debug_fold_checksum (op0)", then just trace down till the + outputs differ. */ + +void +debug_fold_checksum (tree t) +{ + int i; + unsigned char checksum[16]; + struct md5_ctx ctx; + htab_t ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL); + + md5_init_ctx (&ctx); + fold_checksum_tree (t, &ctx, ht); + md5_finish_ctx (&ctx, checksum); + htab_empty (ht); + + for (i = 0; i < 16; i++) + fprintf (stderr, "%d ", checksum[i]); + + fprintf (stderr, "\n"); +} + /* Fold a binary tree expression with code CODE of type TYPE with operands OP0 and OP1. Return a folded expression if successful. Otherwise, return a tree expression with code CODE of type TYPE @@ -14171,45 +14267,6 @@ fold_build_cleanup_point_expr (tree type, tree expr) return build1 (CLEANUP_POINT_EXPR, type, expr); } -/* Build an expression for the address of T. Folds away INDIRECT_REF to - avoid confusing the gimplify process. */ - -tree -build_fold_addr_expr_with_type (tree t, tree ptrtype) -{ - /* The size of the object is not relevant when talking about its address. */ - if (TREE_CODE (t) == WITH_SIZE_EXPR) - t = TREE_OPERAND (t, 0); - - /* Note: doesn't apply to ALIGN_INDIRECT_REF */ - if (TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == MISALIGNED_INDIRECT_REF) - { - t = TREE_OPERAND (t, 0); - if (TREE_TYPE (t) != ptrtype) - t = build1 (NOP_EXPR, ptrtype, t); - } - else - { - tree base = t; - - while (handled_component_p (base)) - base = TREE_OPERAND (base, 0); - if (DECL_P (base)) - TREE_ADDRESSABLE (base) = 1; - - t = build1 (ADDR_EXPR, ptrtype, t); - } - - return t; -} - -tree -build_fold_addr_expr (tree t) -{ - return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t))); -} - /* Given a pointer value OP0 and a type TYPE, return a simplified version of an indirection through OP0, or NULL_TREE if no simplification is possible. */ @@ -14513,7 +14570,7 @@ split_address_to_core_and_offset (tree exp, core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos, poffset, &mode, &unsignedp, &volatilep, false); - core = build_fold_addr_expr (core); + core = fold_addr_expr (core); } else { diff --git a/gcc/tree.h b/gcc/tree.h index e6f1cee3c9f..5bee34cf1db 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4539,6 +4539,7 @@ extern enum built_in_function builtin_mathfn_code (tree); extern tree build_function_call_expr (tree, tree); extern tree fold_build_call_expr (tree, tree, tree, tree); extern tree fold_builtin_call_array (tree, tree, int, tree *); +extern void debug_fold_checksum (tree); extern tree build_call_expr (tree, int, ...); extern tree mathfn_built_in (tree, enum built_in_function fn); extern tree strip_float_extensions (tree);