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]

Re: [C++11][4.9] Add missing REDUC_PLUS_EXPR case to potential_constant_expression_1.


Hi Richard,

Thanks for your feedback. This does feel like a much nicer solution now.

> Yes, it looks basically ok.  I'd probably restrict it to folding target
> builtins
> though - similar to what TARGET_FOLD_BUILTIN did.  Exactly to not
> expose all stmts to the backends.  That is, move the target hook call
> to gimple_fold_call, after the inplace check (and remove the inplace
> argument of the target hook), and call it only for DECL_BUILT_IN_CLASS
> BUILT_IN_MD.

This seems sensible - hopefully something like the attached will be
closer to an acceptable implementation. The aarch64 portion certainly
looks much cleaner now.
 
> Not sure if TARGET_FOLD_STMT is then still an appropriate name ...
> TARGET_FOLD_BUILTIN is already taken unfortunately.  Maybe
> TARGET_FOLD_BUILTIN_MD_CALL?

I've gone for TARGET_GIMPLE_FOLD_BUILTIN (to fit with the
non-target-specific gimple_fold_builtin).

I've also updated the documentation for TARGET_FOLD_BUILTIN to
make it clear that the tree returned must be valid in GENERIC
and GIMPLE.

Thanks again for your help.

James
Graduate Engineer
ARM.

---
gcc/

2013-04-19  James Greenhalgh  <james.greenhalgh@arm.com>

	* coretypes.h (gimple_stmt_iterator_d): Forward declare.
	(gimple_stmt_iterator): New typedef.
	* gimple.h (gimple_stmt_iterator): Rename to...
	(gimple_stmt_iterator_d): ... This.
	* doc/tm.texi.in (TARGET_FOLD_BUILTIN): Detail restriction that
	trees be valid for GIMPLE and GENERIC.
	(TARGET_GIMPLE_FOLD_BUILTIN): New.
	* gimple-fold.c (gimple_fold_call): Call target hook
	gimple_fold_builtin.
	* hooks.c (hook_bool_gsiptr_false): New.
	* hooks.h (hook_bool_gsiptr_false): New.
	* target.def (fold_stmt): New.
	* doc/tm.texi: Regenerate.

2013-04-19  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-builtins.c
	(aarch64_fold_builtin): Move folds to gimple-specific tree codes
	to aarch64_gimple_fold_builtin.
	(aarch64_gimple_fold_builtin): New.
	* config/aarch64/aarch64-protos.h (aarch64_gimple_fold_builtin): New.
	* config/aarch64/aarch64.c (TARGET_GIMPLE_FOLD_BUILTIN): Define.
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 320b4dd..76fc4aa 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -62,6 +62,8 @@ union gimple_statement_d;
 typedef union gimple_statement_d *gimple;
 typedef const union gimple_statement_d *const_gimple;
 typedef gimple gimple_seq;
+struct gimple_stmt_iterator_d;
+typedef gimple_stmt_iterator_d gimple_stmt_iterator;
 union section;
 typedef union section section;
 struct gcc_options;
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 91a756c..908da0b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -10772,10 +10772,13 @@ Fold a call to a machine specific built-in function that was set up by
 @samp{TARGET_INIT_BUILTINS}.  @var{fndecl} is the declaration of the
 built-in function.  @var{n_args} is the number of arguments passed to
 the function; the arguments themselves are pointed to by @var{argp}.
-The result is another tree containing a simplified expression for the
-call's result.  If @var{ignore} is true the value will be ignored.
+The result is another tree, valid for both GIMPLE and GENERIC,
+containing a simplified expression for the call's result.  If
+@var{ignore} is true the value will be ignored.
 @end deftypefn
 
+@hook TARGET_GIMPLE_FOLD_BUILTIN
+
 @hook TARGET_COMPARE_VERSION_PRIORITY
 This hook is used to compare the target attributes in two functions to
 determine which function's features get higher priority.  This is used
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index b9211a9..d1dbf8e 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1145,6 +1145,13 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
 	}
     }
 
