2014-09-23 Christian Bruel <christian.bruel@st.com>
* config/arm/arm.c (add_attribute, arm_insert_attributes): New functions
(TARGET_INSERT_ATTRIBUTES): Define.
(thumb_flipper): New var.
* config/arm/arm.opt (-mflip-thumb): New switch.
@@ -99,6 +99,7 @@
#include "tm-constrs.h"
#include "rtl-iter.h"
#include "sched-int.h"
+#include "tree.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
@@ -232,6 +233,7 @@
static void arm_file_end (void);
static void arm_file_start (void);
+static void arm_insert_attributes (tree, tree *);
static void arm_setup_incoming_varargs (cumulative_args_t, machine_mode,
tree, int *, int);
@@ -390,6 +392,9 @@
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES arm_insert_attributes
+
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START arm_file_start
#undef TARGET_ASM_FILE_END
@@ -2717,6 +2722,10 @@
}
}
+/* True if -mflip-thumb should next add an attribute for the default
+ mode, false if it should next add an attribute for the opposite mode. */
+static GTY(()) bool thumb_flipper;
+
/* Options after initial target override. */
static GTY(()) tree init_optimize;
@@ -2753,7 +2762,7 @@
opts->x_arm_restrict_it = 0;
if (TREE_TARGET_THUMB1 (opts))
- /* Don't warn since it's on by default in -O2. */
+ /* Don't warn since it's on by default in -O2. */
opts->x_flag_schedule_insns = 0;
else
opts->x_flag_schedule_insns = to->x_flag_schedule_insns;
@@ -3282,6 +3291,9 @@
options. */
target_option_default_node = target_option_current_node
= build_target_option_node (&global_options);
+
+ /* Init initial mode for testing. */
+ thumb_flipper = TARGET_THUMB;
}
static void
@@ -29624,6 +29636,52 @@
return build_target_option_node (opts);
}
+static void
+add_attribute (const char * mode, tree *attributes)
+{
+ size_t len = strlen (mode);
+ tree value = build_string (len, mode);
+
+ TREE_TYPE (value) = build_array_type (char_type_node,
+ build_index_type (size_int (len)));
+
+ *attributes = tree_cons (get_identifier ("target"),
+ build_tree_list (NULL_TREE, value),
+ *attributes);
+}
+
+/* For testing. Insert thumb or arm modes alternatively on functions. */
+
+static void
+arm_insert_attributes (tree fndecl, tree * attributes)
+{
+ const char *mode;
+
+ if (! TARGET_FLIP_THUMB)
+ return;
+
+ if (TREE_CODE (fndecl) != FUNCTION_DECL || DECL_EXTERNAL(fndecl)
+ || DECL_BUILT_IN (fndecl) || DECL_ARTIFICIAL (fndecl))
+ return;
+
+ /* Nested definitions must inherit mode. */
+ if (current_function_decl)
+ {
+ mode = TARGET_THUMB ? "thumb" : "arm";
+ add_attribute (mode, attributes);
+ return;
+ }
+
+ /* If there is already a setting don't change it. */
+ if (lookup_attribute ("target", *attributes) != NULL)
+ return;
+
+ mode = thumb_flipper ? "thumb" : "arm";
+ add_attribute (mode, attributes);
+
+ thumb_flipper = !thumb_flipper;
+}
+
/* Hook to validate attribute((target("string"))). */
static bool
@@ -29635,13 +29693,15 @@
tree cur_tree, new_optimize;
gcc_assert ((fndecl != NULL_TREE) && (args != NULL_TREE));
+ tree old_optimize = build_optimization_node (&global_options);
+
/* Get the optimization options of the current function. */
tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
/* If the function changed the optimization levels as well as setting target
options, start with the optimizations specified. */
if (!func_optimize)
- func_optimize = optimization_default_node;
+ func_optimize = old_optimize;
/* Init func_options. */
memset (&func_options, 0, sizeof (func_options));
@@ -29659,14 +29719,17 @@
cur_tree = arm_valid_target_attribute_tree (args, &func_options,
&global_options_set);
- if (cur_tree == NULL_TREE)
- ret = false;
-
new_optimize = build_optimization_node (&func_options);
- DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
+ if (cur_tree == NULL_TREE)
+ ret = false;
+ else
+ {
+ DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = cur_tree;
- DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+ if (old_optimize != new_optimize)
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize;
+ }
return ret;
}
@@ -122,6 +122,10 @@
EnumValue
Enum(float_abi_type) String(hard) Value(ARM_FLOAT_ABI_HARD)
+mflip-thumb
+Target Report Var(TARGET_FLIP_THUMB)
+Switch ARM/Thumb modes on alternating functions for compiler testing
+
mfp16-format=
Target RejectNegative Joined Enum(arm_fp16_format_type) Var(arm_fp16_format) Init(ARM_FP16_FORMAT_NONE)
Specify the __fp16 floating-point format