gimple.h (remove_pointer): New trait.
authorRichard Biener <rguenther@suse.de>
Wed, 12 Aug 2015 07:42:31 +0000 (07:42 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 12 Aug 2015 07:42:31 +0000 (07:42 +0000)
2015-08-12  Richard Biener  <rguenther@suse.de>

* gimple.h (remove_pointer): New trait.
(GIMPLE_CHECK2): New inline template function.
(gassign::code_): New constant static member.
(is_a_helper<const gassign *>): Add.
(gimple_assign_lhs): Use GIMPLE_CHECK2 in the gimple overload
and forward to a new gassign overload with less checking and a
cheaper way to access the operand.
(gimple_assign_lhs_ptr): Likewise.
(gimple_assign_set_lhs): Likewise.
(gimple_assign_rhs1, gimple_assign_rhs1_ptr, gimple_assign_set_rhs1):
Likewise.
(gimple_assign_rhs2, gimple_assign_rhs2_ptr, gimple_assign_set_rhs2):
Likewise.
(gimple_assign_rhs3, gimple_assign_rhs3_ptr, gimple_assign_set_rhs3):
Likewise.
(gimple_assign_rhs_code): Likewise.
* gimple.c (gassign::code_): Define.

From-SVN: r226802

gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h

index 206dc3aa44df0d7890a41af26aefd71d17694f7c..62b38279ab09a0260494c4a30d34d0f36c2c4aee 100644 (file)
@@ -1,3 +1,23 @@
+2015-08-12  Richard Biener  <rguenther@suse.de>
+
+       * gimple.h (remove_pointer): New trait.
+       (GIMPLE_CHECK2): New inline template function.
+       (gassign::code_): New constant static member.
+       (is_a_helper<const gassign *>): Add.
+       (gimple_assign_lhs): Use GIMPLE_CHECK2 in the gimple overload
+       and forward to a new gassign overload with less checking and a
+       cheaper way to access the operand.
+       (gimple_assign_lhs_ptr): Likewise.
+       (gimple_assign_set_lhs): Likewise.
+       (gimple_assign_rhs1, gimple_assign_rhs1_ptr, gimple_assign_set_rhs1):
+       Likewise.
+       (gimple_assign_rhs2, gimple_assign_rhs2_ptr, gimple_assign_set_rhs2):
+       Likewise.
+       (gimple_assign_rhs3, gimple_assign_rhs3_ptr, gimple_assign_set_rhs3):
+       Likewise.
+       (gimple_assign_rhs_code): Likewise.
+       * gimple.c (gassign::code_): Define.
+
 2015-08-12  Richard Biener  <rguenther@suse.de>
 
        * tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
index e31a273172792bd0ac1071b24baf491b0c56e033..e4866ac5803d22c6d0f785b7f14e0ac941a53732 100644 (file)
@@ -89,6 +89,10 @@ static const char * const gimple_alloc_kind_names[] = {
     "everything else"
 };
 
+/* Static gimple tuple members.  */
+const enum gimple_code gassign::code_;
+
+
 /* Gimple tuple constructors.
    Note: Any constructor taking a ``gimple_seq'' as a parameter, can
    be passed a NULL to start with an empty sequence.  */
index 200418803af527d20aadd78e9b73236a2c1ea1be..9e9be4ac62d17ab5f58cd1d6eafcbeeedf042236 100644 (file)
@@ -37,6 +37,10 @@ enum gimple_code {
 extern const char *const gimple_code_name[];
 extern const unsigned char gimple_rhs_class_table[];
 
+/* Strip the outermost pointer, from tr1/type_traits.  */
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T *> { typedef T type; };
+
 /* Error out if a gimple tuple is addressed incorrectly.  */
 #if defined ENABLE_GIMPLE_CHECKING
 #define gcc_gimple_checking_assert(EXPR) gcc_assert (EXPR)
@@ -51,9 +55,59 @@ extern void gimple_check_failed (const_gimple, const char *, int,          \
       gimple_check_failed (__gs, __FILE__, __LINE__, __FUNCTION__,     \
                           (CODE), ERROR_MARK);                         \
   } while (0)
+template <typename T>
+static inline T
+GIMPLE_CHECK2(const_gimple gs,
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+             const char *file = __builtin_FILE (),
+             int line = __builtin_LINE (),
+             const char *fun = __builtin_FUNCTION ())
+#else
+             const char *file = __FILE__,
+             int line = __LINE__,
+             const char *fun = NULL)
+#endif
+{
+  T ret = dyn_cast <T> (gs);
+  if (!ret)
+    gimple_check_failed (gs, file, line, fun,
+                        remove_pointer<T>::type::code_, ERROR_MARK);
+  return ret;
+}
+template <typename T>
+static inline T
+GIMPLE_CHECK2(gimple gs,
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+             const char *file = __builtin_FILE (),
+             int line = __builtin_LINE (),
+             const char *fun = __builtin_FUNCTION ())
+#else
+             const char *file = __FILE__,
+             int line = __LINE__,
+             const char *fun = NULL)
+#endif
+{
+  T ret = dyn_cast <T> (gs);
+  if (!ret)
+    gimple_check_failed (gs, file, line, fun,
+                        remove_pointer<T>::type::code_, ERROR_MARK);
+  return ret;
+}
 #else  /* not ENABLE_GIMPLE_CHECKING  */
 #define gcc_gimple_checking_assert(EXPR) ((void)(0 && (EXPR)))
 #define GIMPLE_CHECK(GS, CODE)                 (void)0
