On Thu, 1 Oct 2015, Richard Biener wrote: > > The following patch from the match-and-simplify branch removes > gimplifier use from PRE replacing it with use of the gimple_build API > building GIMPLE directly. > > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
The 5th (or so) refactoring attempt succeeded - see below. The good thing is the code looks much easier to follow now. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2015-10-05 Richard Biener <rguent...@suse.de> * tree-ssa-pre.c (create_component_ref_by_pieces_1): Move call handling ... (create_expression_by_pieces): ... here and build GIMPLE calls directly. Use gimple_build API and avoid force_gimple_operand. (insert_into_preds_of_block): Simplify. (do_regular_insertion): Add comment. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 228467) --- gcc/tree-ssa-pre.c (working copy) *************** create_component_ref_by_pieces_1 (basic_ *** 2474,2515 **** switch (currop->opcode) { case CALL_EXPR: ! { ! tree folded, sc = NULL_TREE; ! unsigned int nargs = 0; ! tree fn, *args; ! if (TREE_CODE (currop->op0) == FUNCTION_DECL) ! fn = currop->op0; ! else ! fn = find_or_generate_expression (block, currop->op0, stmts); ! if (!fn) ! return NULL_TREE; ! if (currop->op1) ! { ! sc = find_or_generate_expression (block, currop->op1, stmts); ! if (!sc) ! return NULL_TREE; ! } ! args = XNEWVEC (tree, ref->operands.length () - 1); ! while (*operand < ref->operands.length ()) ! { ! args[nargs] = create_component_ref_by_pieces_1 (block, ref, ! operand, stmts); ! if (!args[nargs]) ! return NULL_TREE; ! nargs++; ! } ! folded = build_call_array (currop->type, ! (TREE_CODE (fn) == FUNCTION_DECL ! ? build_fold_addr_expr (fn) : fn), ! nargs, args); ! if (currop->with_bounds) ! CALL_WITH_BOUNDS_P (folded) = true; ! free (args); ! if (sc) ! CALL_EXPR_STATIC_CHAIN (folded) = sc; ! return folded; ! } case MEM_REF: { --- 2474,2480 ---- switch (currop->opcode) { case CALL_EXPR: ! gcc_unreachable (); case MEM_REF: { *************** create_expression_by_pieces (basic_block *** 2798,2818 **** switch (expr->kind) { ! /* We may hit the NAME/CONSTANT case if we have to convert types ! that value numbering saw through. */ case NAME: folded = PRE_EXPR_NAME (expr); break; case CONSTANT: ! folded = PRE_EXPR_CONSTANT (expr); ! break; ! case REFERENCE: ! { ! vn_reference_t ref = PRE_EXPR_REFERENCE (expr); ! folded = create_component_ref_by_pieces (block, ref, stmts); ! if (!folded) ! return NULL_TREE; } break; case NARY: { --- 2763,2837 ---- switch (expr->kind) { ! /* We may hit the NAME/CONSTANT case if we have to convert types ! that value numbering saw through. */ case NAME: folded = PRE_EXPR_NAME (expr); + if (useless_type_conversion_p (exprtype, TREE_TYPE (folded))) + return folded; break; case CONSTANT: ! { ! folded = PRE_EXPR_CONSTANT (expr); ! tree tem = fold_convert (exprtype, folded); ! if (is_gimple_min_invariant (tem)) ! return tem; ! break; } + case REFERENCE: + if (PRE_EXPR_REFERENCE (expr)->operands[0].opcode == CALL_EXPR) + { + vn_reference_t ref = PRE_EXPR_REFERENCE (expr); + unsigned int operand = 1; + vn_reference_op_t currop = &ref->operands[0]; + tree sc = NULL_TREE; + tree fn; + if (TREE_CODE (currop->op0) == FUNCTION_DECL) + fn = currop->op0; + else + fn = find_or_generate_expression (block, currop->op0, stmts); + if (!fn) + return NULL_TREE; + if (currop->op1) + { + sc = find_or_generate_expression (block, currop->op1, stmts); + if (!sc) + return NULL_TREE; + } + auto_vec<tree> args (ref->operands.length () - 1); + while (operand < ref->operands.length ()) + { + tree arg = create_component_ref_by_pieces_1 (block, ref, + &operand, stmts); + if (!arg) + return NULL_TREE; + args.quick_push (arg); + } + gcall *call + = gimple_build_call_vec ((TREE_CODE (fn) == FUNCTION_DECL + ? build_fold_addr_expr (fn) : fn), args); + gimple_call_set_with_bounds (call, currop->with_bounds); + if (sc) + gimple_call_set_chain (call, sc); + tree forcedname = make_ssa_name (currop->type); + gimple_call_set_lhs (call, forcedname); + gimple_set_vuse (call, BB_LIVE_VOP_ON_EXIT (block)); + gimple_seq_add_stmt_without_update (&forced_stmts, call); + folded = forcedname; + } + else + { + folded = create_component_ref_by_pieces (block, + PRE_EXPR_REFERENCE (expr), + stmts); + if (!folded) + return NULL_TREE; + name = make_temp_ssa_name (exprtype, NULL, "pretmp"); + newstmt = gimple_build_assign (name, folded); + gimple_seq_add_stmt_without_update (&forced_stmts, newstmt); + gimple_set_vuse (newstmt, BB_LIVE_VOP_ON_EXIT (block)); + folded = name; + } break; case NARY: { *************** create_expression_by_pieces (basic_block *** 2845,2866 **** for (i = 0; i < nary->length; ++i) CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, genop[i]); folded = build_constructor (nary->type, elts); } else { switch (nary->length) { case 1: ! folded = fold_build1 (nary->opcode, nary->type, ! genop[0]); break; case 2: ! folded = fold_build2 (nary->opcode, nary->type, ! genop[0], genop[1]); break; case 3: ! folded = fold_build3 (nary->opcode, nary->type, ! genop[0], genop[1], genop[2]); break; default: gcc_unreachable (); --- 2864,2889 ---- for (i = 0; i < nary->length; ++i) CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, genop[i]); folded = build_constructor (nary->type, elts); + name = make_temp_ssa_name (exprtype, NULL, "pretmp"); + newstmt = gimple_build_assign (name, folded); + gimple_seq_add_stmt_without_update (&forced_stmts, newstmt); + folded = name; } else { switch (nary->length) { case 1: ! folded = gimple_build (&forced_stmts, nary->opcode, nary->type, ! genop[0]); break; case 2: ! folded = gimple_build (&forced_stmts, nary->opcode, nary->type, ! genop[0], genop[1]); break; case 3: ! folded = gimple_build (&forced_stmts, nary->opcode, nary->type, ! genop[0], genop[1], genop[2]); break; default: gcc_unreachable (); *************** create_expression_by_pieces (basic_block *** 2872,2888 **** gcc_unreachable (); } ! if (!useless_type_conversion_p (exprtype, TREE_TYPE (folded))) ! folded = fold_convert (exprtype, folded); ! /* Force the generated expression to be a sequence of GIMPLE ! statements. ! We have to call unshare_expr because force_gimple_operand may ! modify the tree we pass to it. */ ! gimple_seq tem = NULL; ! folded = force_gimple_operand (unshare_expr (folded), &tem, ! false, NULL); ! gimple_seq_add_seq_without_update (&forced_stmts, tem); /* If we have any intermediate expressions to the value sets, add them to the value sets and chain them in the instruction stream. */ --- 2895,2909 ---- gcc_unreachable (); } ! folded = gimple_convert (&forced_stmts, exprtype, folded); ! ! /* If everything simplified to an exisiting SSA name or constant just ! return that. */ ! if (gimple_seq_empty_p (forced_stmts) ! || is_gimple_min_invariant (folded)) ! return folded; ! gcc_assert (TREE_CODE (folded) == SSA_NAME); /* If we have any intermediate expressions to the value sets, add them to the value sets and chain them in the instruction stream. */ *************** create_expression_by_pieces (basic_block *** 2895,2903 **** tree forcedname = gimple_get_lhs (stmt); pre_expr nameexpr; ! if (TREE_CODE (forcedname) == SSA_NAME) { - bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (forcedname)); VN_INFO_GET (forcedname)->valnum = forcedname; VN_INFO (forcedname)->value_id = get_next_value_id (); nameexpr = get_or_alloc_expr_for_name (forcedname); --- 2916,2923 ---- tree forcedname = gimple_get_lhs (stmt); pre_expr nameexpr; ! if (forcedname != folded) { VN_INFO_GET (forcedname)->valnum = forcedname; VN_INFO (forcedname)->value_id = get_next_value_id (); nameexpr = get_or_alloc_expr_for_name (forcedname); *************** create_expression_by_pieces (basic_block *** 2906,2925 **** bitmap_value_replace_in_set (AVAIL_OUT (block), nameexpr); } ! gimple_set_vuse (stmt, BB_LIVE_VOP_ON_EXIT (block)); ! gimple_set_modified (stmt, true); } gimple_seq_add_seq (stmts, forced_stmts); } ! name = make_temp_ssa_name (exprtype, NULL, "pretmp"); ! newstmt = gimple_build_assign (name, folded); ! gimple_set_vuse (newstmt, BB_LIVE_VOP_ON_EXIT (block)); ! gimple_set_modified (newstmt, true); ! gimple_set_plf (newstmt, NECESSARY, false); ! ! gimple_seq_add_stmt (stmts, newstmt); ! bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (name)); /* Fold the last statement. */ gsi = gsi_last (*stmts); --- 2926,2938 ---- bitmap_value_replace_in_set (AVAIL_OUT (block), nameexpr); } ! bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (forcedname)); ! gimple_set_plf (stmt, NECESSARY, false); } gimple_seq_add_seq (stmts, forced_stmts); } ! name = folded; /* Fold the last statement. */ gsi = gsi_last (*stmts); *************** create_expression_by_pieces (basic_block *** 2947,2953 **** if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserted "); ! print_gimple_stmt (dump_file, newstmt, 0, 0); fprintf (dump_file, " in predecessor %d (%04d)\n", block->index, value_id); } --- 2960,2966 ---- if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Inserted "); ! print_gimple_stmt (dump_file, gsi_stmt (gsi_last (*stmts)), 0, 0); fprintf (dump_file, " in predecessor %d (%04d)\n", block->index, value_id); } *************** insert_into_preds_of_block (basic_block *** 3004,3109 **** tree builtexpr; bprime = pred->src; eprime = avail[pred->dest_idx]; ! ! if (eprime->kind != NAME && eprime->kind != CONSTANT) { - builtexpr = create_expression_by_pieces (bprime, eprime, - &stmts, type); - gcc_assert (!(pred->flags & EDGE_ABNORMAL)); gsi_insert_seq_on_edge (pred, stmts); - if (!builtexpr) - { - /* We cannot insert a PHI node if we failed to insert - on one edge. */ - nophi = true; - continue; - } - avail[pred->dest_idx] = get_or_alloc_expr_for_name (builtexpr); insertions = true; } ! else if (eprime->kind == CONSTANT) { ! /* Constants may not have the right type, fold_convert ! should give us back a constant with the right type. */ ! tree constant = PRE_EXPR_CONSTANT (eprime); ! if (!useless_type_conversion_p (type, TREE_TYPE (constant))) ! { ! tree builtexpr = fold_convert (type, constant); ! if (!is_gimple_min_invariant (builtexpr)) ! { ! tree forcedexpr = force_gimple_operand (builtexpr, ! &stmts, true, ! NULL); ! if (!is_gimple_min_invariant (forcedexpr)) ! { ! if (forcedexpr != builtexpr) ! { ! VN_INFO_GET (forcedexpr)->valnum = PRE_EXPR_CONSTANT (eprime); ! VN_INFO (forcedexpr)->value_id = get_expr_value_id (eprime); ! } ! if (stmts) ! { ! gimple_stmt_iterator gsi; ! gsi = gsi_start (stmts); ! for (; !gsi_end_p (gsi); gsi_next (&gsi)) ! { ! gimple *stmt = gsi_stmt (gsi); ! tree lhs = gimple_get_lhs (stmt); ! if (TREE_CODE (lhs) == SSA_NAME) ! bitmap_set_bit (inserted_exprs, ! SSA_NAME_VERSION (lhs)); ! gimple_set_plf (stmt, NECESSARY, false); ! } ! gsi_insert_seq_on_edge (pred, stmts); ! } ! avail[pred->dest_idx] ! = get_or_alloc_expr_for_name (forcedexpr); ! } ! } ! else ! avail[pred->dest_idx] ! = get_or_alloc_expr_for_constant (builtexpr); ! } ! } ! else if (eprime->kind == NAME) ! { ! /* We may have to do a conversion because our value ! numbering can look through types in certain cases, but ! our IL requires all operands of a phi node have the same ! type. */ ! tree name = PRE_EXPR_NAME (eprime); ! if (!useless_type_conversion_p (type, TREE_TYPE (name))) ! { ! tree builtexpr; ! tree forcedexpr; ! builtexpr = fold_convert (type, name); ! forcedexpr = force_gimple_operand (builtexpr, ! &stmts, true, ! NULL); ! ! if (forcedexpr != name) ! { ! VN_INFO_GET (forcedexpr)->valnum = VN_INFO (name)->valnum; ! VN_INFO (forcedexpr)->value_id = VN_INFO (name)->value_id; ! } ! ! if (stmts) ! { ! gimple_stmt_iterator gsi; ! gsi = gsi_start (stmts); ! for (; !gsi_end_p (gsi); gsi_next (&gsi)) ! { ! gimple *stmt = gsi_stmt (gsi); ! tree lhs = gimple_get_lhs (stmt); ! if (TREE_CODE (lhs) == SSA_NAME) ! bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (lhs)); ! gimple_set_plf (stmt, NECESSARY, false); ! } ! gsi_insert_seq_on_edge (pred, stmts); ! } ! avail[pred->dest_idx] = get_or_alloc_expr_for_name (forcedexpr); ! } } } /* If we didn't want a phi node, and we made insertions, we still have inserted new stuff, and thus return true. If we didn't want a phi node, --- 3017,3041 ---- tree builtexpr; bprime = pred->src; eprime = avail[pred->dest_idx]; ! builtexpr = create_expression_by_pieces (bprime, eprime, ! &stmts, type); ! gcc_assert (!(pred->flags & EDGE_ABNORMAL)); ! if (!gimple_seq_empty_p (stmts)) { gsi_insert_seq_on_edge (pred, stmts); insertions = true; } ! if (!builtexpr) { ! /* We cannot insert a PHI node if we failed to insert ! on one edge. */ ! nophi = true; ! continue; } + if (is_gimple_min_invariant (builtexpr)) + avail[pred->dest_idx] = get_or_alloc_expr_for_constant (builtexpr); + else + avail[pred->dest_idx] = get_or_alloc_expr_for_name (builtexpr); } /* If we didn't want a phi node, and we made insertions, we still have inserted new stuff, and thus return true. If we didn't want a phi node, *************** do_regular_insertion (basic_block block, *** 3267,3272 **** --- 3199,3205 ---- and so not come across fake pred edges. */ gcc_assert (!(pred->flags & EDGE_FAKE)); bprime = pred->src; + /* We are looking at ANTIC_OUT of bprime. */ eprime = phi_translate (expr, ANTIC_IN (block), NULL, bprime, block);