Patchwork Rs6000 infrastructure cleanup (switches), revised patch #3

login
register
mail settings
Submitter Michael Meissner
Date Oct. 5, 2012, 6:47 p.m.
Message ID <20121005184737.GC29369@ibm-tiger.the-meissners.org>
Download mbox | patch
Permalink /patch/189565/
State New
Headers show

Comments

Michael Meissner - Oct. 5, 2012, 6:47 p.m.
I've rewritten my rs6000 infrastructure patch to allow more target switches, so
that it does not change the flags currently in the target_flags.  This should
reduce the number of changes due to TARGET_<xxx> being called OPTION_<xxx>, and
MASK_<xxx> being called OPTION_MASK_<xxx>.  In addition, since it might be
possible to build a powerpc 32-bit compiler on a 32-bit system without long
long support, I don't use HOST_WIDE_INT any more to get 64-bit ints, but
instead just use plain ints.

Instead it adds a second flags word that the cpu definitions in rs6000-cpus.def
can set.  I moved the -mavoid-indexed-addresses processing into this second
word, and had the power6 cpu definition set this second word to make sure that
the logic works correctly.  I also moved the -mpaired support into this frame
work.

I also have expanded the debug information that -mdebug=reg prints out to print
all of the flags switches.

Finally, in doing the builds, I noticed some signed vs. unsigned warnings in
the *builtin_expand functions that were caused by comparing an enum to an
unsigned integer, and I fixed these as well.

I have checked this by doing bootstrap builds and there were no regressions in
the test suite.  In addition, I built a linuxpaired compiler, and verified that
the defaults and -mpaired support are exactly the same.  Are these patches ok
to check in?

2012-10-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* common/config/rs6000/rs6000-common.c (rs6000_handle_option):
	Give an error for -mpaired if the compiler is not configured for
	paired support.

	* config/rs6000/rs6000.opt (rs6000_flags2): Add second target
	flags word, and move some options to use this new flag word.
	Save/restore the second flag word.  Add support for initializing
	the second flags word for -mcpu=<xxx> selection.  Print all of the
	options set if -mdebug=reg. Change mapping of RS6000_BTM_* not to
	use target flags masks.  Fix unsigned/signed warnings.  Add more
	specific warnings for trying to use builtins with the wrong cpu.
	(x_rs6000_flags2): Likewise.
	(x_rs6000_flags2_explicit): Likewise.
	(-mfriz): Likewise.
	(-mavoid-indexed-addresses): Likewise.
	(-mpaired): Likewise.
	(-mlongcall): Likewise.
	* config/rs6000/rs6000-c.c (rs6000_pragma_longcall): Likewise.
	(rs6000_define_or_undefine_macro): Likewise.
	(rs6000_target_modify_macros): Likewise.
	* config/rs6000/rs6000.c (rs6000_target_modify_macros_ptr):
	Likewise.
	(POWERPC_MASKS2): Likewise.
	(struct rs6000_ptt): Likewise.
	(RS6000_CPU): Likewise.
	(RS6000_CPU2): Likewise.
	(DEBUG_FMT_X): Likewise.
	(DEBUG_FMT_S2): Likewise.
	(rs6000_debug_reg_global): Likewise.
	(darwin_rs6000_override_options): Likewise.
	(rs6000_builtin_mask_calculate): Likewise.
	(rs6000_option_override_internal): Likewise.
	(init_cumulative_args): Likewise.
	(altivec_expand_ld_builtin): Likewise.
	(altivec_expand_st_builtin): Likewise.
	(altivec_expand_dst_builtin): Likewise.
	(paired_expand_builtin): Likewise.
	(spe_expand_builtin): Likewise.
	(rs6000_invalid_builtin): Likewise.
	(rs6000_handle_longcall_attribute): Likewise.
	(rs6000_set_default_type_attributes): Likewise.
	(rs6000_opt_masks2): Likewise.
	(rs6000_builtin_mask_names): Likewise.
	(rs6000_opt_var): Likewise.
	(rs6000_opt_var2): Likewise.
	(rs6000_find_target_option): Likewise.
	(rs6000_inner_target_options): Likewise.
	(rs6000_pragma_target_parse): Likewise.
	(rs6000_print_flags_internal): Likewise.
	(rs6000_print_target_flags): Likewise.
	(rs6000_print_rs6000_flags2): Likewise.
	(rs6000_print_builtin_types): Likewise.
	(rs6000_function_specific_save): Likewise.
	(rs6000_function_specific_restore): Likewise.
	(rs6000_function_specific_print): Likewise.
	* config/rs6000/750cl.h (TARGET_PAIRED_FLOAT): Likewise.
	(HAVE_PAIRED_FLOAT): Likewise.
	* config/rs6000/rs6000.h (TARGET_PAIRED_FLOAT): Likewise.
	(TARGET_DEFAULT_FLAGS2): Likewise.
	(TARGET_FRIZ): Likewise.
	(TARGET_AVOID_XFORM): Likewise.
	(TARGET_LONG_CALLS): Likewise.
	(TARGET_PAIRED_FLOAT): Likewise.
	(RS6000_BTM_ALWAYS): Likewise.
	(RS6000_BTM_ALTIVEC): Likewise.
	(RS6000_BTM_VSX): Likewise.
	(RS6000_BTM_SPE): Likewise.
	(RS6000_BTM_PAIRED): Likewise.
	(RS6000_BTM_GFXOPT): Likewise.
	(RS6000_BTM_CELL): Likewise.
	(RS6000_BTM_POPCNTB): Likewise.
	(RS6000_BTM_FPRND): Likewise.
	(RS6000_BTM_POPCNTD): Likewise.
	(RS6000_BTM_FRE): Likewise.
	(RS6000_BTM_FRES): Likewise.
	(RS6000_BTM_FRSQRTE): Likewise.
	(RS6000_BTM_FRSQRTES): Likewise.
	(RS6000_BTM_COMMON): Likewise.
	* config/rs6000/rs6000-cpus.def (power6 cpu): Likewise.
	(power6x cpu): Likewise.
	* config/rs6000/rs6000-protos.h (rs6000_target_modify_macros):
	Likewise.
	(rs6000_target_modify_macros_ptr): Likewise.
