On 07/24/2014 11:48 AM, Jakub Jelinek wrote:
> So, either support for just EAF*, or perhaps support for DECL_ATTRIBUTES
> for internal-fns, say by having some tree array where you'd store
what you
> stick into DECL_ATTRIBUTES normally.
I'd prefer to avoid attributes. Would something like this be enough?
(not yet fully tested, just ran asan.exp tests).
-Y
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 4a9d379..aa0caab 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1348,6 +1348,9 @@ gimple_call_fnspec (const_gimple stmt)
int
gimple_call_arg_flags (const_gimple stmt, unsigned arg)
{
+ if (gimple_call_internal_p (stmt))
+ return internal_fn_arg_flags (gimple_call_internal_fn (stmt), arg);
+
tree attr = gimple_call_fnspec (stmt);
if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 7fb54ea..3f9b448 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -40,7 +40,7 @@ along with GCC; see the file COPYING3. If not see
/* The names of each internal function, indexed by function number. */
const char *const internal_fn_name_array[] = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) #CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) #CODE,
#include "internal-fn.def"
#undef DEF_INTERNAL_FN
"<invalid-fn>"
@@ -48,12 +48,63 @@ const char *const internal_fn_name_array[] = {
/* The ECF_* flags of each internal function, indexed by function number. */
const int internal_fn_flags_array[] = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS,
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) FLAGS,
#include "internal-fn.def"
#undef DEF_INTERNAL_FN
0
};
+/* The EAF_* flags for arguments of internal functions,
+ indexed indirectly via INTERNAL_FN_ARG_FLAGS_ARRAY. */
+static GTY(()) int *internal_fn_arg_flags_array;
+
+/* Maps internal function to offset in internal_fn_arg_flags_array. */
+static size_t internal_fn_arg_flags_offsets[IFN_LAST];
+static size_t max_arg_offset;
+
+void
+init_internal_fns ()
+{
+ max_arg_offset = 0;
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) max_arg_offset += NARGS;
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+ internal_fn_arg_flags_array
+ = (int *) xmalloc (max_arg_offset * sizeof (internal_fn_arg_flags_array[0]));
+
+ size_t offset = 0;
+#define APPEND_ARG_FLAGS0() ;
+#define APPEND_ARG_FLAGS1(F1) \
+ internal_fn_arg_flags_array[offset++] = F1;
+#define APPEND_ARG_FLAGS2(F1, F2) \
+ internal_fn_arg_flags_array[offset++] = F1; \
+ internal_fn_arg_flags_array[offset++] = F2;
+#define APPEND_ARG_FLAGS3(F1, F2, F3) \
+ internal_fn_arg_flags_array[offset++] = F1; \
+ internal_fn_arg_flags_array[offset++] = F2; \
+ internal_fn_arg_flags_array[offset++] = F3;
+#define APPEND_ARG_FLAGS4(F1, F2, F3, F4) \
+ internal_fn_arg_flags_array[offset++] = F1; \
+ internal_fn_arg_flags_array[offset++] = F2; \
+ internal_fn_arg_flags_array[offset++] = F3; \
+ internal_fn_arg_flags_array[offset++] = F4;
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) \
+ internal_fn_arg_flags_offsets[(int) IFN_##CODE] = offset; \
+ APPEND_ARG_FLAGS##NARGS ARG_FLAGS
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+}
+
+/* Return the EAF_* flags for N-th argument of function FN. */
+
+int
+internal_fn_arg_flags (enum internal_fn fn, int arg)
+{
+ size_t offset = internal_fn_arg_flags_offsets[(int) fn] + arg;
+ gcc_assert (offset < max_arg_offset);
+ return internal_fn_arg_flags_array[offset];
+}
+
/* ARRAY_TYPE is an array of vector modes. Return the associated insn
for load-lanes-style optab OPTAB. The insn must exist. */
@@ -905,7 +956,7 @@ expand_BUILTIN_EXPECT (gimple stmt)
where STMT is the statement that performs the call. */
static void (*const internal_fn_expanders[]) (gimple) = {
-#define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) expand_##CODE,
#include "internal-fn.def"
#undef DEF_INTERNAL_FN
0
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index f0aa1b4..a2861a6 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -28,30 +28,34 @@ along with GCC; see the file COPYING3. If not see
Each entry in this file has the form:
- DEF_INTERNAL_FN (NAME, FLAGS)
+ DEF_INTERNAL_FN (NAME, FLAGS, NARGS, ARG_FLAGS)
- where NAME is the name of the function and FLAGS is a set of
- ECF_* flags. Each entry must have a corresponding expander
- of the form:
+ where NAME is the name of the function, FLAGS is a set of
+ ECF_* flags and ARG_FLAGS holds comma-separated list of sets
+ of EAF_* flags.
+
+ Each entry must have a corresponding expander of the form:
void expand_NAME (gimple stmt)
where STMT is the statement that performs the call. */
-DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF)
-DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF)
-DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF)
-DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF)
-DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN)
-DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
-DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF, 1, (0))
+DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF, 1, (0))
+DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, 1, (0))
+DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 1, (0))
+DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, \
+ 2, (0, 0))
+DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF, 3, (0, 0, 0))
+DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF, 4, (0, 0, 0, 0))
+DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, 3, (0, 0, 0))
+DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 2, (0, 0))
+DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, 1, (0))
+DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, 1, (0))
+DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW, \
+ 3, (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE, 0, 0))
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
index 2dcf44e..e476aac 100644
--- a/gcc/internal-fn.h
+++ b/gcc/internal-fn.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_INTERNAL_FN_H
#define GCC_INTERNAL_FN_H
+extern void init_internal_fns ();
+
/* Return the name of internal function FN. The name is only meaningful
for dumps; it has no linkage. */
@@ -41,6 +43,8 @@ internal_fn_flags (enum internal_fn fn)
return internal_fn_flags_array[(int) fn];
}
+int internal_fn_arg_flags (enum internal_fn, int);
+
extern void expand_internal_call (gimple);
#endif
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 34c48fa..cc46b81 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -667,7 +667,7 @@ enum annot_expr_kind {
/* Internal functions. */
enum internal_fn {
-#define DEF_INTERNAL_FN(CODE, FLAGS) IFN_##CODE,
+#define DEF_INTERNAL_FN(CODE, FLAGS, NARGS, ARG_FLAGS) IFN_##CODE,
#include "internal-fn.def"
#undef DEF_INTERNAL_FN
IFN_LAST
diff --git a/gcc/tree.c b/gcc/tree.c
index 10063a4..5520b8b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -9920,8 +9920,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code,
}
/* Call this function after instantiating all builtins that the language
- front end cares about. This will build the rest of the builtins that
- are relied upon by the tree optimizers and the middle-end. */
+ front end cares about. This will build the rest of the builtins
+ and internal function that are relied upon by the tree optimizers and
+ the middle-end. */
void
build_common_builtin_nodes (void)
@@ -10154,6 +10155,8 @@ build_common_builtin_nodes (void)
ECF_CONST | ECF_NOTHROW | ECF_LEAF);
}
}
+
+ init_internal_fns ();
}
/* HACK. GROSS. This is absolutely disgusting. I wish there was a