+  /* Call target-specific, GIMPLE only fold routines.  */
+  callee = gimple_call_fndecl (stmt);
+  if (!changed
+      && callee
+      && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
+    changed |= targetm.gimple_fold_builtin (gsi);
+
   return changed;
 }
 
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 475d2ea..17ad409 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -130,7 +130,7 @@ enum plf_mask {
 
 /* Iterator object for GIMPLE statement sequences.  */
 
-typedef struct
+struct gimple_stmt_iterator_d
 {
   /* Sequence node holding the current statement.  */
   gimple_seq_node ptr;
@@ -141,8 +141,7 @@ typedef struct
      block/sequence is removed.  */
   gimple_seq *seq;
   basic_block bb;
-} gimple_stmt_iterator;
-
+};
 
 /* Data structure definitions for GIMPLE tuples.  NOTE: word markers
    are for 64 bit hosts.  */
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 3b54dfa..3259658 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -147,6 +147,14 @@ hook_bool_FILEptr_rtx_false (FILE *a ATTRIBUTE_UNUSED,
   return false;
 }
 
+/* Generic hook that takes (gimple_stmt_iterator *) and returns
+   false.  */
+bool
+hook_bool_gsiptr_false (gimple_stmt_iterator *a ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
 /* Used for the TARGET_ASM_CAN_OUTPUT_MI_THUNK hook.  */
 bool
 hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree a ATTRIBUTE_UNUSED,
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 50bcc6a..eaf4b03 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -42,6 +42,7 @@ extern bool hook_bool_tree_false (tree);
 extern bool hook_bool_const_tree_false (const_tree);
 extern bool hook_bool_tree_true (tree);
 extern bool hook_bool_const_tree_true (const_tree);
+extern bool hook_bool_gsiptr_false (gimple_stmt_iterator *);
 extern bool hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree,
 							   HOST_WIDE_INT,
 							   HOST_WIDE_INT,
diff --git a/gcc/target.def b/gcc/target.def
index 3ad5870..46375aa 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1289,13 +1289,25 @@ DEFHOOK
  "",
  tree, (unsigned int /*location_t*/ loc, tree fndecl, void *arglist), NULL)
 
-/* Fold a target-specific builtin.  */
+/* Fold a target-specific builtin to a tree valid for both GIMPLE
+   and GENERIC.  */
 DEFHOOK
 (fold_builtin,
  "",
  tree, (tree fndecl, int n_args, tree *argp, bool ignore),
  hook_tree_tree_int_treep_bool_null)
 
