This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][1/n] Merge from match-and-simplify, public API


This introduces the gimple_build API and exposes the gimple_simplify
API that the genmatch generator provides.

With this patch we have a first user of the (still no-op) machinery
which is PRE where I cherry-picked a part of the branch to fix a bug
earlier (and provided a different implementation for gimple_convert).
This specific user is fine with not simplifying anything.

To re-iterate, the API removes the need for GIMPLE passes to build
GENERIC expressions via fold_buildN just to get some basic
simplification applied and then turn the result into GIMPLE
via force_gimple_operand and friends.  So instead of doing

  ratio_name
    = fold_build2 (PLUS_EXPR, TREE_TYPE (ni_name),
                   fold_build2 (RSHIFT_EXPR, TREE_TYPE (ni_name),
                                fold_build2 (MINUS_EXPR, TREE_TYPE (ni_name),
                                             ni_minus_gap_name,
                                             build_int_cst
                                               (TREE_TYPE (ni_name), vf)),
                                log_vf),
                   build_int_cst (TREE_TYPE (ni_name), 1));
  if (!is_gimple_val (ratio_name))
    {
      var = create_tmp_var (TREE_TYPE (ni_name), "bnd");
      gimple stmts = NULL;
      ratio_name = force_gimple_operand (ratio_name, &stmts, true, var);
      gsi_insert_seq_on_edge_immediate (pe, stmts);

you'd do

  stmts = NULL;
  ratio_name
    = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (ni_name),
                    gimple_build (&stmts, RSHIFT_EXPR, TREE_TYPE (ni_name),
                                  gimple_build (&stmts, MINUS_EXPR,
                                                TREE_TYPE (ni_name),
                                                ni_minus_gap_name,
                                                build_int_cst
                                                  (TREE_TYPE (ni_name), vf)),
                                  log_vf);
                    build_int_cst (TREE_TYPE (ni_name), 1));
  gsi_insert_seq_on_edge_immediate (pe, stmts);

which even with the current lack of patterns after this patch would
get you simplifications to constants and operand canonicalization
which is what the GIMPLE passes are usually after when asking
for simplifications when building expressions (note, patterns
for a * 1, a * 0, a + 0, etc. are still required to not regress
expected simplifications here - those will follow soon).

Bootstrap and regtest scheduled on x86_64-unknown-linux-gnu.

Ok?

Thanks,
Richard.

2014-10-15  Richard Biener  <rguenther@suse.de>

	* gimple-fold.h (gimple_build): Declare various overloads.
	(gimple_simplify): Likewise.
	(gimple_convert): Re-implement in terms of gimple_build.
	* gimple-fold.c (gimple_convert): Remove.
	(gimple_build): New functions.

Index: gcc/gimple-fold.h
===================================================================
*** gcc/gimple-fold.h.orig	2014-10-14 15:49:30.657356177 +0200
--- gcc/gimple-fold.h	2014-10-15 13:01:41.548100887 +0200
*************** extern tree gimple_fold_indirect_ref (tr
*** 45,55 ****
  extern bool arith_code_with_undefined_signed_overflow (tree_code);
  extern gimple_seq rewrite_to_defined_overflow (gimple);
  
! extern tree gimple_convert (gimple_seq *, location_t, tree, tree);
  inline tree
  gimple_convert (gimple_seq *seq, tree type, tree op)
  {
    return gimple_convert (seq, UNKNOWN_LOCATION, type, op);
  }
  
  #endif  /* GCC_GIMPLE_FOLD_H */
--- 45,141 ----
  extern bool arith_code_with_undefined_signed_overflow (tree_code);
  extern gimple_seq rewrite_to_defined_overflow (gimple);
  
! /* gimple_build, functionally matching fold_buildN, outputs stmts
!    int the provided sequence, matching and simplifying them on-the-fly.
!    Supposed to replace force_gimple_operand (fold_buildN (...), ...).  */
! tree gimple_build (gimple_seq *, location_t,
! 		   enum tree_code, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum tree_code code, tree type, tree op0)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0);
! }
! tree gimple_build (gimple_seq *, location_t,
! 		   enum tree_code, tree, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum tree_code code, tree type, tree op0, tree op1)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1);
! }
! tree gimple_build (gimple_seq *, location_t,
! 		   enum tree_code, tree, tree, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum tree_code code, tree type, tree op0, tree op1, tree op2)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, code, type, op0, op1, op2);
! }
! tree gimple_build (gimple_seq *, location_t,
! 		   enum built_in_function, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum built_in_function fn, tree type, tree arg0)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0);
! }
! tree gimple_build (gimple_seq *, location_t,
! 		   enum built_in_function, tree, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum built_in_function fn, tree type, tree arg0, tree arg1)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1);
! }
! tree gimple_build (gimple_seq *, location_t,
! 		   enum built_in_function, tree, tree, tree, tree,
! 		   tree (*valueize) (tree) = NULL);
! inline tree
! gimple_build (gimple_seq *seq,
! 	      enum built_in_function fn, tree type,
! 	      tree arg0, tree arg1, tree arg2)
! {
!   return gimple_build (seq, UNKNOWN_LOCATION, fn, type, arg0, arg1, arg2);
! }
! 
! /* ???  Forward from gimple-expr.h.  */
! extern bool useless_type_conversion_p (tree, tree);
! 
! inline tree
! gimple_convert (gimple_seq *seq, location_t loc, tree type, tree op)
! {
!   if (useless_type_conversion_p (type, TREE_TYPE (op)))
!     return op;
!   return gimple_build (seq, loc, NOP_EXPR, type, op);
! }
! 
  inline tree
  gimple_convert (gimple_seq *seq, tree type, tree op)
  {
    return gimple_convert (seq, UNKNOWN_LOCATION, type, op);
  }
  