+template <typename T>
+static inline T
+GIMPLE_CHECK2(gimple gs)
+{
+  return as_a <T> (gs);
+}
+template <typename T>
+static inline T
+GIMPLE_CHECK2(const_gimple gs)
+{
+  return as_a <T> (gs);
+}
 #endif
 
 /* Class of GIMPLE expressions suitable for the RHS of assignments.  See
@@ -832,6 +886,7 @@ struct GTY((tag("GSS_WITH_OPS")))
 struct GTY((tag("GSS_WITH_MEM_OPS")))
   gassign : public gimple_statement_with_memory_ops
 {
+  static const enum gimple_code code_ = GIMPLE_ASSIGN;
   /* no additional fields; this uses the layout for GSS_WITH_MEM_OPS. */
 };
 
@@ -861,6 +916,14 @@ is_a_helper <gassign *>::test (gimple gs)
   return gs->code == GIMPLE_ASSIGN;
 }
 
+template <>
+template <>
+inline bool
+is_a_helper <const gassign *>::test (const_gimple gs)
+{
+  return gs->code == GIMPLE_ASSIGN;
+}
+
 template <>
 template <>
 inline bool
@@ -2325,65 +2388,100 @@ get_gimple_rhs_class (enum tree_code code)
 
 /* Return the LHS of assignment statement GS.  */
 
+static inline tree
+gimple_assign_lhs (const gassign *gs)
+{
+  return gs->op[0];
+}
+
 static inline tree
 gimple_assign_lhs (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op (gs, 0);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_lhs (ass);
 }
 
 
 /* Return a pointer to the LHS of assignment statement GS.  */
 
+static inline tree *
+gimple_assign_lhs_ptr (const gassign *gs)
+{
+  return const_cast<tree *> (&gs->op[0]);
+}
+
 static inline tree *
 gimple_assign_lhs_ptr (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op_ptr (gs, 0);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_lhs_ptr (ass);
 }
 
 
 /* Set LHS to be the LHS operand of assignment statement GS.  */
 
 static inline void
-gimple_assign_set_lhs (gimple gs, tree lhs)
+gimple_assign_set_lhs (gassign *gs, tree lhs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  gimple_set_op (gs, 0, lhs);
+  gs->op[0] = lhs;
 
   if (lhs && TREE_CODE (lhs) == SSA_NAME)
     SSA_NAME_DEF_STMT (lhs) = gs;
 }
 
+static inline void
+gimple_assign_set_lhs (gimple gs, tree lhs)
+{
+  gassign *ass = GIMPLE_CHECK2<gassign *> (gs);
+  gimple_assign_set_lhs (ass, lhs);
+}
+
 
 /* Return the first operand on the RHS of assignment statement GS.  */
 
+static inline tree
+gimple_assign_rhs1 (const gassign *gs)
+{
+  return gs->op[1];
+}
+
 static inline tree
 gimple_assign_rhs1 (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op (gs, 1);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs1 (ass);
 }
 
 
 /* Return a pointer to the first operand on the RHS of assignment
    statement GS.  */
 
+static inline tree *
+gimple_assign_rhs1_ptr (const gassign *gs)
+{
+  return const_cast<tree *> (&gs->op[1]);
+}
+
 static inline tree *
 gimple_assign_rhs1_ptr (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op_ptr (gs, 1);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs1_ptr (ass);
 }
 
 /* Set RHS to be the first operand on the RHS of assignment statement GS.  */
 
 static inline void
-gimple_assign_set_rhs1 (gimple gs, tree rhs)
+gimple_assign_set_rhs1 (gassign *gs, tree rhs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
+  gs->op[1] = rhs;
+}
 
-  gimple_set_op (gs, 1, rhs);
+static inline void
+gimple_assign_set_rhs1 (gimple gs, tree rhs)
+{
+  gassign *ass = GIMPLE_CHECK2<gassign *> (gs);
+  gimple_assign_set_rhs1 (ass, rhs);
 }
 
 
