The following fixes PR71866 and also includes some cleanup starting to address the issue at a different level (we want to insert a & -1 as we didn't manage to simplify that during phi-translation - but during insertion we _do_ simplify it and end up inserting nothing but still report "progress", so we repeat that again and again).
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2016-07-14 Richard Biener <rguent...@suse.de> PR tree-optimization/71866 * tree-ssa-pre.c (get_constant_for_value_id): Remove. (do_hoist_insertion): Avoid endless recursion when we didn't insert anything because we managed to simplify things down to a constant or SSA name. (fully_constant_expression): Re-write in terms of ... * tree-ssa-sccvn.h (vn_nary_simplify): ... this. Declare. * tree-ssa-sccvn.c (vn_nary_simplify): New wrapper around vn_nary_build_or_lookup_1. (vn_nary_build_or_lookup_1): Added flag and renamed from ... (vn_nary_build_or_lookup): ... this which now wraps it. * gcc.dg/torture/pr71866.c: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c (revision 238287) +++ gcc/tree-ssa-pre.c (working copy) @@ -1164,29 +1164,6 @@ get_or_alloc_expr_for_constant (tree con return newexpr; } -/* Given a value id V, find the actual tree representing the constant - value if there is one, and return it. Return NULL if we can't find - a constant. */ - -static tree -get_constant_for_value_id (unsigned int v) -{ - if (value_id_constant_p (v)) - { - unsigned int i; - bitmap_iterator bi; - bitmap exprset = value_expressions[v]; - - EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi) - { - pre_expr expr = expression_for_id (i); - if (expr->kind == CONSTANT) - return PRE_EXPR_CONSTANT (expr); - } - } - return NULL; -} - /* Get or allocate a pre_expr for a piece of GIMPLE, and return it. Currently only supports constants and SSA_NAMES. */ static pre_expr @@ -1236,76 +1213,16 @@ fully_constant_expression (pre_expr e) case NARY: { vn_nary_op_t nary = PRE_EXPR_NARY (e); - switch (TREE_CODE_CLASS (nary->opcode)) - { - case tcc_binary: - case tcc_comparison: - { - /* We have to go from trees to pre exprs to value ids to - constants. */ - tree naryop0 = nary->op[0]; - tree naryop1 = nary->op[1]; - tree result; - if (!is_gimple_min_invariant (naryop0)) - { - pre_expr rep0 = get_or_alloc_expr_for (naryop0); - unsigned int vrep0 = get_expr_value_id (rep0); - tree const0 = get_constant_for_value_id (vrep0); - if (const0) - naryop0 = fold_convert (TREE_TYPE (naryop0), const0); - } - if (!is_gimple_min_invariant (naryop1)) - { - pre_expr rep1 = get_or_alloc_expr_for (naryop1); - unsigned int vrep1 = get_expr_value_id (rep1); - tree const1 = get_constant_for_value_id (vrep1); - if (const1) - naryop1 = fold_convert (TREE_TYPE (naryop1), const1); - } - result = fold_binary (nary->opcode, nary->type, - naryop0, naryop1); - if (result && is_gimple_min_invariant (result)) - return get_or_alloc_expr_for_constant (result); - /* We might have simplified the expression to a - SSA_NAME for example from x_1 * 1. But we cannot - insert a PHI for x_1 unconditionally as x_1 might - not be available readily. */ - return e; - } - case tcc_reference: - if (nary->opcode != REALPART_EXPR - && nary->opcode != IMAGPART_EXPR - && nary->opcode != VIEW_CONVERT_EXPR) - return e; - /* Fallthrough. */ - case tcc_unary: - { - /* We have to go from trees to pre exprs to value ids to - constants. */ - tree naryop0 = nary->op[0]; - tree const0, result; - if (is_gimple_min_invariant (naryop0)) - const0 = naryop0; - else - { - pre_expr rep0 = get_or_alloc_expr_for (naryop0); - unsigned int vrep0 = get_expr_value_id (rep0); - const0 = get_constant_for_value_id (vrep0); - } - result = NULL; - if (const0) - { - tree type1 = TREE_TYPE (nary->op[0]); - const0 = fold_convert (type1, const0); - result = fold_unary (nary->opcode, nary->type, const0); - } - if (result && is_gimple_min_invariant (result)) - return get_or_alloc_expr_for_constant (result); - return e; - } - default: - return e; - } + tree res = vn_nary_simplify (nary); + if (!res) + return e; + if (is_gimple_min_invariant (res)) + return get_or_alloc_expr_for_constant (res); + /* We might have simplified the expression to a + SSA_NAME for example from x_1 * 1. But we cannot + insert a PHI for x_1 unconditionally as x_1 might + not be available readily. */ + return e; } case REFERENCE: { @@ -3618,10 +3552,18 @@ do_hoist_insertion (basic_block block) gimple_seq stmts = NULL; tree res = create_expression_by_pieces (block, expr, &stmts, get_expr_type (expr)); - if (gsi_end_p (last) || is_ctrl_stmt (gsi_stmt (last))) - gsi_insert_seq_before (&last, stmts, GSI_SAME_STMT); + + /* Do not return true if expression creation ultimately + did not insert any statements. */ + if (gimple_seq_empty_p (stmts)) + res = NULL_TREE; else - gsi_insert_seq_after (&last, stmts, GSI_NEW_STMT); + { + if (gsi_end_p (last) || is_ctrl_stmt (gsi_stmt (last))) + gsi_insert_seq_before (&last, stmts, GSI_SAME_STMT); + else + gsi_insert_seq_after (&last, stmts, GSI_NEW_STMT); + } /* Make sure to not return true if expression creation ultimately failed but also make sure to insert any stmts produced as they Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 238287) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_lookup_simplify_result (code_helper r *** 1625,1634 **** } /* Return a value-number for RCODE OPS... either by looking up an existing ! value-number for the simplified result or by inserting the operation. */ static tree ! vn_nary_build_or_lookup (code_helper rcode, tree type, tree *ops) { tree result = NULL_TREE; /* We will be creating a value number for --- 1625,1636 ---- } /* Return a value-number for RCODE OPS... either by looking up an existing ! value-number for the simplified result or by inserting the operation if ! INSERT is true. */ static tree ! vn_nary_build_or_lookup_1 (code_helper rcode, tree type, tree *ops, ! bool insert) { tree result = NULL_TREE; /* We will be creating a value number for *************** vn_nary_build_or_lookup (code_helper rco *** 1658,1664 **** else { tree val = vn_lookup_simplify_result (rcode, type, ops); ! if (!val) { gimple_seq stmts = NULL; result = maybe_push_res_to_seq (rcode, type, ops, &stmts); --- 1660,1666 ---- else { tree val = vn_lookup_simplify_result (rcode, type, ops); ! if (!val && insert) { gimple_seq stmts = NULL; result = maybe_push_res_to_seq (rcode, type, ops, &stmts); *************** vn_nary_build_or_lookup (code_helper rco *** 1719,1724 **** --- 1721,1749 ---- return result; } + /* Return a value-number for RCODE OPS... either by looking up an existing + value-number for the simplified result or by inserting the operation. */ + + static tree + vn_nary_build_or_lookup (code_helper rcode, tree type, tree *ops) + { + return vn_nary_build_or_lookup_1 (rcode, type, ops, true); + } + + /* Try to simplify the expression RCODE OPS... of type TYPE and return + its value if present. */ + + tree + vn_nary_simplify (vn_nary_op_t nary) + { + if (nary->length > 3) + return NULL_TREE; + tree ops[3]; + memcpy (ops, nary->op, sizeof (tree) * nary->length); + return vn_nary_build_or_lookup_1 (nary->opcode, nary->type, ops, false); + } + + /* Callback for walk_non_aliased_vuses. Tries to perform a lookup from the statement defining VUSE and if not successful tries to translate *REFP and VR_ through an aggregate copy at the definition Index: gcc/tree-ssa-sccvn.h =================================================================== *** gcc/tree-ssa-sccvn.h (revision 238287) --- gcc/tree-ssa-sccvn.h (working copy) *************** unsigned int get_constant_value_id (tree *** 234,239 **** --- 234,240 ---- unsigned int get_or_alloc_constant_value_id (tree); bool value_id_constant_p (unsigned int); tree fully_constant_vn_reference_p (vn_reference_t); + tree vn_nary_simplify (vn_nary_op_t); /* Valueize NAME if it is an SSA name, otherwise just return it. */ Index: gcc/testsuite/gcc.dg/torture/pr71866.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr71866.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr71866.c (working copy) @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-ftree-pre -fcode-hoisting" } */ + +typedef unsigned char u8; +extern unsigned long pci_io_base; +u8 in_8 (const volatile void *); +int eeh_enabled (); +void eeh_check_failure (); +static inline +u8 eeh_readb(const volatile void *addr) +{ + u8 val = in_8(addr); + if (((val) == (u8)~0 && eeh_enabled())) eeh_check_failure(); + return val; +} +extern struct ppc_pci_io { + void (*outb) (u8 val, unsigned long port); +} +ppc_pci_io; +static inline +u8 readb (const volatile void * addr) +{ + return eeh_readb((addr)); +} +static inline +u8 inb (unsigned long port) +{ + return readb((volatile void *)pci_io_base + port); +} +static inline +void outb (u8 val, unsigned long port) +{ + if (ppc_pci_io.outb != ((void *)0)) ppc_pci_io.outb (val, port); +}; +void frob_econtrol(unsigned long base_hi, unsigned char m, unsigned char v) +{ + unsigned char ectr = 0; + if (m != 0xff) ectr = inb((base_hi + 0x2)); + outb((ectr & ~m) ^ v, (base_hi + 0x2)); +}