Gunther Nikl - Oct. 6, 2012, 7:47 p.m.
Michael Meissner wrote:
> @@ -10326,7 +10352,7 @@ static rtx
>  altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
>  {
>    tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
> -  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
> +  enum rs6000_builtins fcode = (enum rs6000_builtins)
DECL_FUNCTION_CODE (fndecl);
>    tree arg0;
>    enum machine_mode tmode, mode0;
>    rtx pat, op0;

There are several changes like that in your patch. Shouldn't these
changes be done in a separate patch?

Regards,
Gunther

Patch

Index: gcc/common/config/rs6000/rs6000-common.c
===================================================================
--- gcc/common/config/rs6000/rs6000-common.c	(revision 192041)
+++ gcc/common/config/rs6000/rs6000-common.c	(working copy)
@@ -281,6 +281,12 @@  rs6000_handle_option (struct gcc_options
     case OPT_mrecip:
       opts->x_rs6000_recip_name = (value) ? "default" : "none";
       break;
+
+#if !HAVE_PAIRED_FLOAT
+    case OPT_mpaired:
+      error_at (loc, "this compiler does not support -mpaired");
+      break;
+#endif
     }
   return true;
 }
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 192041)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -90,6 +90,17 @@  unsigned int rs6000_debug
 TargetSave
 int rs6000_target_flags_explicit
 
+;; Secondary flags word.  We have run out of bits in target_flags, so push
+;; newer flag bits into rs6000_flags2 and rs6000_flags2_explicit
+Variable
+int rs6000_flags2 = TARGET_DEFAULT_FLAGS2
+
+TargetSave
+int x_rs6000_flags2
+
+TargetSave
+int x_rs6000_flags2_explicit
+
 ;; This option existed in the past, but now is always on.
 mpowerpc
 Target RejectNegative Undocumented Ignore
@@ -163,7 +174,7 @@  Target Report Mask(POPCNTD) Save
 Use PowerPC V2.06 popcntd instruction
 
 mfriz
-Target Report Var(TARGET_FRIZ) Init(-1) Save
+Target Report Mask(FRIZ) Var(rs6000_flags2)
 Under -ffast-math, generate a FRIZ instruction for (double)(long long) conversions
 
 mveclibabi=
@@ -223,7 +234,7 @@  Target Report Var(TARGET_SINGLE_PIC_BASE
 Do not load the PIC register in function prologues
 
 mavoid-indexed-addresses
-Target Report Var(TARGET_AVOID_XFORM) Init(-1) Save
+Target Report Mask(AVOID_XFORM) Var(rs6000_flags2)
 Avoid generation of indexed load/store instructions when possible
 
 mtls-markers
@@ -325,7 +336,7 @@  Target Var(rs6000_spe) Save
 Generate SPE SIMD instructions on E500
 
 mpaired
-Target Var(rs6000_paired_float) Save
+Target Mask(PAIRED_FLOAT) Var(rs6000_flags2)
 Generate PPC750CL paired-single instructions
 
 mspe=no
@@ -397,7 +408,7 @@  EnumValue
 Enum(rs6000_traceback_type) String(no) Value(traceback_none)
 
 mlongcall
-Target Report Var(rs6000_default_long_calls) Save
+Target Report Mask(LONG_CALLS) Var(rs6000_flags2)
 Avoid all range limits on call instructions
 
 mgen-cell-microcode
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 192041)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -41,7 +41,7 @@ 
 
    where TOGGLE is either 0 or 1.
 
-   rs6000_default_long_calls is set to the value of TOGGLE, changing
+   TARGET_LONG_CALLS is set to the value of TOGGLE, changing
    whether or not new function declarations receive a longcall
    attribute by default.  */
 
@@ -72,7 +72,10 @@  rs6000_pragma_longcall (cpp_reader *pfil
   if (pragma_lex (&x) != CPP_EOF)
     warning (OPT_Wpragmas, "junk at end of #pragma longcall");
 
-  rs6000_default_long_calls = (n == integer_one_node);
+  if (n == integer_one_node)
+    rs6000_flags2 |= OPTION_MASK_LONG_CALLS;
+  else
+    rs6000_flags2 &= ~OPTION_MASK_LONG_CALLS;
 }
 
 /* Handle defining many CPP flags based on TARGET_xxx.  As a general
@@ -285,12 +288,13 @@  rs6000_define_or_undefine_macro (bool de
    have both the target flags and the builtin flags as arguments.  */
 
 void
-rs6000_target_modify_macros (bool define_p, int flags, unsigned bu_mask)
+rs6000_target_modify_macros (bool define_p, int flags, int flags2,
+			     unsigned bu_mask)
 {
   if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
-    fprintf (stderr, "rs6000_target_modify_macros (%s, 0x%x, 0x%x)\n",
+    fprintf (stderr, "rs6000_target_modify_macros (%s, 0x%x, 0x%x, 0x%x)\n",
 	     (define_p) ? "define" : "undef",
-	     (unsigned) flags, bu_mask);
+	     (unsigned) flags, (unsigned) flags2, bu_mask);
 
   /* target_flags based options.  */
   rs6000_define_or_undefine_macro (define_p, "_ARCH_PPC");
@@ -342,7 +346,7 @@  void
 rs6000_cpu_cpp_builtins (cpp_reader *pfile)
 {
   /* Define all of the common macros.  */
-  rs6000_target_modify_macros (true, target_flags,
+  rs6000_target_modify_macros (true, target_flags, rs6000_flags2,
 			       rs6000_builtin_mask_calculate ());
 
   if (TARGET_FRE)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 192041)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -288,7 +288,7 @@  typedef rtx (*gen_2arg_fn_t) (rtx, rtx, 
 /* Pointer to function (in rs6000-c.c) that can define or undefine target
    macros that have changed.  Languages that don't support the preprocessor
    don't link in rs6000-c.c, so we can't call it directly.  */
-void (*rs6000_target_modify_macros_ptr) (bool, int, unsigned);
+void (*rs6000_target_modify_macros_ptr) (bool, int, int, unsigned);
 
 
 /* Target cpu costs.  */
@@ -990,6 +990,9 @@  static bool rs6000_debug_cannot_change_m
 						   enum machine_mode,
 						   enum reg_class);
 static bool rs6000_save_toc_in_prologue_p (void);
+static void rs6000_print_target_flags (FILE *, int, int, const char *);
+static void rs6000_print_rs6000_flags2 (FILE *, int, int, const char *);
+static void rs6000_print_builtin_flags (FILE *, unsigned, int, const char *);
 
 rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode, int, int,
 					     int, int *)
@@ -1477,7 +1480,8 @@  enum {
 		   | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
 		   | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP
 		   | MASK_POPCNTD | MASK_VSX | MASK_ISEL | MASK_NO_UPDATE
-		   | MASK_RECIP_PRECISION)
+		   | MASK_RECIP_PRECISION | MASK_SOFT_FLOAT),
+  POWERPC_MASKS2 = (OPTION_MASK_AVOID_XFORM)
 };
 
 /* Masks for instructions set at various powerpc ISAs.  */
