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);
  

Reply via email to