aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <dje.gcc@gmail.com>2014-01-11 18:57:56 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>2014-01-11 13:57:56 -0500
commitc82846bc44d259ea1702410f916ff3c0aa019f7b (patch)
treea5436871a1c494bc86f3e27e8561dc3c69eeb824
parent2558e2e838790ef1441788c0ba4c14e1bf061b55 (diff)
downloadgcc-c82846bc44d259ea1702410f916ff3c0aa019f7b.zip
gcc-c82846bc44d259ea1702410f916ff3c0aa019f7b.tar.gz
gcc-c82846bc44d259ea1702410f916ff3c0aa019f7b.tar.bz2
re PR target/58115 (testcase gcc.target/i386/intrinsics_4.c failure)
PR target/58115 * config/rs6000/rs6000.h (SWITCHABLE_TARGET): Define. * config/rs6000/rs6000.c: Include target-globals.h. (rs6000_set_current_function): Instead of doing target_reinit unconditionally, use save_target_globals_default_opts and restore_target_globals. * config/rs6000/rs6000-builtin.def (mffs, mtfsf): Add builtins for FPSCR. * config/rs6000/rs6000.c (rs6000_expand_mtfsf_builtin): New. (rs6000_expand_builtin): Handle mffs and mtfsf. (rs6000_init_builtins): Define mffs and mtfsf. * config/rs6000/rs6000.md (UNSPECV_MFFS, UNSPECV_MTFSF): New. (rs6000_mffs): New pattern. (rs6000_mtfsf): New pattern. From-SVN: r206554
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def8
-rw-r--r--gcc/config/rs6000/rs6000.c78
-rw-r--r--gcc/config/rs6000/rs6000.h3
-rw-r--r--gcc/config/rs6000/rs6000.md16
5 files changed, 117 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a66a01d..7b38804 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2014-01-11 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/58115
+ * config/rs6000/rs6000.h (SWITCHABLE_TARGET): Define.
+ * config/rs6000/rs6000.c: Include target-globals.h.
+ (rs6000_set_current_function): Instead of doing target_reinit
+ unconditionally, use save_target_globals_default_opts and
+ restore_target_globals.
+
+ * config/rs6000/rs6000-builtin.def (mffs, mtfsf): Add builtins for
+ FPSCR.
+ * config/rs6000/rs6000.c (rs6000_expand_mtfsf_builtin): New.
+ (rs6000_expand_builtin): Handle mffs and mtfsf.
+ (rs6000_init_builtins): Define mffs and mtfsf.
+ * config/rs6000/rs6000.md (UNSPECV_MFFS, UNSPECV_MTFSF): New constants.
+ (rs6000_mffs): New pattern.
+ (rs6000_mtfsf): New pattern.
+
2014-01-11 Bin Cheng <bin.cheng@arm.com>
* tree-ssa-loop-ivopts.c (iv_ca_narrow): New parameter.
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 4d25bfd..b7b67fa 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -1752,6 +1752,14 @@ BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase",
BU_SPECIAL_X (RS6000_BUILTIN_MFTB, "__builtin_ppc_mftb",
RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+BU_SPECIAL_X (RS6000_BUILTIN_MFFS, "__builtin_mffs",
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+
+RS6000_BUILTIN_X (RS6000_BUILTIN_MTFSF, "__builtin_mtfsf",
+ RS6000_BTM_ALWAYS,
+ RS6000_BTC_MISC | RS6000_BTC_UNARY | RS6000_BTC_VOID,
+ CODE_FOR_rs6000_mtfsf)
+
/* Darwin CfString builtin. */
BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
RS6000_BTC_MISC)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 500acb7..e4daa78 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -78,6 +78,7 @@
#include "tree-vectorizer.h"
#include "dumpfile.h"
#include "cgraph.h"
+#include "target-globals.h"
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
@@ -11469,6 +11470,48 @@ rs6000_expand_zeroop_builtin (enum insn_code icode, rtx target)
static rtx
+rs6000_expand_mtfsf_builtin (enum insn_code icode, tree exp, rtx target)
+{
+ rtx pat;
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ tree arg1 = CALL_EXPR_ARG (exp, 1);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ enum machine_mode mode0 = insn_data[icode].operand[0].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[1].mode;
+
+ if (icode == CODE_FOR_nothing)
+ /* Builtin not supported on this processor. */
+ return 0;
+
+ /* If we got invalid arguments bail out before generating bad rtl. */
+ if (arg0 == error_mark_node || arg1 == error_mark_node)
+ return const0_rtx;
+
+ if (GET_CODE (op0) != CONST_INT
+ || INTVAL (op0) > 255
+ || INTVAL (op0) < 0)
+ {
+ error ("argument 1 must be an 8-bit field value");
+ return const0_rtx;
+ }
+
+ if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ op0 = copy_to_mode_reg (mode0, op0);
+
+ if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ op1 = copy_to_mode_reg (mode1, op1);
+
+ pat = GEN_FCN (icode) (op0, op1);
+ if (! pat)
+ return const0_rtx;
+ emit_insn (pat);
+
+ return NULL_RTX;
+}
+
+
+static rtx
rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target)
{
rtx pat;
@@ -13277,6 +13320,12 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
: CODE_FOR_rs6000_mftb_si),
target);
+ case RS6000_BUILTIN_MFFS:
+ return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffs, target);
+
+ case RS6000_BUILTIN_MTFSF:
+ return rs6000_expand_mtfsf_builtin (CODE_FOR_rs6000_mtfsf, exp, target);
+
case ALTIVEC_BUILTIN_MASK_FOR_LOAD:
case ALTIVEC_BUILTIN_MASK_FOR_STORE:
{
@@ -13584,6 +13633,14 @@ rs6000_init_builtins (void)
NULL_TREE);
def_builtin ("__builtin_ppc_mftb", ftype, RS6000_BUILTIN_MFTB);
+ ftype = build_function_type_list (double_type_node, NULL_TREE);
+ def_builtin ("__builtin_mffs", ftype, RS6000_BUILTIN_MFFS);
+
+ ftype = build_function_type_list (void_type_node,
+ intSI_type_node, double_type_node,
+ NULL_TREE);
+ def_builtin ("__builtin_mtfsf", ftype, RS6000_BUILTIN_MTFSF);
+
#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
@@ -31199,16 +31256,25 @@ rs6000_set_current_function (tree fndecl)
{
cl_target_option_restore (&global_options,
TREE_TARGET_OPTION (new_tree));
- target_reinit ();
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else
+ TREE_TARGET_GLOBALS (new_tree)
+ = save_target_globals_default_opts ();
}
else if (old_tree)
{
- struct cl_target_option *def
- = TREE_TARGET_OPTION (target_option_current_node);
-
- cl_target_option_restore (&global_options, def);
- target_reinit ();
+ new_tree = target_option_current_node;
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (new_tree));
+ if (TREE_TARGET_GLOBALS (new_tree))
+ restore_target_globals (TREE_TARGET_GLOBALS (new_tree));
+ else if (new_tree == target_option_default_node)
+ restore_target_globals (&default_target_globals);
+ else
+ TREE_TARGET_GLOBALS (new_tree)
+ = save_target_globals_default_opts ();
}
}
}
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index fdbe965..1a37a5d 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2446,6 +2446,9 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+/* For switching between functions with different target attributes. */
+#define SWITCHABLE_TARGET 1
+
/* uncomment for disabling the corresponding default options */
/* #define MACHINE_no_sched_interblock */
/* #define MACHINE_no_sched_speculative */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index f9f988b..744a11d 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -140,6 +140,8 @@
UNSPECV_ISYNC ; isync instruction
UNSPECV_MFTB ; move from time base
UNSPECV_NLGR ; non-local goto receiver
+ UNSPECV_MFFS ; Move from FPSCR
+ UNSPECV_MTFSF ; Move to FPSCR Fields
])
@@ -15587,6 +15589,20 @@
})
+(define_insn "rs6000_mffs"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
+ (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFS))]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "mffs %0")
+
+(define_insn "rs6000_mtfsf"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")
+ (match_operand:DF 1 "gpc_reg_operand" "d")]
+ UNSPECV_MTFSF)]
+ "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "mtfsf %0,%1")
+
+
;; Power8 fusion support for fusing an addis instruction with a D-form load of
;; a GPR. The addis instruction must be adjacent to the load, and use the same
;; register that is being loaded. The fused ops must be physically adjacent.