+/* Fold a target-specific builtin to a valid GIMPLE tree.  */
+DEFHOOK
+(gimple_fold_builtin,
+ "Like @samp{TARGET_FOLD_BUILTIN}, but without the restriction that\n\
+the result tree be valid for GENERIC.  Fold a call to a machine specific\n\
+built-in function that was set up by @samp{TARGET_INIT_BUILTINS}.\n\
+@var{gsi} points to the gimple statement holding the function call.\n\
+Returns true if any change was made to the GIMPLE stream.",
+ bool, (gimple_stmt_iterator *gsi),
+ hook_bool_gsiptr_false)
+
 /* Target hook is used to compare the target attributes in two functions to
    determine which function's features get higher priority.  This is used
    during function multi-versioning to figure out the order in which two
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 8361632..7a65d59 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -30,6 +30,9 @@
 #include "langhooks.h"
 #include "diagnostic-core.h"
 #include "optabs.h"
+#include "gimple.h"
+#include "tree-ssa-propagate.h"
+#include "gimple-fold.h"
 
 enum aarch64_simd_builtin_type_mode
 {
@@ -1310,21 +1313,11 @@ aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
 {
   int fcode = DECL_FUNCTION_CODE (fndecl);
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
-
   switch (fcode)
     {
-      BUILTIN_VALL (UNOP, reduc_splus_, 10)
-	return fold_build1 (REDUC_PLUS_EXPR, type, args[0]);
-	break;
-      BUILTIN_VDQIF (UNOP, reduc_smax_, 10)
-	return fold_build1 (REDUC_MAX_EXPR, type, args[0]);
-	break;
-      BUILTIN_VDQIF (UNOP, reduc_smin_, 10)
-	return fold_build1 (REDUC_MIN_EXPR, type, args[0]);
-	break;
       BUILTIN_VDQF (UNOP, abs, 2)
 	return fold_build1 (ABS_EXPR, type, args[0]);
-	break;
+      break;
       BUILTIN_VDQF (BINOP, cmge, 0)
       BUILTIN_VDQF (BINOP, cmgt, 0)
       BUILTIN_VDQF (BINOP, cmeq, 0)
@@ -1340,15 +1333,15 @@ aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
 	    {
 	      BUILTIN_VDQF (BINOP, cmge, 0)
 		cmp = fold_build2 (GE_EXPR, type, args[0], args[1]);
-		break;
+	      break;
 	      BUILTIN_VDQF (BINOP, cmgt, 0)
 		cmp = fold_build2 (GT_EXPR, type, args[0], args[1]);
-		break;
+	      break;
 	      BUILTIN_VDQF (BINOP, cmeq, 0)
 		cmp = fold_build2 (EQ_EXPR, type, args[0], args[1]);
-		break;
-	      default:
-		gcc_unreachable ();
+	      break;
+	    default:
+	      gcc_unreachable ();
 	    }
 	  return fold_build3 (VEC_COND_EXPR, type, cmp, vect_true, vect_false);
 	  break;
@@ -1357,14 +1350,70 @@ aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
       VAR1 (UNOP, floatv4si, 2, v4sf)
       VAR1 (UNOP, floatv2di, 2, v2df)
 	return fold_build1 (FLOAT_EXPR, type, args[0]);
-	break;
-      default:
-	break;
+      break;
+    default:
+      break;
     }
 
   return NULL_TREE;
 }
 
+bool
+aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+  bool changed = false;
+  gimple stmt = gsi_stmt (*gsi);
+  tree call = gimple_call_fn (stmt);
+  tree fndecl;
+  gimple new_stmt = NULL;
+  if (call)
+    {
+      fndecl = gimple_call_fndecl (stmt);
+      if (fndecl)
+	{
+	  int fcode = DECL_FUNCTION_CODE (fndecl);
+	  int nargs = gimple_call_num_args (stmt);
+	  tree *args = (nargs > 0
+			? gimple_call_arg_ptr (stmt, 0)
+			: &error_mark_node);
+
+	  switch (fcode)
+	    {
+	      BUILTIN_VALL (UNOP, reduc_splus_, 10)
+		new_stmt = gimple_build_assign_with_ops (
+						REDUC_PLUS_EXPR,
+						gimple_call_lhs (stmt),
+						args[0],
+						NULL_TREE);
+		break;
+	      BUILTIN_VDQIF (UNOP, reduc_smax_, 10)
+		new_stmt = gimple_build_assign_with_ops (
+						REDUC_MAX_EXPR,
+						gimple_call_lhs (stmt),
+						args[0],
+						NULL_TREE);
+		break;
+	      BUILTIN_VDQIF (UNOP, reduc_smin_, 10)
+		new_stmt = gimple_build_assign_with_ops (
+						REDUC_MIN_EXPR,
+						gimple_call_lhs (stmt),
+						args[0],
+						NULL_TREE);
+		break;
+	    default:
+	      break;
+	    }
+	}
+    }
+
+  if (new_stmt)
+    {
+      gsi_replace (gsi, new_stmt, true);
+      changed = true;
+    }
+  return changed;
+}
+
 #undef AARCH64_CHECK_BUILTIN_MODE
 #undef AARCH64_FIND_FRINT_VARIANT
 #undef BUILTIN_DX
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 2400239..4a53f32 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -179,6 +179,7 @@ bool aarch64_simd_mem_operand_p (rtx);
 rtx aarch64_simd_vect_par_cnst_half (enum machine_mode, bool);
 rtx aarch64_tls_get_addr (void);
 tree aarch64_fold_builtin (tree, int, tree *, bool);
+bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
 unsigned aarch64_dbx_register_number (unsigned);
 unsigned aarch64_trampoline_size (void);
 void aarch64_asm_output_labelref (FILE *, const char *);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index d3b349f..b9535bf 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -7859,6 +7859,9 @@ aarch64_vectorize_vec_perm_const_ok (enum machine_mode vmode,
 #undef TARGET_FOLD_BUILTIN
 #define TARGET_FOLD_BUILTIN aarch64_fold_builtin
 
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
+
 #undef TARGET_FUNCTION_ARG
 #define TARGET_FUNCTION_ARG aarch64_function_arg
 

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