@@ -1506,13 +1510,16 @@  struct rs6000_ptt
   const char *const name;		/* Canonical processor name.  */
   const enum processor_type processor;	/* Processor type enum value.  */
   const int target_enable;		/* Target flags to enable.  */
+  const int target_enable2;		/* 2nd target flags word to enable. */
 };
 
 static struct rs6000_ptt const processor_target_table[] =
 {
-#define RS6000_CPU(NAME, CPU, FLAGS) { NAME, CPU, FLAGS },
+#define RS6000_CPU(NAME, CPU, FLAGS) { NAME, CPU, FLAGS, 0 },
+#define RS6000_CPU2(NAME, CPU, FLAGS, FLAGS2) { NAME, CPU, FLAGS, FLAGS2 },
 #include "rs6000-cpus.def"
 #undef RS6000_CPU
+#undef RS6000_CPU2
 };
 
 /* Look up a processor name for -mcpu=xxx and -mtune=xxx.  Return -1 if the
@@ -1717,8 +1724,9 @@  rs6000_debug_reg_print (int first_regno,
 }
 
 #define DEBUG_FMT_D "%-32s= %d\n"
-#define DEBUG_FMT_X "%-32s= 0x%x\n"
+#define DEBUG_FMT_X "%-32s= 0x%.8x"
 #define DEBUG_FMT_S "%-32s= %s\n"
+#define DEBUG_FMT_S2 "%-32s= %s (%d)\n"
 
 /* Print various interesting information with -mdebug=reg.  */
 static void
@@ -1813,12 +1821,28 @@  rs6000_debug_reg_global (void)
     }
 
   if (rs6000_cpu_index >= 0)
-    fprintf (stderr, DEBUG_FMT_S, "cpu",
-	     processor_target_table[rs6000_cpu_index].name);
+    {
+      const struct rs6000_ptt *p = &processor_target_table[rs6000_cpu_index];
+      fprintf (stderr, DEBUG_FMT_S2, "cpu", p->name, (int)p->processor);
+      rs6000_print_target_flags (stderr, p->target_enable, 0, "cpu_flags");
+      rs6000_print_rs6000_flags2 (stderr, p->target_enable2, 0, "cpu_flags2");
+    }
+  else
+    fprintf (stderr, DEBUG_FMT_S, "cpu", "<none>");
 
   if (rs6000_tune_index >= 0)
-    fprintf (stderr, DEBUG_FMT_S, "tune",
-	     processor_target_table[rs6000_tune_index].name);
+    {
+      const struct rs6000_ptt *p = &processor_target_table[rs6000_tune_index];
+      fprintf (stderr, DEBUG_FMT_S2, "tune", p->name, (int)p->processor);
+      rs6000_print_target_flags (stderr, p->target_enable, 0, "tune_flags");
+      rs6000_print_rs6000_flags2 (stderr, p->target_enable2, 0, "tune_flags2");
+    }
+  else
+    fprintf (stderr, DEBUG_FMT_S, "tune", "<none>");
+
+  rs6000_print_target_flags (stderr, target_flags, 0, "target_flags");
+  rs6000_print_rs6000_flags2 (stderr, rs6000_flags2, 0, "rs6000_flags2");
+  rs6000_print_builtin_flags (stderr, rs6000_builtin_mask, 0, "builtins");
 
   switch (rs6000_sched_costly_dep)
     {
@@ -1948,7 +1972,6 @@  rs6000_debug_reg_global (void)
 	   (int)END_BUILTINS);
   fprintf (stderr, DEBUG_FMT_D, "Number of rs6000 builtins",
 	   (int)RS6000_BUILTIN_COUNT);
-  fprintf (stderr, DEBUG_FMT_X, "Builtin mask", rs6000_builtin_mask);
 }
 
 /* Initialize the various global tables that are based on register size.  */
@@ -2317,8 +2340,8 @@  darwin_rs6000_override_options (void)
     }
   if (flag_mkernel)
     {
-      rs6000_default_long_calls = 1;
       target_flags |= MASK_SOFT_FLOAT;
+      target_flags2 |= OPTION_MASK_LONG_CALLS;
     }
 
   /* Make -m64 imply -maltivec.  Darwin's 64-bit ABI includes
@@ -2361,10 +2384,9 @@  rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_VSX)		    ? RS6000_BTM_VSX	  : 0)
 	  | ((TARGET_SPE)		    ? RS6000_BTM_SPE	  : 0)
 	  | ((TARGET_PAIRED_FLOAT)	    ? RS6000_BTM_PAIRED	  : 0)
-	  | ((TARGET_FRE)		    ? RS6000_BTM_FRE	  : 0)
-	  | ((TARGET_FRES)		    ? RS6000_BTM_FRES	  : 0)
-	  | ((TARGET_FRSQRTE)		    ? RS6000_BTM_FRSQRTE  : 0)
-	  | ((TARGET_FRSQRTES)		    ? RS6000_BTM_FRSQRTES : 0)
+	  | ((TARGET_PPC_GFXOPT)	    ? RS6000_BTM_GFXOPT	  : 0)
+	  | ((TARGET_POPCNTB)		    ? RS6000_BTM_POPCNTB  : 0)
+	  | ((TARGET_FPRND)		    ? RS6000_BTM_FPRND	  : 0)
 	  | ((TARGET_POPCNTD)		    ? RS6000_BTM_POPCNTD  : 0)
 	  | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL     : 0));
 }
@@ -2382,6 +2404,7 @@  rs6000_option_override_internal (bool gl
   const char *implicit_cpu = OPTION_TARGET_CPU_DEFAULT;
 
   int set_masks;
+  int set_masks2;
   int cpu_index;
   int tune_index;
   struct cl_target_option *main_target_opt
@@ -2418,18 +2441,21 @@  rs6000_option_override_internal (bool gl
       rs6000_pointer_size = 32;
     }
 
-  set_masks = POWERPC_MASKS | MASK_SOFT_FLOAT;
+  set_masks = POWERPC_MASKS;
+  set_masks2 = POWERPC_MASKS2;
+
 #ifdef OS_MISSING_POWERPC64
   if (OS_MISSING_POWERPC64)
     set_masks &= ~MASK_POWERPC64;
 #endif
 #ifdef OS_MISSING_ALTIVEC
   if (OS_MISSING_ALTIVEC)
-    set_masks &= ~MASK_ALTIVEC;
+    set_masks &= ~(MASK_ALTIVEC | MASK_VSX);
 #endif
 
   /* Don't override by the processor default if given explicitly.  */
   set_masks &= ~target_flags_explicit;
