+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.
#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
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;
: 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:
{
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)
{
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 ();
}
}
}
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
])
\f
})
\f
+(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")
+
+\f
;; 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.