@@ -2391,73 +2489,104 @@ gimple_assign_set_rhs1 (gimple gs, tree rhs)
    If GS does not have two operands, NULL is returned instead.  */
 
 static inline tree
-gimple_assign_rhs2 (const_gimple gs)
+gimple_assign_rhs2 (const gassign *gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-
   if (gimple_num_ops (gs) >= 3)
-    return gimple_op (gs, 2);
+    return gs->op[2];
   else
     return NULL_TREE;
 }
 
+static inline tree
+gimple_assign_rhs2 (const_gimple gs)
+{
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs2 (ass);
+}
+
 
 /* Return a pointer to the second operand on the RHS of assignment
    statement GS.  */
 
+static inline tree *
+gimple_assign_rhs2_ptr (const gassign *gs)
+{
+  gcc_gimple_checking_assert (gimple_num_ops (gs) >= 3);
+  return const_cast<tree *> (&gs->op[2]);
+}
+
 static inline tree *
 gimple_assign_rhs2_ptr (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op_ptr (gs, 2);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs2_ptr (ass);
 }
 
 
 /* Set RHS to be the second operand on the RHS of assignment statement GS.  */
 
 static inline void
-gimple_assign_set_rhs2 (gimple gs, tree rhs)
+gimple_assign_set_rhs2 (gassign *gs, tree rhs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
+  gcc_gimple_checking_assert (gimple_num_ops (gs) >= 3);
+  gs->op[2] = rhs;
+}
 
-  gimple_set_op (gs, 2, rhs);
+static inline void
+gimple_assign_set_rhs2 (gimple gs, tree rhs)
+{
+  gassign *ass = GIMPLE_CHECK2<gassign *> (gs);
+  return gimple_assign_set_rhs2 (ass, rhs);
 }
 
 /* Return the third operand on the RHS of assignment statement GS.
    If GS does not have two operands, NULL is returned instead.  */
 
 static inline tree
-gimple_assign_rhs3 (const_gimple gs)
+gimple_assign_rhs3 (const gassign *gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-
   if (gimple_num_ops (gs) >= 4)
-    return gimple_op (gs, 3);
+    return gs->op[3];
   else
     return NULL_TREE;
 }
 
+static inline tree
+gimple_assign_rhs3 (const_gimple gs)
+{
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs3 (ass);
+}
+
 /* Return a pointer to the third operand on the RHS of assignment
    statement GS.  */
 
 static inline tree *
 gimple_assign_rhs3_ptr (const_gimple gs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-  return gimple_op_ptr (gs, 3);
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  gcc_gimple_checking_assert (gimple_num_ops (gs) >= 4);
+  return const_cast<tree *> (&ass->op[3]);
 }
 
 
 /* Set RHS to be the third operand on the RHS of assignment statement GS.  */
 
 static inline void
-gimple_assign_set_rhs3 (gimple gs, tree rhs)
+gimple_assign_set_rhs3 (gassign *gs, tree rhs)
 {
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
+  gcc_gimple_checking_assert (gimple_num_ops (gs) >= 4);
+  gs->op[3] = rhs;
+}
 
-  gimple_set_op (gs, 3, rhs);
+static inline void
+gimple_assign_set_rhs3 (gimple gs, tree rhs)
+{
+  gassign *ass = GIMPLE_CHECK2<gassign *> (gs);
+  gimple_assign_set_rhs3 (ass, rhs);
 }
 
+
 /* A wrapper around 3 operand gimple_assign_set_rhs_with_ops, for callers
    which expect to see only two operands.  */
 
@@ -2501,21 +2630,25 @@ gimple_assign_set_nontemporal_move (gimple gs, bool nontemporal)
    tree code of the object.  */
 
 static inline enum tree_code
-gimple_assign_rhs_code (const_gimple gs)
+gimple_assign_rhs_code (const gassign *gs)
 {
-  enum tree_code code;
-  GIMPLE_CHECK (gs, GIMPLE_ASSIGN);
-
-  code = (enum tree_code) gs->subcode;
+  enum tree_code code = (enum tree_code) gs->subcode;
   /* While we initially set subcode to the TREE_CODE of the rhs for
      GIMPLE_SINGLE_RHS assigns we do not update that subcode to stay
      in sync when we rewrite stmts into SSA form or do SSA propagations.  */
   if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
-    code = TREE_CODE (gimple_assign_rhs1 (gs));
+    code = TREE_CODE (gs->op[1]);
 
   return code;
 }
 
+static inline enum tree_code
+gimple_assign_rhs_code (const_gimple gs)
+{
+  const gassign *ass = GIMPLE_CHECK2<const gassign *> (gs);
+  return gimple_assign_rhs_code (ass);
+}
+
 
 /* Set CODE to be the code for the expression computed on the RHS of
    assignment S.  */