+ /* Add gimple_seq_discard (gimple_seq *) that releases defs of all stmts
+    in the sequence.  */
+ 
+ /* In gimple-match.c.  */
+ tree gimple_simplify (enum tree_code, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ tree gimple_simplify (enum tree_code, tree, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ tree gimple_simplify (enum tree_code, tree, tree, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ tree gimple_simplify (enum built_in_function, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ tree gimple_simplify (enum built_in_function, tree, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ tree gimple_simplify (enum built_in_function, tree, tree, tree, tree,
+ 		      gimple_seq *, tree (*)(tree));
+ 
  #endif  /* GCC_GIMPLE_FOLD_H */
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c.orig	2014-10-14 15:49:30.634356179 +0200
--- gcc/gimple-fold.c	2014-10-15 13:02:08.158099055 +0200
*************** along with GCC; see the file COPYING3.
*** 56,61 ****
--- 56,62 ----
  #include "builtins.h"
  #include "output.h"
  
+ 
  /* Return true when DECL can be referenced from current unit.
     FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
     We can get declarations that are not possible to reference for various
*************** rewrite_to_defined_overflow (gimple stmt
*** 5296,5314 ****
    return stmts;
  }
  
! /* Return OP converted to TYPE by emitting a conversion statement on SEQ
!    if required using location LOC.  Note that OP will be returned
!    unmodified if GIMPLE does not require an explicit conversion between
!    its type and TYPE.  */
  
  tree
! gimple_convert (gimple_seq *seq, location_t loc, tree type, tree op)
  {
!   if (useless_type_conversion_p (type, TREE_TYPE (op)))
!     return op;
!   op = fold_convert_loc (loc, type, op);
!   gimple_seq stmts = NULL;
!   op = force_gimple_operand (op, &stmts, true, NULL_TREE);
!   gimple_seq_add_seq_without_update (seq, stmts);
!   return op;
  }
--- 5297,5487 ----
    return stmts;
  }
  
! 
! 
! /* Build the expression CODE OP0 of type TYPE with location LOC,
!    simplifying it first if possible using VALUEIZE if not NULL.
!    OP0 is expected to be valueized already.  Returns the built
!    expression value and appends statements possibly defining it
!    to SEQ.  */
  
  tree
! gimple_build (gimple_seq *seq, location_t loc,
! 	      enum tree_code code, tree type, tree op0,
! 	      tree (*valueize)(tree))
  {
!   tree res = gimple_simplify (code, type, op0, seq, valueize);
!   if (!res)
!     {
!       if (gimple_in_ssa_p (cfun))
! 	res = make_ssa_name (type, NULL);
!       else
! 	res = create_tmp_reg (type, NULL);
!       gimple stmt;
!       if (code == REALPART_EXPR
! 	  || code == IMAGPART_EXPR
! 	  || code == VIEW_CONVERT_EXPR)
! 	stmt = gimple_build_assign_with_ops (code, res,
! 					     build1 (code, type,
! 						     op0), NULL_TREE);
!       else
! 	stmt = gimple_build_assign_with_ops (code, res, op0, NULL_TREE);
!       gimple_set_location (stmt, loc);
!       gimple_seq_add_stmt_without_update (seq, stmt);
!     }
!   return res;
! }
! 
! /* Build the expression OP0 CODE OP1 of type TYPE with location LOC,
!    simplifying it first if possible using VALUEIZE if not NULL.
!    OP0 and OP1 are expected to be valueized already.  Returns the built
!    expression value and appends statements possibly defining it
!    to SEQ.  */
! 
! tree
! gimple_build (gimple_seq *seq, location_t loc,
! 	      enum tree_code code, tree type, tree op0, tree op1,
! 	      tree (*valueize)(tree))
! {
!   tree res = gimple_simplify (code, type, op0, op1, seq, valueize);
!   if (!res)
!     {
!       if (gimple_in_ssa_p (cfun))
! 	res = make_ssa_name (type, NULL);
!       else
! 	res = create_tmp_reg (type, NULL);
!       gimple stmt = gimple_build_assign_with_ops (code, res, op0, op1);
!       gimple_set_location (stmt, loc);
!       gimple_seq_add_stmt_without_update (seq, stmt);
!     }
!   return res;
  }
+ 
+ 
+ /* Build the expression (CODE OP0 OP1 OP2) of type TYPE with location LOC,
+    simplifying it first if possible using VALUEIZE if not NULL.
+    OP0, OP1 and OP2 are expected to be valueized already.  Returns the built
+    expression value and appends statements possibly defining it
+    to SEQ.  */
+ 
+ tree
+ gimple_build (gimple_seq *seq, location_t loc,
+ 	      enum tree_code code, tree type, tree op0, tree op1, tree op2,
+ 	      tree (*valueize)(tree))
+ {
+   tree res = gimple_simplify (code, type, op0, op1, op2,
+ 			      seq, valueize);
+   if (!res)
+     {
+       if (gimple_in_ssa_p (cfun))
+ 	res = make_ssa_name (type, NULL);
+       else
+ 	res = create_tmp_reg (type, NULL);
+       gimple stmt;
+       if (code == BIT_FIELD_REF)
+ 	stmt = gimple_build_assign_with_ops (code, res,
+ 					     build3 (BIT_FIELD_REF, type,
+ 						     op0, op1, op2),
+ 					     NULL_TREE);
+       else
+ 	stmt = gimple_build_assign_with_ops (code, res, op0, op1, op2);
+       gimple_set_location (stmt, loc);
+       gimple_seq_add_stmt_without_update (seq, stmt);
+     }
+   return res;
+ }
+ 
+ /* Build the call FN (ARG0) with a result of type TYPE
+    (or no result if TYPE is void) with location LOC,
+    simplifying it first if possible using VALUEIZE if not NULL.
+    ARG0 is expected to be valueized already.  Returns the built
+    expression value (or NULL_TREE if TYPE is void) and appends
+    statements possibly defining it to SEQ.  */
+ 
+ tree
+ gimple_build (gimple_seq *seq, location_t loc,
+ 	      enum built_in_function fn, tree type, tree arg0,
+ 	      tree (*valueize)(tree))
+ {
+   tree res = gimple_simplify (fn, type, arg0, seq, valueize);
+   if (!res)
+     {
+       tree decl = builtin_decl_implicit (fn);
+       gimple stmt = gimple_build_call (decl, 1, arg0);
+       if (!VOID_TYPE_P (type))
+ 	{
+ 	  if (gimple_in_ssa_p (cfun))
+ 	    res = make_ssa_name (type, NULL);
+ 	  else
+ 	    res = create_tmp_reg (type, NULL);
+ 	  gimple_call_set_lhs (stmt, res);
+ 	}
+       gimple_set_location (stmt, loc);
+       gimple_seq_add_stmt_without_update (seq, stmt);
+     }
+   return res;
+ }
+ 
+ /* Build the call FN (ARG0, ARG1) with a result of type TYPE
+    (or no result if TYPE is void) with location LOC,
+    simplifying it first if possible using VALUEIZE if not NULL.
+    ARG0 is expected to be valueized already.  Returns the built
+    expression value (or NULL_TREE if TYPE is void) and appends
+    statements possibly defining it to SEQ.  */
+ 
+ tree
+ gimple_build (gimple_seq *seq, location_t loc,
+ 	      enum built_in_function fn, tree type, tree arg0, tree arg1,
+ 	      tree (*valueize)(tree))
+ {
+   tree res = gimple_simplify (fn, type, arg0, arg1, seq, valueize);
+   if (!res)
+     {
+       tree decl = builtin_decl_implicit (fn);
+       gimple stmt = gimple_build_call (decl, 2, arg0, arg1);
+       if (!VOID_TYPE_P (type))
+ 	{
+ 	  if (gimple_in_ssa_p (cfun))
+ 	    res = make_ssa_name (type, NULL);
+ 	  else
+ 	    res = create_tmp_reg (type, NULL);
+ 	  gimple_call_set_lhs (stmt, res);
+ 	}
+       gimple_set_location (stmt, loc);
+       gimple_seq_add_stmt_without_update (seq, stmt);
+     }
+   return res;
+ }
+ 
+ /* Build the call FN (ARG0, ARG1, ARG2) with a result of type TYPE
+    (or no result if TYPE is void) with location LOC,
+    simplifying it first if possible using VALUEIZE if not NULL.
+    ARG0 is expected to be valueized already.  Returns the built
+    expression value (or NULL_TREE if TYPE is void) and appends
+    statements possibly defining it to SEQ.  */
+ 
+ tree
+ gimple_build (gimple_seq *seq, location_t loc,
+ 	      enum built_in_function fn, tree type,
+ 	      tree arg0, tree arg1, tree arg2,
+ 	      tree (*valueize)(tree))
+ {
+   tree res = gimple_simplify (fn, type, arg0, arg1, arg2, seq, valueize);
+   if (!res)
+     {
+       tree decl = builtin_decl_implicit (fn);
+       gimple stmt = gimple_build_call (decl, 3, arg0, arg1, arg2);
+       if (!VOID_TYPE_P (type))
+ 	{
+ 	  if (gimple_in_ssa_p (cfun))
+ 	    res = make_ssa_name (type, NULL);
+ 	  else
+ 	    res = create_tmp_reg (type, NULL);
+ 	  gimple_call_set_lhs (stmt, res);
+ 	}
+       gimple_set_location (stmt, loc);
+       gimple_seq_add_stmt_without_update (seq, stmt);
+     }
+   return res;
+ }
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]