re PR target/58115 (testcase gcc.target/i386/intrinsics_4.c failure)
authorDavid Edelsohn <dje.gcc@gmail.com>
Sat, 11 Jan 2014 18:57:56 +0000 (18:57 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Sat, 11 Jan 2014 18:57:56 +0000 (13:57 -0500)
        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

gcc/ChangeLog
gcc/config/rs6000/rs6000-builtin.def
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index a66a01d..7b38804 100644 (file)
@@ -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.
index 4d25bfd..b7b67fa 100644 (file)
@@ -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)
index 500acb7..e4daa78 100644 (file)
@@ -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 ();
        }
     }
 }
index fdbe965..1a37a5d 100644 (file)
@@ -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 */
index f9f988b..744a11d 100644 (file)
    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.