+  set_masks2 &= ~rs6000_flags2_explicit;
 
   /* Process the -mcpu=<xxx> and -mtune=<xxx> argument.  If the user changed
      the cpu in a target attribute or pragma, but did not specify a tuning
@@ -2470,10 +2496,17 @@  rs6000_option_override_internal (bool gl
       target_flags &= ~set_masks;
       target_flags |= (processor_target_table[cpu_index].target_enable
 		       & set_masks);
+      rs6000_flags2 &= ~set_masks2;
+      rs6000_flags2 |= (processor_target_table[cpu_index].target_enable2
+			& set_masks2);
     }
   else
-    target_flags |= (processor_target_table[cpu_index].target_enable
-		     & ~target_flags_explicit);
+    {
+      target_flags |= (processor_target_table[cpu_index].target_enable
+		       & ~target_flags_explicit);
+      rs6000_flags2 |= (processor_target_table[cpu_index].target_enable2
+			& ~rs6000_flags2_explicit);
+    }
 
   if (rs6000_tune_index >= 0)
     tune_index = rs6000_tune_index;
@@ -2583,6 +2616,13 @@  rs6000_option_override_internal (bool gl
 	}
     }
 
+  /* Reset -mavoid-indexed-addresses if it was enabled by default but
+     altivec/vsx were used.  */
+  if (((rs6000_flags2_explicit & OPTION_MASK_AVOID_XFORM) == 0)
+      && TARGET_AVOID_XFORM
+      && (TARGET_ALTIVEC || TARGET_VSX))
+    rs6000_flags2 &= ~OPTION_MASK_AVOID_XFORM;
+
   /* Add some warnings for VSX.  */
   if (TARGET_VSX)
     {
@@ -2602,7 +2642,7 @@  rs6000_option_override_internal (bool gl
 	 systems at this point.  */
       else if (!BYTES_BIG_ENDIAN)
 	msg = N_("-mvsx used with little endian code");
-      else if (TARGET_AVOID_XFORM > 0)
+      else if (TARGET_AVOID_XFORM)
 	msg = N_("-mvsx needs indexed addressing");
       else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC))
         {
@@ -3113,16 +3153,6 @@  rs6000_option_override_internal (bool gl
       && rs6000_single_float == 0 && rs6000_double_float == 0)
     rs6000_single_float = rs6000_double_float = 1;
 
-  /* If not explicitly specified via option, decide whether to generate indexed
-     load/store instructions.  */
-  if (TARGET_AVOID_XFORM == -1)
-    /* Avoid indexed addressing when targeting Power6 in order to avoid the
-     DERAT mispredict penalty.  However the LVE and STVE altivec instructions
-     need indexed accesses and the type used is the scalar type of the element
-     being loaded or stored.  */
-    TARGET_AVOID_XFORM = (rs6000_cpu == PROCESSOR_POWER6 && TARGET_CMPB
-			  && !TARGET_ALTIVEC);
-
   /* Set the -mrecip options.  */
   if (rs6000_recip_name)
     {
@@ -3176,11 +3206,7 @@  rs6000_option_override_internal (bool gl
      target_flags.  */
   rs6000_builtin_mask = rs6000_builtin_mask_calculate ();
   if (TARGET_DEBUG_BUILTIN || TARGET_DEBUG_TARGET)
-    fprintf (stderr, "new builtin mask = 0x%x%s%s%s%s\n", rs6000_builtin_mask,
-	     (rs6000_builtin_mask & RS6000_BTM_ALTIVEC) ? ", altivec" : "",
-	     (rs6000_builtin_mask & RS6000_BTM_VSX)     ? ", vsx"     : "",
-	     (rs6000_builtin_mask & RS6000_BTM_PAIRED)  ? ", paired"  : "",
-	     (rs6000_builtin_mask & RS6000_BTM_SPE)     ? ", spe" : "");
+    rs6000_print_builtin_flags (stderr, rs6000_builtin_mask, 0, "builtins");
 
   /* Initialize all of the registers.  */
   rs6000_init_hard_regno_mode_ok (global_init_p);
@@ -7451,7 +7477,7 @@  init_cumulative_args (CUMULATIVE_ARGS *c
     cum->nargs_prototype = n_named_args;
 
   /* Check for a longcall attribute.  */
-  if ((!fntype && rs6000_default_long_calls)
+  if ((!fntype && TARGET_LONG_CALLS)
       || (fntype
 	  && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
 	  && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))))
@@ -10326,7 +10352,7 @@  static rtx
 altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
   tree arg0;
   enum machine_mode tmode, mode0;
   rtx pat, op0;
@@ -10385,7 +10411,7 @@  altivec_expand_st_builtin (tree exp, rtx
 			   bool *expandedp)
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
   tree arg0, arg1;
   enum machine_mode mode0, mode1;
   rtx pat, op0, op1;
@@ -10442,7 +10468,7 @@  altivec_expand_dst_builtin (tree exp, rt
 			    bool *expandedp)
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
   tree arg0, arg1, arg2;
   enum machine_mode mode0, mode1;
   rtx pat, op0, op1, op2;
@@ -10844,7 +10870,7 @@  static rtx
 paired_expand_builtin (tree exp, rtx target, bool * expandedp)
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
   const struct builtin_description *d;
   size_t i;
 
@@ -10909,7 +10935,7 @@  spe_expand_builtin (tree exp, rtx target
 {
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   tree arg1, arg0;
-  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
   enum insn_code icode;
   enum machine_mode tmode, mode0;
   rtx pat, op0;
@@ -11287,6 +11313,12 @@  rs6000_invalid_builtin (enum rs6000_buil
     error ("Builtin function %s requires the -mpaired option", name);
   else if ((fnmask & RS6000_BTM_SPE) != 0)
     error ("Builtin function %s requires the -mspe option", name);
+  else if ((fnmask & RS6000_BTM_POPCNTB) != 0)
+    error ("Builtin function %s requires the -mpopcntb option", name);
+  else if ((fnmask & RS6000_BTM_FPRND) != 0)
+    error ("Builtin function %s requires the -mfprnd option", name);
+  else if ((fnmask & RS6000_BTM_POPCNTD) != 0)
+    error ("Builtin function %s requires the -mpopcntd option", name);
   else
     error ("Builtin function %s is not supported with the current options",
 	   name);
@@ -24648,11 +24680,11 @@  rs6000_handle_longcall_attribute (tree *
 }
 
 /* Set longcall attributes on all functions declared when
-   rs6000_default_long_calls is true.  */
+   TARGET_LONG_CALLS is true.  */
 static void
 rs6000_set_default_type_attributes (tree type)
 {
-  if (rs6000_default_long_calls
+  if (TARGET_LONG_CALLS
       && (TREE_CODE (type) == FUNCTION_TYPE
 	  || TREE_CODE (type) == METHOD_TYPE))
     TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
@@ -27384,9 +27416,9 @@  rs6000_final_prescan_insn (rtx insn, rtx
 
 
 /* Mask options that we want to support inside of attribute((target)) and
-   #pragma GCC target operations.  Note, we do not include things like
-   64/32-bit, endianess, hard/soft floating point, etc. that would have
-   different calling sequences.  */
+   #pragma GCC target operations that are options set in target_flags.  Note,
+   we do not include things like 64/32-bit, endianess, hard/soft floating
+   point, etc. that would have different calling sequences.  */
 
 struct rs6000_opt_mask {
   const char *name;		/* option name */
@@ -27441,6 +27473,16 @@  static struct rs6000_opt_mask const rs60
   { "string",		MASK_STRING,		false, false },
 };
 
+/* Mask options that we want to support inside of attribute((target)) and
+   #pragma GCC target operations that are set in rs6000_flags2.  */
+static struct rs6000_opt_mask const rs6000_opt_masks2[] =
+{
+  { "friz",			OPTION_MASK_FRIZ,	  false, true },
+  { "avoid-indexed-addresses",	OPTION_MASK_AVOID_XFORM,  true,  true },
+  { "longcall",			OPTION_MASK_LONG_CALLS,	  false, true },
+  { "paired",			OPTION_MASK_PAIRED_FLOAT, false, true },
+};
+
 /* Builtin mask mapping for printing the flags.  */
 static struct rs6000_opt_mask const rs6000_builtin_mask_names[] =
 {
@@ -27448,38 +27490,68 @@  static struct rs6000_opt_mask const rs60
   { "vsx",		 RS6000_BTM_VSX,	false, false },
   { "spe",		 RS6000_BTM_SPE,	false, false },
   { "paired",		 RS6000_BTM_PAIRED,	false, false },
-  { "fre",		 RS6000_BTM_FRE,	false, false },
-  { "fres",		 RS6000_BTM_FRES,	false, false },
-  { "frsqrte",		 RS6000_BTM_FRSQRTE,	false, false },
-  { "frsqrtes",		 RS6000_BTM_FRSQRTES,	false, false },
-  { "popcntd",		 RS6000_BTM_POPCNTD,	false, false },
+  { "gfxopt",		 RS6000_BTM_GFXOPT,	false, false },
   { "cell",		 RS6000_BTM_CELL,	false, false },
+  { "popcntb",		 RS6000_BTM_POPCNTB,	false, false },
+  { "fprnd",		 RS6000_BTM_FPRND,	false, false },
+  { "popcntd",		 RS6000_BTM_POPCNTD,	false, false },
 };
 
-/* Option variables that we want to support inside attribute((target)) and
-   #pragma GCC target operations.  */
-
-struct rs6000_opt_var {
-  const char *name;		/* option name */
-  size_t global_offset;		/* offset of the option in global_options.  */
-  size_t target_offset;		/* offset of the option in target optiosn.  */
-};
+/* Inner function to set the flags for a given option.  Return true if the
+   option was found.  */
 
-static struct rs6000_opt_var const rs6000_opt_vars[] =
+static bool
+rs6000_find_target_option (const char *name)
 {
-  { "friz",
-    offsetof (struct gcc_options, x_TARGET_FRIZ),
-    offsetof (struct cl_target_option, x_TARGET_FRIZ), },
-  { "avoid-indexed-addresses",
-    offsetof (struct gcc_options, x_TARGET_AVOID_XFORM),
-    offsetof (struct cl_target_option, x_TARGET_AVOID_XFORM) },
-  { "paired",
-    offsetof (struct gcc_options, x_rs6000_paired_float),
-    offsetof (struct cl_target_option, x_rs6000_paired_float), },
-  { "longcall",
-    offsetof (struct gcc_options, x_rs6000_default_long_calls),
-    offsetof (struct cl_target_option, x_rs6000_default_long_calls), },
-};
+  size_t i, j;
+  bool invert = false;
+  const struct rs6000_opt_mask *opts;
+  size_t n_opts;
+  int *flags, *explicit_flags;
+
+  if (strncmp (name, "no-", 3) == 0)
+    {
+      invert = true;
+      name += 3;
+    }
+
+  for (i = 0; i < 2; i++)
+    {
+      if (i == 0)
+	{
+	  opts = rs6000_opt_masks;
+	  n_opts = ARRAY_SIZE (rs6000_opt_masks);
+	  flags = &target_flags;
+	  explicit_flags = &target_flags_explicit;
+	}
+      else
+	{
+	  opts = rs6000_opt_masks2;
+	  n_opts = ARRAY_SIZE (rs6000_opt_masks2);
+	  flags = &rs6000_flags2;
+	  explicit_flags = &rs6000_flags2_explicit;
+	}
+
+      for (j = 0; j < n_opts; j++)
+	if (opts[j].valid_target && strcmp (name, opts[j].name) == 0)
+	  {
+	    int mask = opts[j].mask;
+
+	    *explicit_flags |= mask;
+
+	    if (opts[j].invert)
+	      invert = !invert;
+
+	    if (invert)
+	      *flags &= ~mask;
+	    else
+	      *flags |= mask;
+	    return true;
+	  }
+      }
+
+  return false;
+}
 
 /* Inner function to handle attribute((target("..."))) and #pragma GCC target
    parsing.  Return true if there were no errors.  */
@@ -27500,7 +27572,6 @@  rs6000_inner_target_options (tree args, 
       while ((q = strtok (p, ",")) != NULL)
 	{
 	  bool error_p = false;
-	  bool not_valid_p = false;
 	  const char *cpu_opt = NULL;
 
 	  p = NULL;
@@ -27526,59 +27597,15 @@  rs6000_inner_target_options (tree args, 
 		  cpu_opt = q+5;
 		}
 	    }
-	  else
+	  else if (rs6000_find_target_option (q))
 	    {
-	      size_t i;
-	      bool invert = false;
-	      char *r = q;
-
-	      error_p = true;
-	      if (strncmp (r, "no-", 3) == 0)
-		{
-		  invert = true;
-		  r += 3;
-		}
-
-	      for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
-		if (strcmp (r, rs6000_opt_masks[i].name) == 0)
-		  {
-		    int mask = rs6000_opt_masks[i].mask;
-
-		    if (!rs6000_opt_masks[i].valid_target)
-		      not_valid_p = true;
-		    else
-		      {
-			error_p = false;
-			target_flags_explicit |= mask;
-
-			/* VSX needs altivec, so -mvsx automagically sets
-			   altivec.  */
-			if (mask == MASK_VSX && !invert)
-			  mask |= MASK_ALTIVEC;
-
-			if (rs6000_opt_masks[i].invert)
-			  invert = !invert;
-
-			if (invert)
-			  target_flags &= ~mask;
-			else
-			  target_flags |= mask;
-		      }
-		    break;
-		  }
-
-	      if (error_p && !not_valid_p)
-		{
-		  for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
-		    if (strcmp (r, rs6000_opt_vars[i].name) == 0)
-		      {
-			size_t j = rs6000_opt_vars[i].global_offset;
-			*((int *) ((char *)&global_options + j)) = !invert;
-			error_p = false;
-			break;
-		      }
-		}
+	      /* VSX needs altivec, so attribute((target("vsx")))
+		 automagically sets altivec.  */
+	      if (TARGET_VSX)
+		target_flags |= MASK_ALTIVEC;
 	    }
+	  else
+	    error_p = true;
 
 	  if (error_p)
 	    {
@@ -27599,8 +27626,6 @@  rs6000_inner_target_options (tree args, 
 	      if (cpu_opt)
 		error ("invalid cpu \"%s\" for %s\"%s\"%s", cpu_opt, eprefix,
 		       q, esuffix);
-	      else if (not_valid_p)
-		error ("%s\"%s\"%s is not allowed", eprefix, q, esuffix);
 	      else
 		error ("%s\"%s\"%s is invalid", eprefix, q, esuffix);
 	    }
@@ -27768,6 +27793,7 @@  rs6000_pragma_target_parse (tree args, t
   struct cl_target_option *prev_opt, *cur_opt;
   unsigned prev_bumask, cur_bumask, diff_bumask;
   int prev_flags, cur_flags, diff_flags;
+  int prev_flags2, cur_flags2, diff_flags2;
 
   if (TARGET_DEBUG_TARGET)
     {
@@ -27818,24 +27844,29 @@  rs6000_pragma_target_parse (tree args, t
       prev_opt    = TREE_TARGET_OPTION (prev_tree);
       prev_bumask = prev_opt->x_rs6000_builtin_mask;
       prev_flags  = prev_opt->x_target_flags;
+      prev_flags2 = prev_opt->x_rs6000_flags2;
 
       cur_opt     = TREE_TARGET_OPTION (cur_tree);
       cur_flags   = cur_opt->x_target_flags;
+      cur_flags2  = cur_opt->x_rs6000_flags2;
       cur_bumask  = cur_opt->x_rs6000_builtin_mask;
 
       diff_bumask = (prev_bumask ^ cur_bumask);
       diff_flags  = (prev_flags  ^ cur_flags);
+      diff_flags2 = (prev_flags2 ^ cur_flags2);
 
-      if ((diff_flags != 0) || (diff_bumask != 0))
+      if ((diff_flags != 0) || (diff_bumask != 0) || (diff_flags2 != 0))
 	{
 	  /* Delete old macros.  */
 	  rs6000_target_modify_macros_ptr (false,
 					   prev_flags & diff_flags,
+					   prev_flags2 & diff_flags2,
 					   prev_bumask & diff_bumask);
 
 	  /* Define new macros.  */
 	  rs6000_target_modify_macros_ptr (true,
 					   cur_flags & diff_flags,
+					   cur_flags2 & diff_flags2,
 					   cur_bumask & diff_bumask);
 	}
     }
@@ -27922,12 +27953,91 @@  rs6000_set_current_function (tree fndecl
 }
 
 
+/* Decode the various flags in target_flags, rs6000_flags2, and
+   rs6000_builtin_mask.  */
+
+static void
+rs6000_print_flags_internal (FILE *file, int flags, int indent,
+			     const char *hdr, const char *prefix,
+			     const struct rs6000_opt_mask *opts,
+			     size_t n_elements)
+{
+  size_t i;
+  const char *final = ", <none>";
+  const char *nl = "\n";
+  const char *comma = ", ";
+  int start_column;
+  size_t column;
+  size_t max_column = 98;
+
+  if (indent)
+    fprintf (file, "%*s", indent, "");
+
+  column = start_column = indent + fprintf (file, DEBUG_FMT_X, hdr, flags) + 2;
+  for (i = 0; i < n_elements; i++)
+    if ((flags & opts[i].mask) != 0)
+      {
+	const char *no_str = opts[i].invert ? "no-" : "";
+	size_t len = (strlen (comma)
+		      + strlen (prefix)
+		      + strlen (no_str)
+		      + strlen (opts[i].name));
+
+	column += len;
+	if (column > max_column)
+	  {
+	    fprintf (stderr, ", \\\n%*s", start_column, "");
+	    column = start_column + len;
+	    comma = "";
+	    nl = "\n\n";
+	  }
+
+	fprintf (file, "%s%s%s%s", comma, prefix, no_str, opts[i].name);
+	flags &= ~ opts[i].mask;
+	comma = ", ";
+	final = "";
+      }
+
+  fputs (final, file);
+  fputs (nl, file);
+}
+
+static void
+rs6000_print_target_flags (FILE *file, int mask, int indent, const char *hdr)
+{
+  rs6000_print_flags_internal (file, mask, indent, hdr, "-m",
+			       rs6000_opt_masks,
+			       ARRAY_SIZE (rs6000_opt_masks));
+}
+
+static void
+rs6000_print_rs6000_flags2 (FILE *file, int mask, int indent, const char *hdr)
+{
+  rs6000_print_flags_internal (file, mask, indent, hdr, "-m",
+			       rs6000_opt_masks2,
+			       ARRAY_SIZE (rs6000_opt_masks2));
+}
+
+/* Decode the builtin flags.  */
+
+static void
+rs6000_print_builtin_flags (FILE *file, unsigned mask, int indent,
+			    const char *hdr)
+{
+  rs6000_print_flags_internal (file, (int)mask, indent, hdr, "",
+			       rs6000_builtin_mask_names,
+			       ARRAY_SIZE (rs6000_builtin_mask_names));
+}
+
+
 /* Save the current options */
 
 static void
 rs6000_function_specific_save (struct cl_target_option *ptr)
 {
   ptr->rs6000_target_flags_explicit = target_flags_explicit;
+  ptr->x_rs6000_flags2 = rs6000_flags2;
+  ptr->x_rs6000_flags2_explicit = rs6000_flags2_explicit;
 }
 
 /* Restore the current options */
@@ -27936,6 +28046,8 @@  static void
 rs6000_function_specific_restore (struct cl_target_option *ptr)
 {
   target_flags_explicit = ptr->rs6000_target_flags_explicit;
+  rs6000_flags2 = ptr->x_rs6000_flags2;
+  rs6000_flags2_explicit = ptr->x_rs6000_flags2_explicit;
   (void) rs6000_option_override_internal (false);
 }
 
@@ -27945,37 +28057,13 @@  static void
 rs6000_function_specific_print (FILE *file, int indent,
 				struct cl_target_option *ptr)
 {
-  size_t i;
-  int flags = ptr->x_target_flags;
-  unsigned bu_mask = ptr->x_rs6000_builtin_mask;
-
-  /* Print the various mask options.  */
-  for (i = 0; i < ARRAY_SIZE (rs6000_opt_masks); i++)
-    if ((flags & rs6000_opt_masks[i].mask) != 0)
-      {
-	flags &= ~ rs6000_opt_masks[i].mask;
-	fprintf (file, "%*s-m%s%s\n", indent, "",
-		 rs6000_opt_masks[i].invert ? "no-" : "",
-		 rs6000_opt_masks[i].name);
-      }
+  rs6000_print_target_flags (file, ptr->x_target_flags, indent,
+			     "target_flags");
+  rs6000_print_rs6000_flags2 (file, ptr->x_rs6000_flags2, indent,
+			     "rs6000_flags2");
 
-  /* Print the various options that are variables.  */
-  for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
-    {
-      size_t j = rs6000_opt_vars[i].target_offset;
-      if (((signed char *) ptr)[j])
-	fprintf (file, "%*s-m%s\n", indent, "",
-		 rs6000_opt_vars[i].name);
-    }
-
-  /* Print the various builtin flags.  */
-  fprintf (file, "%*sbuiltin mask = 0x%x\n", indent, "", bu_mask);
-  for (i = 0; i < ARRAY_SIZE (rs6000_builtin_mask_names); i++)
-    if ((bu_mask & rs6000_builtin_mask_names[i].mask) != 0)
-      {
-	fprintf (file, "%*s%s builtins supported\n", indent, "",
-		 rs6000_builtin_mask_names[i].name);
-      }
+  rs6000_print_builtin_flags (file, ptr->x_rs6000_builtin_mask, indent,
+			      "builtins");
 }
 
 
Index: gcc/config/rs6000/750cl.h
===================================================================
--- gcc/config/rs6000/750cl.h	(revision 192041)
+++ gcc/config/rs6000/750cl.h	(working copy)
@@ -1,5 +1,5 @@ 
 /* Enable 750cl paired single support.
-   Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009, 2012 Free Software Foundation, Inc.
    Contributed by Revital Eres (eres@il.ibm.com)
    This file is part of GCC.
 
@@ -22,8 +22,7 @@ 
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#undef TARGET_PAIRED_FLOAT
-#define TARGET_PAIRED_FLOAT rs6000_paired_float
+#define HAVE_PAIRED_FLOAT 1
 
 #undef ASM_CPU_SPEC 
 #define ASM_CPU_SPEC "-m750cl"
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 192041)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -67,10 +67,6 @@ 
 #define PPC405_ERRATUM77 0
 #endif
 
-#ifndef TARGET_PAIRED_FLOAT
-#define TARGET_PAIRED_FLOAT 0
-#endif
-
 #ifdef HAVE_AS_POPCNTB
 #define ASM_CPU_POWER5_SPEC "-mpower5"
 #else
@@ -327,6 +323,10 @@  extern const char *host_detect_local_cpu
 
 #define TARGET_DEFAULT (MASK_MULTIPLE | MASK_STRING)
 
+#ifndef TARGET_DEFAULT_FLAGS2
+#define TARGET_DEFAULT_FLAGS2 (OPTION_MASK_FRIZ)
+#endif
+
 /* FPU operations supported. 
    Each use of TARGET_SINGLE_FLOAT or TARGET_DOUBLE_FLOAT must 
    also test TARGET_HARD_FLOAT.  */
@@ -336,6 +336,12 @@  extern const char *host_detect_local_cpu
 #define TARGET_SIMPLE_FPU   0
 #define TARGET_XILINX_FPU   0
 
+/* Map options set in the 2nd flags word back to TARGET_xxx.  */
+#define TARGET_FRIZ		OPTION_FRIZ
+#define TARGET_AVOID_XFORM	OPTION_AVOID_XFORM
+#define TARGET_LONG_CALLS	OPTION_LONG_CALLS
+#define TARGET_PAIRED_FLOAT	OPTION_PAIRED_FLOAT
+
 /* Recast the processor type to the cpu attribute.  */
 #define rs6000_cpu_attr ((enum attr_cpu)rs6000_cpu)
 
@@ -465,6 +471,9 @@  extern int rs6000_vector_align[];
 #define TARGET_FCTIDUZ	TARGET_POPCNTD
 #define TARGET_FCTIWUZ	TARGET_POPCNTD
 
+/* Explicit secondary flag options that were set.  */
+#define rs6000_flags2_explicit	global_options_set.x_rs6000_flags2
+
 /* For power systems, we want to enable Altivec and VSX builtins even if the
    user did not use -maltivec or -mvsx to allow the builtins to be used inside
    of #pragma GCC target or the target attribute to change the code level for a
@@ -2273,29 +2282,34 @@  extern int frame_pointer_needed;
 #define RS6000_BTC_MEM		RS6000_BTC_MISC	/* load/store touches mem.  */
 #define RS6000_BTC_SAT		RS6000_BTC_MISC	/* saturate sets VSCR.  */
 
-/* Builtin targets.  For now, we reuse the masks for those options that are in
-   target flags, and pick two random bits for SPE and paired which aren't in
-   target_flags.  */
-#define RS6000_BTM_ALWAYS	0		/* Always enabled.  */
-#define RS6000_BTM_ALTIVEC	MASK_ALTIVEC	/* VMX/altivec vectors.  */
-#define RS6000_BTM_VSX		MASK_VSX	/* VSX (vector/scalar).  */
-#define RS6000_BTM_SPE		MASK_STRING	/* E500 */
-#define RS6000_BTM_PAIRED	MASK_MULHW	/* 750CL paired insns.  */
-#define RS6000_BTM_FRE		MASK_POPCNTB	/* FRE instruction.  */
-#define RS6000_BTM_FRES		MASK_PPC_GFXOPT	/* FRES instruction.  */
-#define RS6000_BTM_FRSQRTE	MASK_PPC_GFXOPT	/* FRSQRTE instruction.  */
-#define RS6000_BTM_FRSQRTES	MASK_POPCNTB	/* FRSQRTES instruction.  */
-#define RS6000_BTM_POPCNTD	MASK_POPCNTD	/* Target supports ISA 2.06.  */
-#define RS6000_BTM_CELL		MASK_FPRND	/* Target is cell powerpc.  */
+/* Builtin targets.  Originally these were bits set in target_flags, but now
+   that we have 2 words of target flags, define the builtin bits
+   separately.  */
+#define RS6000_BTM_ALWAYS	0x0000		/* Always enabled.  */
+#define RS6000_BTM_ALTIVEC	0x0001		/* VMX/altivec vectors.  */
+#define RS6000_BTM_VSX		0x0002		/* VSX (vector/scalar).  */
+#define RS6000_BTM_SPE		0x0004		/* E500 */
+#define RS6000_BTM_PAIRED	0x0008		/* 750CL paired insns.  */
+#define RS6000_BTM_GFXOPT	0x0010		/* PowerPC Graphics group.  */
+#define RS6000_BTM_CELL		0x0020		/* Target is cell powerpc.  */
+#define RS6000_BTM_POPCNTB	0x0040		/* ISA 2.03 (power5). */
+#define RS6000_BTM_FPRND	0x0080		/* ISA 2.04 (power5+). */
+#define RS6000_BTM_POPCNTD	0x0100		/* ISA 2.06. */
+
+#define RS6000_BTM_FRE		RS6000_BTM_POPCNTB	/* FRE insn.  */
+#define RS6000_BTM_FRES		RS6000_BTM_GFXOPT	/* FRES insn.  */
+#define RS6000_BTM_FRSQRTE	RS6000_BTM_GFXOPT	/* FRSQRTE insn.  */
+#define RS6000_BTM_FRSQRTES	RS6000_BTM_POPCNTB	/* FRSQRTES insn.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
-				 | RS6000_BTM_FRE			\
-				 | RS6000_BTM_FRES			\
-				 | RS6000_BTM_FRSQRTE			\
-				 | RS6000_BTM_FRSQRTES			\
-				 | RS6000_BTM_POPCNTD			\
-				 | RS6000_BTM_CELL)
+				 | RS6000_BTM_SPE			\
+				 | RS6000_BTM_PAIRED			\
+				 | RS6000_BTM_GFXOPT			\
+				 | RS6000_BTM_CELL			\
+				 | RS6000_BTM_POPCNTB			\
+				 | RS6000_BTM_FPRND			\
+				 | RS6000_BTM_POPCNTD)
 
 /* Define builtin enum index.  */
 
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 192041)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -26,9 +26,10 @@ 
    Please keep this list in order, and don't forget to update the documentation
    in invoke.texi when adding a new processor or flag.
 
-   Before including this file, define a macro:
+   Before including this file, define two macros:
 
    RS6000_CPU (NAME, CPU, FLAGS)
+   RS6000_CPU2 (NAME, CPU, FLAGS, FLAGS2)
 
    where the arguments are the fields of struct rs6000_ptt.  */
 
@@ -94,12 +95,18 @@  RS6000_CPU ("power5", PROCESSOR_POWER5, 
 	    | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB)
 RS6000_CPU ("power5+", PROCESSOR_POWER5, MASK_POWERPC64 | MASK_PPC_GPOPT
 	    | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND)
-RS6000_CPU ("power6", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
-	    | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
-	    | MASK_CMPB | MASK_DFP | MASK_RECIP_PRECISION)
-RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
-	    | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
-	    | MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION)
+/* Avoid indexed addressing when targeting Power6 in order to avoid the
+   DERAT mispredict penalty.  However the LVE and STVE altivec instructions
+   need indexed accesses and the type used is the scalar type of the element
+   being loaded or stored.  */
+RS6000_CPU2 ("power6", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
+	     | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
+	     | MASK_CMPB | MASK_DFP | MASK_RECIP_PRECISION,
+	     OPTION_MASK_AVOID_XFORM)
+RS6000_CPU2 ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
+	     | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
+	     | MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION,
+	     OPTION_MASK_AVOID_XFORM)
 RS6000_CPU ("power7", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
 	    POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
 	    | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 192041)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -185,8 +185,8 @@  extern void rs6000_cpu_cpp_builtins (str
 #ifdef TREE_CODE
 extern bool rs6000_pragma_target_parse (tree, tree);
 #endif
-extern void rs6000_target_modify_macros (bool, int, unsigned);
-extern void (*rs6000_target_modify_macros_ptr) (bool, int, unsigned);
+extern void rs6000_target_modify_macros (bool, int, int, unsigned);
+extern void (*rs6000_target_modify_macros_ptr) (bool, int, int, unsigned);
 
 #if TARGET_MACHO
 char *output_call (rtx, rtx *, int, int);