--- /dev/null
+--- gettext-0.16.1/gettext-runtime/tests/test-lock.c-orig 2011-07-22 12:51:14.734334073 -0500
++++ gettext-0.16.1/gettext-runtime/tests/test-lock.c 2011-07-22 12:43:59.962333864 -0500
+@@ -106,7 +106,9 @@
+ }
+ static inline void * gl_thread_self (void)
+ {
+- return (void *) pthread_self ();
++ pthread_t x;
++ x = pthread_self ();
++ return (void *)&x;
+ }
+ #endif
+ #if TEST_PTH_THREADS
--- /dev/null
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI += "file://gettext.fix_testcase.patch"
+
+PR .= "+${DISTRO}.0"
--- /dev/null
+require binutils-fsl.inc
--- /dev/null
+require binutils-fsl.inc
--- /dev/null
+require binutils-fsl.inc
--- /dev/null
+SRC_URI = "\
+ ${GNU_MIRROR}/binutils/binutils-${PV}.tar.bz2 \
+ file://bin.e5500.patch \
+ file://bin.e6500-2.patch \
+ file://bin.e500mc_nop.patch \
+ "
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+PR .= "+${DISTRO}.0"
--- /dev/null
+require binutils-fsl.inc
--- /dev/null
+Generate the preferred NOP: ori r0, r0, 0 in the place of ori r2, r2, 0
+and add the nop test cases in gas for e500mc64, e5500 and e6500.
+
+diff -ruN binutils-4.6.0-orig/gas/config/tc-ppc.c binutils-4.6.0-new/gas/config/tc-ppc.c
+--- binutils-4.6.0-orig/gas/config/tc-ppc.c 2011-08-18 16:02:21.847979825 -0500
++++ binutils-4.6.0-new/gas/config/tc-ppc.c 2011-08-19 10:09:19.888849978 -0500
+@@ -5815,8 +5817,14 @@
+ }
+
+ if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
+- /* power7 group terminating nop: "ori 2,2,0". */
+- md_number_to_chars (dest, 0x60420000, 4);
++ {
++ if (ppc_cpu & PPC_OPCODE_E500MC)
++ /* e500mc group terminating nop: "ori 0,0,0". */
++ md_number_to_chars (dest, 0x60000000, 4);
++ else
++ /* power7 group terminating nop: "ori 2,2,0". */
++ md_number_to_chars (dest, 0x60420000, 4);
++ }
+ else
+ /* power6 group terminating nop: "ori 1,1,0". */
+ md_number_to_chars (dest, 0x60210000, 4);
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e500mc64_nop.d binutils-4.6.0-new/gas/testsuite/gas/ppc/e500mc64_nop.d
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e500mc64_nop.d 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e500mc64_nop.d 2011-08-19 10:16:29.561849966 -0500
+@@ -0,0 +1,13 @@
++#as: -mppc -me500mc64
++#objdump: -dr -Me500mc64
++#name: Power E500MC64 nop tests
++
++.*: +file format elf(32)?(64)?-powerpc.*
++
++Disassembly of section \.text:
++
++0+00 <start>:
++ 0: 60 00 00 00 nop
++ 4: 60 00 00 00 nop
++ 8: 60 00 00 00 nop
++ c: 60 00 00 00 nop
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e500mc64_nop.s binutils-4.6.0-new/gas/testsuite/gas/ppc/e500mc64_nop.s
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e500mc64_nop.s 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e500mc64_nop.s 2011-08-19 10:16:29.561849966 -0500
+@@ -0,0 +1,5 @@
++# Power E500MC64 nop tests
++ .section ".text"
++start:
++ nop
++ .p2align 4,,15
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e5500_nop.d binutils-4.6.0-new/gas/testsuite/gas/ppc/e5500_nop.d
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e5500_nop.d 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e5500_nop.d 2011-08-19 10:16:29.561849966 -0500
+@@ -0,0 +1,13 @@
++#as: -mppc -me5500
++#objdump: -dr -Me5500
++#name: Power E5500 nop tests
++
++.*: +file format elf(32)?(64)?-powerpc.*
++
++Disassembly of section \.text:
++
++0+00 <start>:
++ 0: 60 00 00 00 nop
++ 4: 60 00 00 00 nop
++ 8: 60 00 00 00 nop
++ c: 60 00 00 00 nop
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e5500_nop.s binutils-4.6.0-new/gas/testsuite/gas/ppc/e5500_nop.s
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e5500_nop.s 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e5500_nop.s 2011-08-19 10:16:29.561849966 -0500
+@@ -0,0 +1,5 @@
++# Power E5500 nop tests
++ .section ".text"
++start:
++ nop
++ .p2align 4,,15
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e6500_nop.d binutils-4.6.0-new/gas/testsuite/gas/ppc/e6500_nop.d
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e6500_nop.d 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e6500_nop.d 2011-08-19 10:16:29.561849966 -0500
+@@ -0,0 +1,13 @@
++#as: -mppc -me6500
++#objdump: -dr -Me6500
++#name: Power E6500 nop tests
++
++.*: +file format elf(32)?(64)?-powerpc.*
++
++Disassembly of section \.text:
++
++0+00 <start>:
++ 0: 60 00 00 00 nop
++ 4: 60 00 00 00 nop
++ 8: 60 00 00 00 nop
++ c: 60 00 00 00 nop
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/e6500_nop.s binutils-4.6.0-new/gas/testsuite/gas/ppc/e6500_nop.s
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/e6500_nop.s 1969-12-31 18:00:00.000000000 -0600
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/e6500_nop.s 2011-08-19 10:16:29.562849956 -0500
+@@ -0,0 +1,5 @@
++# Power E6500 nop tests
++ .section ".text"
++start:
++ nop
++ .p2align 4,,15
+diff -ruN binutils-4.6.0-orig/gas/testsuite/gas/ppc/ppc.exp binutils-4.6.0-new/gas/testsuite/gas/ppc/ppc.exp
+--- binutils-4.6.0-orig/gas/testsuite/gas/ppc/ppc.exp 2011-08-19 10:15:29.445978575 -0500
++++ binutils-4.6.0-new/gas/testsuite/gas/ppc/ppc.exp 2011-08-19 10:16:17.827852501 -0500
+@@ -43,6 +43,9 @@
+ run_dump_test "ppc750ps"
+ run_dump_test "e500mc"
+ run_dump_test "e6500"
++ run_dump_test "e500mc64_nop"
++ run_dump_test "e5500_nop"
++ run_dump_test "e6500_nop"
+ run_dump_test "a2"
+ run_dump_test "cell"
+ run_dump_test "common"
--- /dev/null
+bin.e5500
+
+Implements target e5500 and -me5500, etc..
+
+diff -r -u binutils-2.21-20110211-orig/bfd/archures.c binutils-2.21-20110211/bfd/archures.c
+--- binutils-2.21-20110211-orig/bfd/archures.c 2010-12-30 18:33:31.000000000 -0600
++++ binutils-2.21-20110211/bfd/archures.c 2011-02-14 13:17:00.528340236 -0600
+@@ -234,6 +234,7 @@
+ .#define bfd_mach_ppc_e500 500
+ .#define bfd_mach_ppc_e500mc 5001
+ .#define bfd_mach_ppc_e500mc64 5005
++.#define bfd_mach_ppc_e5500 5006
+ .#define bfd_mach_ppc_titan 83
+ . bfd_arch_rs6000, {* IBM RS/6000 *}
+ .#define bfd_mach_rs6k 6000
+diff -r -u binutils-2.21-20110211-orig/bfd/bfd-in2.h binutils-2.21-20110211/bfd/bfd-in2.h
+--- binutils-2.21-20110211-orig/bfd/bfd-in2.h 2011-02-11 10:57:58.000000000 -0600
++++ binutils-2.21-20110211/bfd/bfd-in2.h 2011-02-14 13:19:57.365092179 -0600
+@@ -1921,6 +1921,7 @@
+ #define bfd_mach_ppc_e500 500
+ #define bfd_mach_ppc_e500mc 5001
+ #define bfd_mach_ppc_e500mc64 5005
++#define bfd_mach_ppc_e5500 5006
+ #define bfd_mach_ppc_titan 83
+ bfd_arch_rs6000, /* IBM RS/6000 */
+ #define bfd_mach_rs6k 6000
+diff -r -u binutils-2.21-20110211-orig/bfd/cpu-powerpc.c binutils-2.21-20110211/bfd/cpu-powerpc.c
+--- binutils-2.21-20110211-orig/bfd/cpu-powerpc.c 2010-02-07 19:59:34.000000000 -0600
++++ binutils-2.21-20110211/bfd/cpu-powerpc.c 2011-02-14 13:21:48.802403135 -0600
+@@ -352,6 +352,20 @@
+ FALSE, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
++ &bfd_powerpc_archs[19]
++ },
++ {
++ 64, /* 64 bits in a word */
++ 64, /* 64 bits in an address */
++ 8, /* 8 bits in a byte */
++ bfd_arch_powerpc,
++ bfd_mach_ppc_e5500,
++ "powerpc",
++ "powerpc:e5500",
++ 3,
++ FALSE, /* not the default */
++ powerpc_compatible,
++ bfd_default_scan,
+ 0
+ }
+ };
+diff -r -u binutils-2.21-20110211-orig/gas/config/tc-ppc.c binutils-2.21-20110211/gas/config/tc-ppc.c
+--- binutils-2.21-20110211-orig/gas/config/tc-ppc.c 2011-02-11 10:58:01.000000000 -0600
++++ binutils-2.21-20110211/gas/config/tc-ppc.c 2011-02-14 13:23:39.478340515 -0600
+@@ -1235,6 +1235,7 @@
+ -me500, -me500x2 generate code for Motorola e500 core complex\n\
+ -me500mc, generate code for Freescale e500mc core complex\n\
+ -me500mc64, generate code for Freescale e500mc64 core complex\n\
++-me5500, generate code for Freescale e5500 core complex\n\
+ -mspe generate code for Motorola SPE instructions\n\
+ -mtitan generate code for AppliedMicro Titan core complex\n\
+ -mregnames Allow symbolic names for registers\n\
+diff -r -u binutils-2.21-20110211-orig/gas/doc/as.texinfo binutils-2.21-20110211/gas/doc/as.texinfo
+--- binutils-2.21-20110211-orig/gas/doc/as.texinfo 2011-02-11 10:58:01.000000000 -0600
++++ binutils-2.21-20110211/gas/doc/as.texinfo 2011-02-14 13:26:01.383403323 -0600
+@@ -431,7 +431,7 @@
+ [@b{-a32}|@b{-a64}]
+ [@b{-mpwrx}|@b{-mpwr2}|@b{-mpwr}|@b{-m601}|@b{-mppc}|@b{-mppc32}|@b{-m603}|@b{-m604}|@b{-m403}|@b{-m405}|
+ @b{-m440}|@b{-m464}|@b{-m476}|@b{-m7400}|@b{-m7410}|@b{-m7450}|@b{-m7455}|@b{-m750cl}|@b{-mppc64}|
+- @b{-m620}|@b{-me500}|@b{-e500x2}|@b{-me500mc}|@b{-me500mc64}|@b{-mppc64bridge}|@b{-mbooke}|
++ @b{-m620}|@b{-me500}|@b{-e500x2}|@b{-me500mc}|@b{-me500mc64}|@b{-me5500}|@b{-mppc64bridge}|@b{-mbooke}|
+ @b{-mpower4}|@b{-mpr4}|@b{-mpower5}|@b{-mpwr5}|@b{-mpwr5x}|@b{-mpower6}|@b{-mpwr6}|
+ @b{-mpower7}|@b{-mpw7}|@b{-ma2}|@b{-mcell}|@b{-mspe}|@b{-mtitan}|@b{-me300}|@b{-mcom}]
+ [@b{-many}] [@b{-maltivec}|@b{-mvsx}]
+diff -r -u binutils-2.21-20110211-orig/gas/doc/c-ppc.texi binutils-2.21-20110211/gas/doc/c-ppc.texi
+--- binutils-2.21-20110211-orig/gas/doc/c-ppc.texi 2011-02-11 10:58:04.000000000 -0600
++++ binutils-2.21-20110211/gas/doc/c-ppc.texi 2011-02-14 13:26:31.140090956 -0600
+@@ -88,6 +88,9 @@
+ @item -me500mc64
+ Generate code for Freescale e500mc64 core complex.
+
++@item -me5500
++Generate code for Freescale e5500 core complex.
++
+ @item -mspe
+ Generate code for Motorola SPE instructions.
+
+diff -r -u binutils-2.21-20110211-orig/opcodes/ppc-dis.c binutils-2.21-20110211/opcodes/ppc-dis.c
+--- binutils-2.21-20110211-orig/opcodes/ppc-dis.c 2010-07-03 03:27:23.000000000 -0500
++++ binutils-2.21-20110211/opcodes/ppc-dis.c 2011-02-14 13:28:54.384090879 -0600
+@@ -114,6 +114,12 @@
+ | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
+ | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
+ 0 },
++ { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
++ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
++ | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
++ | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
++ | PPC_OPCODE_POWER7),
++ 0 },
+ { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
+ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
--- /dev/null
+bin.e6500-2
+Implements target e6500 and -me6500, etc..
+
+Also enables some cell instructions but using different opcodes. (This
+should be temporary until new mnemonics are chosen. Likely to be
+defined only when ISA 2.07 comes out)
+
+Also implements new altivec instructions, and a few other e6500
+instructions like miso, and sync with two arguments.
+
+diff -ruN binutils-2.21-20110211-e5500/bfd/archures.c binutils-2.21-20110211-e6500/bfd/archures.c
+--- binutils-2.21-20110211-e5500/bfd/archures.c 2011-05-03 16:04:03.828069461 -0500
++++ binutils-2.21-20110211-e6500/bfd/archures.c 2011-05-03 16:04:15.253938636 -0500
+@@ -235,6 +235,7 @@
+ .#define bfd_mach_ppc_e500mc 5001
+ .#define bfd_mach_ppc_e500mc64 5005
+ .#define bfd_mach_ppc_e5500 5006
++.#define bfd_mach_ppc_e6500 5007
+ .#define bfd_mach_ppc_titan 83
+ . bfd_arch_rs6000, {* IBM RS/6000 *}
+ .#define bfd_mach_rs6k 6000
+diff -ruN binutils-2.21-20110211-e5500/bfd/bfd-in2.h binutils-2.21-20110211-e6500/bfd/bfd-in2.h
+--- binutils-2.21-20110211-e5500/bfd/bfd-in2.h 2011-05-03 16:04:03.836064584 -0500
++++ binutils-2.21-20110211-e6500/bfd/bfd-in2.h 2011-05-03 16:04:15.260938268 -0500
+@@ -1922,6 +1922,7 @@
+ #define bfd_mach_ppc_e500mc 5001
+ #define bfd_mach_ppc_e500mc64 5005
+ #define bfd_mach_ppc_e5500 5006
++#define bfd_mach_ppc_e6500 5007
+ #define bfd_mach_ppc_titan 83
+ bfd_arch_rs6000, /* IBM RS/6000 */
+ #define bfd_mach_rs6k 6000
+diff -ruN binutils-2.21-20110211-e5500/bfd/cpu-powerpc.c binutils-2.21-20110211-e6500/bfd/cpu-powerpc.c
+--- binutils-2.21-20110211-e5500/bfd/cpu-powerpc.c 2011-05-03 16:04:03.839066505 -0500
++++ binutils-2.21-20110211-e6500/bfd/cpu-powerpc.c 2011-05-03 16:04:15.272066052 -0500
+@@ -366,6 +366,20 @@
+ FALSE, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
++ &bfd_powerpc_archs[20]
++ },
++ {
++ 64, /* 64 bits in a word */
++ 64, /* 64 bits in an address */
++ 8, /* 8 bits in a byte */
++ bfd_arch_powerpc,
++ bfd_mach_ppc_e6500,
++ "powerpc",
++ "powerpc:e6500",
++ 3,
++ FALSE, /* not the default */
++ powerpc_compatible,
++ bfd_default_scan,
+ 0
+ }
+ };
+diff -ruN binutils-2.21-20110211-e5500/gas/config/tc-ppc.c binutils-2.21-20110211-e6500/gas/config/tc-ppc.c
+--- binutils-2.21-20110211-e5500/gas/config/tc-ppc.c 2011-05-03 16:04:03.847063157 -0500
++++ binutils-2.21-20110211-e6500/gas/config/tc-ppc.c 2011-05-03 16:04:15.279062744 -0500
+@@ -1236,6 +1236,7 @@
+ -me500mc, generate code for Freescale e500mc core complex\n\
+ -me500mc64, generate code for Freescale e500mc64 core complex\n\
+ -me5500, generate code for Freescale e5500 core complex\n\
++-me6500, generate code for Freescale e6500 core complex\n\
+ -mspe generate code for Motorola SPE instructions\n\
+ -mtitan generate code for AppliedMicro Titan core complex\n\
+ -mregnames Allow symbolic names for registers\n\
+diff -ruN binutils-2.21-20110211-e5500/gas/doc/as.texinfo binutils-2.21-20110211-e6500/gas/doc/as.texinfo
+--- binutils-2.21-20110211-e5500/gas/doc/as.texinfo 2011-05-03 16:04:03.857062970 -0500
++++ binutils-2.21-20110211-e6500/gas/doc/as.texinfo 2011-05-03 16:04:15.289062767 -0500
+@@ -431,8 +431,8 @@
+ [@b{-a32}|@b{-a64}]
+ [@b{-mpwrx}|@b{-mpwr2}|@b{-mpwr}|@b{-m601}|@b{-mppc}|@b{-mppc32}|@b{-m603}|@b{-m604}|@b{-m403}|@b{-m405}|
+ @b{-m440}|@b{-m464}|@b{-m476}|@b{-m7400}|@b{-m7410}|@b{-m7450}|@b{-m7455}|@b{-m750cl}|@b{-mppc64}|
+- @b{-m620}|@b{-me500}|@b{-e500x2}|@b{-me500mc}|@b{-me500mc64}|@b{-me5500}|@b{-mppc64bridge}|@b{-mbooke}|
+- @b{-mpower4}|@b{-mpr4}|@b{-mpower5}|@b{-mpwr5}|@b{-mpwr5x}|@b{-mpower6}|@b{-mpwr6}|
++ @b{-m620}|@b{-me500}|@b{-e500x2}|@b{-me500mc}|@b{-me500mc64}|@b{-me5500}|@b{-me6500}|@b{-mppc64bridge}|
++ @b{-mbooke}|@b{-mpower4}|@b{-mpr4}|@b{-mpower5}|@b{-mpwr5}|@b{-mpwr5x}|@b{-mpower6}|@b{-mpwr6}|
+ @b{-mpower7}|@b{-mpw7}|@b{-ma2}|@b{-mcell}|@b{-mspe}|@b{-mtitan}|@b{-me300}|@b{-mcom}]
+ [@b{-many}] [@b{-maltivec}|@b{-mvsx}]
+ [@b{-mregnames}|@b{-mno-regnames}]
+diff -ruN binutils-2.21-20110211-e5500/gas/doc/c-ppc.texi binutils-2.21-20110211-e6500/gas/doc/c-ppc.texi
+--- binutils-2.21-20110211-e5500/gas/doc/c-ppc.texi 2011-05-03 16:04:03.859065711 -0500
++++ binutils-2.21-20110211-e6500/gas/doc/c-ppc.texi 2011-05-03 16:04:15.291064458 -0500
+@@ -91,6 +91,9 @@
+ @item -me5500
+ Generate code for Freescale e5500 core complex.
+
++@item -me6500
++Generate code for Freescale e6500 core complex.
++
+ @item -mspe
+ Generate code for Motorola SPE instructions.
+
+diff -ruN binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/e6500.d binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/e6500.d
+--- binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/e6500.d 1969-12-31 18:00:00.000000000 -0600
++++ binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/e6500.d 2011-05-03 17:04:13.611815418 -0500
+@@ -0,0 +1,75 @@
++#as: -mppc -me6500
++#objdump: -dr -Me6500
++#name: Power E6500 tests
++
++.*: +file format elf(32)?(64)?-powerpc.*
++
++Disassembly of section \.text:
++
++0+00 <start>:
++ 0: 10 01 10 c0 vabsdub v0,v1,v2
++ 4: 10 01 11 00 vabsduh v0,v1,v2
++ 8: 10 01 11 40 vabsduw v0,v1,v2
++ c: 7c 01 10 dc mvidsplt v0,r1,r2
++ 10: 7c 01 11 1c mviwsplt v0,r1,r2
++ 14: 7c 00 12 0a lvexbx v0,0,r2
++ 18: 7c 01 12 0a lvexbx v0,r1,r2
++ 1c: 7c 00 12 4a lvexhx v0,0,r2
++ 20: 7c 01 12 4a lvexhx v0,r1,r2
++ 24: 7c 00 12 8a lvexwx v0,0,r2
++ 28: 7c 01 12 8a lvexwx v0,r1,r2
++ 2c: 7c 00 13 0a stvexbx v0,0,r2
++ 30: 7c 01 13 0a stvexbx v0,r1,r2
++ 34: 7c 00 13 4a stvexhx v0,0,r2
++ 38: 7c 01 13 4a stvexhx v0,r1,r2
++ 3c: 7c 00 13 8a stvexwx v0,0,r2
++ 40: 7c 01 13 8a stvexwx v0,r1,r2
++ 44: 7c 00 12 4e lvepx v0,0,r2
++ 48: 7c 01 12 4e lvepx v0,r1,r2
++ 4c: 7c 00 12 0e lvepxl v0,0,r2
++ 50: 7c 01 12 0e lvepxl v0,r1,r2
++ 54: 7c 00 16 4e stvepx v0,0,r2
++ 58: 7c 01 16 4e stvepx v0,r1,r2
++ 5c: 7c 00 16 0e stvepxl v0,0,r2
++ 60: 7c 01 16 0e stvepxl v0,r1,r2
++ 64: 7c 00 14 8a lvlx v0,0,r2
++ 68: 7c 01 14 8a lvlx v0,r1,r2
++ 6c: 7c 00 16 8a lvlxl v0,0,r2
++ 70: 7c 01 16 8a lvlxl v0,r1,r2
++ 74: 7c 00 14 4a lvrx v0,0,r2
++ 78: 7c 01 14 4a lvrx v0,r1,r2
++ 7c: 7c 00 16 4a lvrxl v0,0,r2
++ 80: 7c 01 16 4a lvrxl v0,r1,r2
++ 84: 7c 00 15 8a stvlx v0,0,r2
++ 88: 7c 01 15 8a stvlx v0,r1,r2
++ 8c: 7c 00 17 8a stvlxl v0,0,r2
++ 90: 7c 01 17 8a stvlxl v0,r1,r2
++ 94: 7c 00 15 4a stvrx v0,0,r2
++ 98: 7c 01 15 4a stvrx v0,r1,r2
++ 9c: 7c 00 17 4a stvrxl v0,0,r2
++ a0: 7c 01 17 4a stvrxl v0,r1,r2
++ a4: 7c 00 14 ca lvswx v0,0,r2
++ a8: 7c 01 14 ca lvswx v0,r1,r2
++ ac: 7c 00 16 ca lvswxl v0,0,r2
++ b0: 7c 01 16 ca lvswxl v0,r1,r2
++ b4: 7c 00 15 ca stvswx v0,0,r2
++ b8: 7c 01 15 ca stvswx v0,r1,r2
++ bc: 7c 00 17 ca stvswxl v0,0,r2
++ c0: 7c 01 17 ca stvswxl v0,r1,r2
++ c4: 7c 00 16 0a lvsm v0,0,r2
++ c8: 7c 01 16 0a lvsm v0,r1,r2
++ cc: 7f 5a d3 78 miso
++ d0: 7c 00 04 ac sync
++ d4: 7c 00 04 ac sync
++ d8: 7c 20 04 ac lwsync
++ dc: 7c 00 04 ac sync
++ e0: 7c 07 04 ac sync 0,7
++ e4: 7c 28 04 ac sync 1,8
++ e8: 7c 00 00 c3 dni 0,0
++ ec: 7f ff 00 c3 dni 31,31
++ f0: 7c 40 0b 4d dcblq. 2,0,r1
++ f4: 7c 43 0b 4d dcblq. 2,r3,r1
++ f8: 7c 40 09 8d icblq. 2,0,r1
++ fc: 7c 43 09 8d icblq. 2,r3,r1
++ 100: 7c 10 02 dc mftmr r0,16
++ 104: 7c 10 03 dc mttmr 16,r0
+diff -ruN binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/e6500.s binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/e6500.s
+--- binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/e6500.s 1969-12-31 18:00:00.000000000 -0600
++++ binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/e6500.s 2011-05-03 16:35:30.724819687 -0500
+@@ -0,0 +1,69 @@
++# Power E6500 tests
++ .section ".text"
++start:
++ vabsdub 0, 1, 2
++ vabsduh 0, 1, 2
++ vabsduw 0, 1, 2
++ mvidsplt 0, 1, 2
++ mviwsplt 0, 1, 2
++ lvexbx 0, 0, 2
++ lvexbx 0, 1, 2
++ lvexhx 0, 0, 2
++ lvexhx 0, 1, 2
++ lvexwx 0, 0, 2
++ lvexwx 0, 1, 2
++ stvexbx 0, 0, 2
++ stvexbx 0, 1, 2
++ stvexhx 0, 0, 2
++ stvexhx 0, 1, 2
++ stvexwx 0, 0, 2
++ stvexwx 0, 1, 2
++ lvepx 0, 0, 2
++ lvepx 0, 1, 2
++ lvepxl 0, 0, 2
++ lvepxl 0, 1, 2
++ stvepx 0, 0, 2
++ stvepx 0, 1, 2
++ stvepxl 0, 0, 2
++ stvepxl 0, 1, 2
++ lvlx 0, 0, 2
++ lvlx 0, 1, 2
++ lvlxl 0, 0, 2
++ lvlxl 0, 1, 2
++ lvrx 0, 0, 2
++ lvrx 0, 1, 2
++ lvrxl 0, 0, 2
++ lvrxl 0, 1, 2
++ stvlx 0, 0, 2
++ stvlx 0, 1, 2
++ stvlxl 0, 0, 2
++ stvlxl 0, 1, 2
++ stvrx 0, 0, 2
++ stvrx 0, 1, 2
++ stvrxl 0, 0, 2
++ stvrxl 0, 1, 2
++ lvswx 0, 0, 2
++ lvswx 0, 1, 2
++ lvswxl 0, 0, 2
++ lvswxl 0, 1, 2
++ stvswx 0, 0, 2
++ stvswx 0, 1, 2
++ stvswxl 0, 0, 2
++ stvswxl 0, 1, 2
++ lvsm 0, 0, 2
++ lvsm 0, 1, 2
++ miso
++ sync
++ sync 0,0
++ sync 1,0
++ sync 2,0
++ sync 3,7
++ sync 3,8
++ dni 0,0
++ dni 31,31
++ dcblq. 2,0,1
++ dcblq. 2,3,1
++ icblq. 2,0,1
++ icblq. 2,3,1
++ mftmr 0,16
++ mttmr 16,0
+diff -ruN binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/ppc.exp binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/ppc.exp
+--- binutils-2.21-20110211-e5500/gas/testsuite/gas/ppc/ppc.exp 2010-02-07 19:59:38.000000000 -0600
++++ binutils-2.21-20110211-e6500/gas/testsuite/gas/ppc/ppc.exp 2011-05-03 16:04:15.297067070 -0500
+@@ -42,6 +42,7 @@
+ run_list_test "range" "-a32"
+ run_dump_test "ppc750ps"
+ run_dump_test "e500mc"
++ run_dump_test "e6500"
+ run_dump_test "a2"
+ run_dump_test "cell"
+ run_dump_test "common"
+diff -ruN binutils-2.21-20110211-e5500/include/opcode/ppc.h binutils-2.21-20110211-e6500/include/opcode/ppc.h
+--- binutils-2.21-20110211-e5500/include/opcode/ppc.h 2010-07-03 01:51:53.000000000 -0500
++++ binutils-2.21-20110211-e6500/include/opcode/ppc.h 2011-05-03 16:04:15.298069340 -0500
+@@ -174,6 +174,15 @@
+ /* Opcode which is supported by the e500 family */
+ #define PPC_OPCODE_E500 0x100000000ull
+
++/* Opcode is supported by Extended Altivec Vector Unit */
++#define PPC_OPCODE_ALTIVEC2 0x200000000ull
++
++/* Opcode is supported by Power E6500 */
++#define PPC_OPCODE_E6500 0x400000000ull
++
++/* Opcode is supported by Thread management APU */
++#define PPC_OPCODE_TMR 0x800000000ull
++
+ /* A macro to extract the major opcode from an instruction. */
+ #define PPC_OP(i) (((i) >> 26) & 0x3f)
+ \f
+diff -ruN binutils-2.21-20110211-e5500/opcodes/ppc-dis.c binutils-2.21-20110211-e6500/opcodes/ppc-dis.c
+--- binutils-2.21-20110211-e5500/opcodes/ppc-dis.c 2011-05-03 16:04:03.862065832 -0500
++++ binutils-2.21-20110211-e6500/opcodes/ppc-dis.c 2011-05-03 16:04:15.300067851 -0500
+@@ -120,6 +120,12 @@
+ | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
+ | PPC_OPCODE_POWER7),
+ 0 },
++ { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
++ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
++ | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
++ | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4
++ | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
++ 0 },
+ { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
+ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
+diff -ruN binutils-2.21-20110211-e5500/opcodes/ppc-opc.c binutils-2.21-20110211-e6500/opcodes/ppc-opc.c
+--- binutils-2.21-20110211-e5500/opcodes/ppc-opc.c 2011-02-11 10:58:12.000000000 -0600
++++ binutils-2.21-20110211-e6500/opcodes/ppc-opc.c 2011-05-03 17:22:20.260813917 -0500
+@@ -53,6 +53,7 @@
+ static long extract_boe (unsigned long, ppc_cpu_t, int *);
+ static unsigned long insert_fxm (unsigned long, long, ppc_cpu_t, const char **);
+ static long extract_fxm (unsigned long, ppc_cpu_t, int *);
++static unsigned long insert_ls (unsigned long, long, ppc_cpu_t, const char **);
+ static unsigned long insert_mbe (unsigned long, long, ppc_cpu_t, const char **);
+ static long extract_mbe (unsigned long, ppc_cpu_t, int *);
+ static unsigned long insert_mb6 (unsigned long, long, ppc_cpu_t, const char **);
+@@ -450,6 +451,7 @@
+ lower 5 bits are stored in the upper 5 and vice- versa. */
+ #define SPR SISIGNOPT + 1
+ #define PMR SPR
++#define TMR SPR
+ #define SPR_MASK (0x3ff << 11)
+ { 0x3ff, 11, insert_spr, extract_spr, 0 },
+
+@@ -472,8 +474,12 @@
+ #define T STRM
+ { 0x3, 21, NULL, NULL, 0 },
+
++ /* The ESYNC field in an X (sync) form instruction. */
++#define ESYNC STRM + 1
++ { 0xf, 16, insert_ls, NULL, PPC_OPERAND_OPTIONAL },
++
+ /* The SV field in a POWER SC form instruction. */
+-#define SV STRM + 1
++#define SV ESYNC + 1
+ { 0x3fff, 2, NULL, NULL, 0 },
+
+ /* The TBR field in an XFX form instruction. This is like the SPR
+@@ -515,6 +521,7 @@
+
+ /* The UIMM field in a VX form instruction. */
+ #define UIMM SIMM + 1
++#define DCTL UIMM
+ { 0x1f, 16, NULL, NULL, 0 },
+
+ /* The SHB field in a VA form instruction. */
+@@ -996,6 +1003,32 @@
+ return mask;
+ }
+
++/* The LS field in a sync instruction that accepts 2 operands
++ Values 2 and 3 are reserved,
++ must be treated as 0 for future compatibility
++ Values 0 and 1 can be accepted, if field ESYNC is zero
++ Otherwise L = complement of ESYNC-bit2 (1<<18) */
++
++static unsigned long
++insert_ls (unsigned long insn,
++ long value,
++ ppc_cpu_t dialect ATTRIBUTE_UNUSED,
++ const char **errmsg ATTRIBUTE_UNUSED)
++{
++ unsigned long ls;
++
++ ls = (insn >> 21) & 0x03;
++ if (value == 0)
++ {
++ if (ls > 1)
++ return insn & ~(0x3 << 21);
++ return insn;
++ }
++ if ((value & 0x2) != 0)
++ return (insn & ~(0x3 << 21)) | ((value & 0xf) << 16);
++ return (insn & ~(0x3 << 21)) | (0x1 << 21) | ((value & 0xf) << 16);
++}
++
+ /* The MB and ME fields in an M form instruction expressed as a single
+ operand which is itself a bitmask. The extraction function always
+ marks it as invalid, since we never want to recognize an
+@@ -1728,6 +1761,9 @@
+ /* An X form sync instruction with everything filled in except the LS field. */
+ #define XSYNC_MASK (0xff9fffff)
+
++/* An X form sync instruction with everything filled in except the L and E fields. */
++#define XSYNCLE_MASK (0xff90ffff)
++
+ /* An X_MASK, but with the EH bit clear. */
+ #define XEH_MASK (X_MASK & ~((unsigned long )1))
+
+@@ -1922,6 +1958,7 @@
+ #define PPC860 PPC
+ #define PPCPS PPC_OPCODE_PPCPS
+ #define PPCVEC PPC_OPCODE_ALTIVEC
++#define PPCVEC2 PPC_OPCODE_ALTIVEC2
+ #define PPCVSX PPC_OPCODE_VSX
+ #define POWER PPC_OPCODE_POWER
+ #define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2
+@@ -1940,6 +1977,7 @@
+ #define PPCEFS PPC_OPCODE_EFS
+ #define PPCBRLK PPC_OPCODE_BRLOCK
+ #define PPCPMR PPC_OPCODE_PMR
++#define PPCTMR PPC_OPCODE_TMR
+ #define PPCCHLK PPC_OPCODE_CACHELCK
+ #define PPCRFMCI PPC_OPCODE_RFMCI
+ #define E500MC PPC_OPCODE_E500MC
+@@ -1947,6 +1985,7 @@
+ #define TITAN PPC_OPCODE_TITAN
+ #define MULHW PPC_OPCODE_405 | PPC_OPCODE_440 | TITAN
+ #define E500 PPC_OPCODE_E500
++#define E6500 PPC_OPCODE_E6500
+ \f
+ /* The opcode table.
+
+@@ -2112,12 +2151,14 @@
+ {"machhwsu", XO (4, 76,0,0),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"machhwsu.", XO (4, 76,0,1),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"ps_cmpo1", X (4, 96), X_MASK|(3<<21), PPCPS, PPCNONE, {BF, FRA, FRB}},
++{"vabsdub", VX (4, 192), VX_MASK, PPCVEC2, PPCNONE, {VD, VA, VB}},
+ {"vcmpeqfp", VXR(4, 198,0), VXR_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"vpkuwus", VX (4, 206), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"machhws", XO (4, 108,0,0),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"machhws.", XO (4, 108,0,1),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"nmachhws", XO (4, 110,0,0),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"nmachhws.", XO (4, 110,0,1),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
++{"vabsduh", VX (4, 256), VX_MASK, PPCVEC2, PPCNONE, {VD, VA, VB}},
+ {"vmaxsb", VX (4, 258), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"vslb", VX (4, 260), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"vmulosb", VX (4, 264), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+@@ -2130,6 +2171,7 @@
+ {"mulchwu.", XRC(4, 136,1), X_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"macchwu", XO (4, 140,0,0),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
+ {"macchwu.", XO (4, 140,0,1),XO_MASK, MULHW, PPCNONE, {RT, RA, RB}},
++{"vabsduw", VX (4, 320), VX_MASK, PPCVEC2, PPCNONE, {VD, VA, VB}},
+ {"vmaxsh", VX (4, 322), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"vslh", VX (4, 324), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+ {"vmulosh", VX (4, 328), VX_MASK, PPCVEC, PPCNONE, {VD, VA, VB}},
+@@ -3613,6 +3655,8 @@
+
+ {"lbepx", X(31,95), X_MASK, E500MC|PPCA2, PPCNONE, {RT, RA, RB}},
+
++{"dni", XRC(31,97,1), XRB_MASK, E6500, PPCNONE, {DUI, DCTL}},
++
+ {"lvx", X(31,103), X_MASK, PPCVEC, PPCNONE, {VD, RA, RB}},
+ {"lqfcmx", APU(31,103,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+@@ -3622,6 +3666,8 @@
+ {"mul", XO(31,107,0,0), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+ {"mul.", XO(31,107,0,1), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+
++{"mvidsplt", X(31,110), X_MASK, PPCVEC2, PPCNONE, {VD, RA, RB}},
++
+ {"mtsrdin", X(31,114), XRA_MASK, PPC64, PPCNONE, {RS, RB}},
+
+ {"lharx", X(31,116), XEH_MASK, POWER7, PPCNONE, {RT, RA0, RB, EH}},
+@@ -3656,6 +3702,8 @@
+ {"adde.", XO(31,138,0,1), XO_MASK, PPCCOM, PPCNONE, {RT, RA, RB}},
+ {"ae.", XO(31,138,0,1), XO_MASK, PWRCOM, PPCNONE, {RT, RA, RB}},
+
++{"mviwsplt", X(31,142), X_MASK, PPCVEC2, PPCNONE, {VD, RA, RB}},
++
+ {"dcbtstlse", X(31,142), X_MASK, PPCCHLK, PPCNONE, {CT, RA, RB}},
+
+ {"mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, PPCNONE, {RS}},
+@@ -3711,6 +3759,8 @@
+
+ {"prtyd", X(31,186), XRB_MASK, POWER6|PPCA2, PPCNONE, {RA, RS}},
+
++{"icblq.", XRC(31,198,1), X_MASK, E6500, PPCNONE, {CT, RA0, RB}},
++
+ {"stvewx", X(31,199), X_MASK, PPCVEC, PPCNONE, {VS, RA, RB}},
+ {"stwfcmx", APU(31,199,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+@@ -3788,8 +3838,12 @@
+ {"mfdcrx", X(31,259), X_MASK, BOOKE|PPCA2|PPC476, TITAN, {RS, RA}},
+ {"mfdcrx.", XRC(31,259,1), X_MASK, PPCA2, PPCNONE, {RS, RA}},
+
++{"lvexbx", X(31,261), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"icbt", X(31,262), XRT_MASK, PPC403, PPCNONE, {RA, RB}},
+
++{"lvepxl", X(31,263), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"ldfcmx", APU(31,263,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+ {"doz", XO(31,264,0,0), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+ {"doz.", XO(31,264,0,1), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+@@ -3823,6 +3877,9 @@
+
+ {"mfdcrux", X(31,291), X_MASK, PPC464, PPCNONE, {RS, RA}},
+
++{"lvexhx", X(31,293), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++{"lvepx", X(31,295), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"tlbie", X(31,306), XRTLRA_MASK, PPC, TITAN, {RB, L}},
+ {"tlbi", X(31,306), XRT_MASK, POWER, PPCNONE, {RA0, RB}},
+
+@@ -3874,6 +3931,8 @@
+ {"mfdcr", X(31,323), X_MASK, PPC403|BOOKE|PPCA2|PPC476, TITAN, {RT, SPR}},
+ {"mfdcr.", XRC(31,323,1), X_MASK, PPCA2, PPCNONE, {RT, SPR}},
+
++{"lvexwx", X(31,325), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"dcread", X(31,326), X_MASK, PPC476|TITAN, PPCNONE, {RT, RA, RB}},
+
+ {"div", XO(31,331,0,0), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+@@ -3882,6 +3941,7 @@
+ {"lxvdsx", X(31,332), XX1_MASK, PPCVSX, PPCNONE, {XT6, RA, RB}},
+
+ {"mfpmr", X(31,334), X_MASK, PPCPMR|PPCE300, PPCNONE, {RT, PMR}},
++{"mftmr", X(31,366), X_MASK, PPCTMR|E6500, PPCNONE, {RT, TMR}},
+
+ {"mfmq", XSPR(31,339, 0), XSPR_MASK, M601, PPCNONE, {RT}},
+ {"mfxer", XSPR(31,339, 1), XSPR_MASK, COM, PPCNONE, {RT}},
+@@ -4112,6 +4172,8 @@
+ {"mtdcrx", X(31,387), X_MASK, BOOKE|PPCA2|PPC476, TITAN, {RA, RS}},
+ {"mtdcrx.", XRC(31,387,1), X_MASK, PPCA2, PPCNONE, {RA, RS}},
+
++{"stvexbx", X(31,389), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"dcblc", X(31,390), X_MASK, PPCCHLK|PPC476|TITAN, PPCNONE, {CT, RA, RB}},
+ {"stdfcmx", APU(31,391,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+@@ -4136,6 +4198,10 @@
+
+ {"mtdcrux", X(31,419), X_MASK, PPC464, PPCNONE, {RA, RS}},
+
++{"stvexhx", X(31,421), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
++{"dcblq.", XRC(31,422,1), X_MASK, E6500, PPCNONE, {CT, RA0, RB}},
++
+ {"divde", XO(31,425,0,0), XO_MASK, POWER7|PPCA2, PPCNONE, {RT, RA, RB}},
+ {"divde.", XO(31,425,0,1), XO_MASK, POWER7|PPCA2, PPCNONE, {RT, RA, RB}},
+ {"divwe", XO(31,427,0,0), XO_MASK, POWER7|PPCA2, PPCNONE, {RT, RA, RB}},
+@@ -4149,6 +4215,8 @@
+
+ {"mdors", 0x7f9ce378, 0xffffffff, E500MC, PPCNONE, {0}},
+
++{"miso", 0x7f5ad378, 0xffffffff, E6500, PPCNONE, {0}},
++
+ {"mr", XRC(31,444,0), X_MASK, COM, PPCNONE, {RA, RS, RBS}},
+ {"or", XRC(31,444,0), X_MASK, COM, PPCNONE, {RA, RS, RB}},
+ {"mr.", XRC(31,444,1), X_MASK, COM, PPCNONE, {RA, RS, RBS}},
+@@ -4191,6 +4259,8 @@
+ {"mtdcr", X(31,451), X_MASK, PPC403|BOOKE|PPCA2|PPC476, TITAN, {SPR, RS}},
+ {"mtdcr.", XRC(31,451,1), X_MASK, PPCA2, PPCNONE, {SPR, RS}},
+
++{"stvexwx", X(31,453), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"dccci", X(31,454), XRT_MASK, PPC403|PPC440|TITAN|PPCA2, PPCNONE, {RAOPT, RBOPT}},
+ {"dci", X(31,454), XRARB_MASK, PPCA2|PPC476, PPCNONE, {CT}},
+
+@@ -4201,6 +4271,7 @@
+ {"divwu.", XO(31,459,0,1), XO_MASK, PPC, PPCNONE, {RT, RA, RB}},
+
+ {"mtpmr", X(31,462), X_MASK, PPCPMR|PPCE300, PPCNONE, {PMR, RS}},
++{"mttmr", X(31,494), X_MASK, PPCTMR|E6500, PPCNONE, {TMR, RS}},
+
+ {"mtmq", XSPR(31,467, 0), XSPR_MASK, M601, PPCNONE, {RS}},
+ {"mtxer", XSPR(31,467, 1), XSPR_MASK, COM, PPCNONE, {RS}},
+@@ -4445,6 +4516,8 @@
+
+ {"lhdx", X(31,547), X_MASK, E500MC, PPCNONE, {RT, RA, RB}},
+
++{"lvrx", X(31,549), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"bbelr", X(31,550), X_MASK, PPCBRLK, PPCNONE, {0}},
+
+ {"lvrx", X(31,551), X_MASK, CELL, PPCNONE, {VD, RA0, RB}},
+@@ -4461,6 +4534,8 @@
+
+ {"lwdx", X(31,579), X_MASK, E500MC, PPCNONE, {RT, RA, RB}},
+
++{"lvlx", X(31,581), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"lwfcmux", APU(31,583,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+ {"lxsdx", X(31,588), XX1_MASK, PPCVSX, PPCNONE, {XT6, RA, RB}},
+@@ -4472,9 +4547,10 @@
+
+ {"lwsync", XSYNC(31,598,1), 0xffffffff, PPC, E500, {0}},
+ {"ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, PPCNONE, {0}},
++{"sync", X(31,598), XSYNCLE_MASK,E6500, PPCNONE, {LS, ESYNC}},
+ {"sync", X(31,598), XSYNC_MASK, PPCCOM, BOOKE|PPC476, {LS}},
+ {"msync", X(31,598), 0xffffffff, BOOKE|PPCA2|PPC476, PPCNONE, {0}},
+-{"sync", X(31,598), 0xffffffff, BOOKE|PPC476, PPCNONE, {0}},
++{"sync", X(31,598), 0xffffffff, BOOKE|PPC476, E6500, {0}},
+ {"lwsync", X(31,598), 0xffffffff, E500, PPCNONE, {0}},
+ {"dcs", X(31,598), 0xffffffff, PWRCOM, PPCNONE, {0}},
+
+@@ -4485,6 +4561,8 @@
+
+ {"lddx", X(31,611), X_MASK, E500MC, PPCNONE, {RT, RA, RB}},
+
++{"lvswx", X(31,613), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"lqfcmux", APU(31,615,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+ {"nego", XO(31,104,1,0), XORB_MASK, COM, PPCNONE, {RT, RA}},
+@@ -4534,6 +4612,8 @@
+
+ {"sthdx", X(31,675), X_MASK, E500MC, PPCNONE, {RS, RA, RB}},
+
++{"stvrx", X(31,677), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"stvrx", X(31,679), X_MASK, CELL, PPCNONE, {VS, RA0, RB}},
+ {"sthfcmux", APU(31,679,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+@@ -4546,6 +4626,8 @@
+
+ {"stwdx", X(31,707), X_MASK, E500MC, PPCNONE, {RS, RA, RB}},
+
++{"stvlx", X(31,709), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"stwfcmux", APU(31,711,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+ {"stxsdx", X(31,716), XX1_MASK, PPCVSX, PPCNONE, {XS6, RA, RB}},
+@@ -4578,6 +4660,8 @@
+
+ {"stddx", X(31,739), X_MASK, E500MC, PPCNONE, {RS, RA, RB}},
+
++{"stvswx", X(31,741), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"stqfcmux", APU(31,743,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+ {"subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, PPCNONE, {RT, RA}},
+@@ -4606,6 +4690,8 @@
+ {"srliq", XRC(31,760,0), X_MASK, M601, PPCNONE, {RA, RS, SH}},
+ {"srliq.", XRC(31,760,1), X_MASK, M601, PPCNONE, {RA, RS, SH}},
+
++{"lvsm", X(31,773), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++{"stvepxl", X(31,775), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
+ {"lvlxl", X(31,775), X_MASK, CELL, PPCNONE, {VD, RA0, RB}},
+ {"ldfcmux", APU(31,775,0), APU_MASK, PPC405, PPCNONE, {FCRT, RA, RB}},
+
+@@ -4638,6 +4724,8 @@
+
+ {"lfddx", X(31,803), X_MASK, E500MC, PPCNONE, {FRT, RA, RB}},
+
++{"lvrxl", X(31,805), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++{"stvepx", X(31,807), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
+ {"lvrxl", X(31,807), X_MASK, CELL, PPCNONE, {VD, RA0, RB}},
+
+ {"rac", X(31,818), X_MASK, M601, PPCNONE, {RT, RA, RB}},
+@@ -4658,6 +4746,8 @@
+ {"sradi", XS(31,413,0), XS_MASK, PPC64, PPCNONE, {RA, RS, SH6}},
+ {"sradi.", XS(31,413,1), XS_MASK, PPC64, PPCNONE, {RA, RS, SH6}},
+
++{"lvlxl", X(31,837), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"divo", XO(31,331,1,0), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+ {"divo.", XO(31,331,1,1), XO_MASK, M601, PPCNONE, {RT, RA, RB}},
+
+@@ -4676,6 +4766,8 @@
+
+ {"lfiwax", X(31,855), X_MASK, POWER6|PPCA2|PPC476, PPCNONE, {FRT, RA0, RB}},
+
++{"lvswxl", X(31,869), X_MASK, PPCVEC2, PPCNONE, {VD, RA0, RB}},
++
+ {"abso", XO(31,360,1,0), XORB_MASK, M601, PPCNONE, {RT, RA}},
+ {"abso.", XO(31,360,1,1), XORB_MASK, M601, PPCNONE, {RT, RA}},
+
+@@ -4721,6 +4813,8 @@
+
+ {"stfddx", X(31,931), X_MASK, E500MC, PPCNONE, {FRS, RA, RB}},
+
++{"stvrxl", X(31,933), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"wclrone", XOPL2(31,934,2),XRT_MASK, PPCA2, PPCNONE, {RA0, RB}},
+ {"wclrall", X(31,934), XRARB_MASK, PPCA2, PPCNONE, {L}},
+ {"wclr", X(31,934), X_MASK, PPCA2, PPCNONE, {L, RA0, RB}},
+@@ -4749,6 +4843,8 @@
+ {"extsb", XRC(31,954,0), XRB_MASK, PPC, PPCNONE, {RA, RS}},
+ {"extsb.", XRC(31,954,1), XRB_MASK, PPC, PPCNONE, {RA, RS}},
+
++{"stvlxl", X(31,965), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"iccci", X(31,966), XRT_MASK, PPC403|PPC440|TITAN|PPCA2, PPCNONE, {RAOPT, RBOPT}},
+ {"ici", X(31,966), XRARB_MASK, PPCA2|PPC476, PPCNONE, {CT}},
+
+@@ -4776,6 +4872,8 @@
+
+ {"icbiep", XRT(31,991,0), XRT_MASK, E500MC|PPCA2, PPCNONE, {RA, RB}},
+
++{"stvswxl", X(31,997), X_MASK, PPCVEC2, PPCNONE, {VS, RA0, RB}},
++
+ {"icread", X(31,998), XRT_MASK, PPC403|PPC440|PPC476|TITAN, PPCNONE, {RA, RB}},
+
+ {"nabso", XO(31,488,1,0), XORB_MASK, M601, PPCNONE, {RT, RA}},
--- /dev/null
+SRC_URI = "svn://www.eglibc.org/svn/branches/;module=${EGLIBC_BRANCH};proto=http \
+ file://glibc.undefined_static.patch \
+ file://glibc.fixgcc4.6.patch \
+ file://glibc.readv_proto.patch \
+ file://glibc.fix_sqrt.patch \
+ file://glibc.fix_prof.patch \
+ file://glibc.e500mc_subspecies_of_powerpc_is_not_supported.patch \
+ file://etc/ld.so.conf \
+ file://generate-supported.mk \
+"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+PR .= "+${DISTRO}.0"
--- /dev/null
+require eglibc-fsl.inc
--- /dev/null
+require eglibc-fsl.inc
--- /dev/null
+require eglibc-fsl.inc
--- /dev/null
+#!/usr/bin/make
+
+include $(IN)
+
+all:
+ rm -f $(OUT)
+ touch $(OUT)
+ for locale in $(SUPPORTED-LOCALES); do \
+ [ $$locale = true ] && continue; \
+ echo $$locale | sed 's,/, ,' >> $(OUT); \
+ done
--- /dev/null
+--- a/configure 2012-03-05 07:00:49.600200254 -0600
++++ b/configure 2012-03-05 07:01:13.249394037 -0600
+@@ -4581,7 +4581,7 @@
+ if test -z "$submachine_used" && test -n "$submachine"; then
+ { { $as_echo "$as_me:$LINENO: error: The $submachine subspecies of $host_cpu is not supported." >&5
+ $as_echo "$as_me: error: The $submachine subspecies of $host_cpu is not supported." >&2;}
+- { (exit 1); exit 1; }; }
++ }
+ fi
+
+
--- /dev/null
+diff -ruN libc-orig/elf/dl-runtime.c libc-e5500/elf/dl-runtime.c
+--- libc-orig/elf/dl-runtime.c 2011-12-08 04:25:09.201995061 -0600
++++ libc-e5500/elf/dl-runtime.c 2011-12-08 04:26:12.760996794 -0600
+@@ -156,7 +156,7 @@
+ }
+ #endif
+
+-#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
++#if !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
+ DL_FIXUP_VALUE_TYPE
+ __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+ _dl_profile_fixup (
+@@ -425,7 +425,7 @@
+ return value;
+ }
+
+-#endif /* PROF && ELF_MACHINE_NO_PLT */
++#endif /* ELF_MACHINE_NO_PLT */
+
+
+ #include <stdio.h>
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/dl-trampoline.S libc-e5500/sysdeps/powerpc/powerpc32/dl-trampoline.S
+--- libc-orig/sysdeps/powerpc/powerpc32/dl-trampoline.S 2011-12-08 04:25:12.103998210 -0600
++++ libc-e5500/sysdeps/powerpc/powerpc32/dl-trampoline.S 2011-12-08 04:26:19.310748350 -0600
+@@ -71,7 +71,6 @@
+ cfi_endproc
+ .size _dl_runtime_resolve,.-_dl_runtime_resolve
+
+-#ifndef PROF
+ .align 2
+ .globl _dl_prof_resolve
+ .type _dl_prof_resolve,@function
+@@ -183,4 +182,4 @@
+ bctr
+ cfi_endproc
+ .size _dl_prof_resolve,.-_dl_prof_resolve
+-#endif
++
--- /dev/null
+Implements sqrt with fsqrte.
+Adds functions for 603e (also used for e300c3, e600 and e500mc)
+Adds functions for e5500 in 64 bit mode (also used for e6500)
+
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c libc-e5500/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrt.c 2011-05-18 13:00:40.423986787 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++ Copyright (C) 2010 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++ We find the actual square root and half of its reciprocal
++ simultaneously. */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++ double b;
++#endif
++{
++ if (__builtin_expect (b > 0, 1))
++ {
++ double y, g, h, d, r;
++ ieee_double_shape_type u;
++
++ if (__builtin_expect (b != a_inf.value, 1))
++ {
++ fenv_t fe;
++
++ fe = fegetenv_register ();
++
++ u.value = b;
++
++ relax_fenv_state ();
++
++ __asm__ ("frsqrte %[estimate], %[x]\n"
++ : [estimate] "=f" (y) : [x] "f" (b));
++
++ /* Following Muller et al, page 168, equation 5.20.
++
++ h goes to 1/(2*sqrt(b))
++ g goes to sqrt(b).
++
++ We need three iterations to get within 1ulp. */
++
++ /* Indicate that these can be performed prior to the branch. GCC
++ insists on sinking them below the branch, however; it seems like
++ they'd be better before the branch so that we can cover any latency
++ from storing the argument and loading its high word. Oh well. */
++
++ g = b * y;
++ h = 0.5 * y;
++
++ /* Handle small numbers by scaling. */
++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++ return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++#define FNMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */
++
++ /* Final refinement. */
++ d = FNMSUB (g, g, b);
++
++ fesetenv_register (fe);
++ return FMADD (d, h, g);
++ }
++ }
++ else if (b < 0)
++ {
++ /* For some reason, some PowerPC32 processors don't implement
++ FE_INVALID_SQRT. */
++#ifdef FE_INVALID_SQRT
++ feraiseexcept (FE_INVALID_SQRT);
++
++ fenv_union_t u = { .fenv = fegetenv_register () };
++ if ((u.l[1] & FE_INVALID) == 0)
++#endif
++ feraiseexcept (FE_INVALID);
++ b = a_nan.value;
++ }
++ return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c libc-e5500/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/powerpc/powerpc32/603e/fpu/e_sqrtf.c 2011-05-18 13:00:40.423986787 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++ Copyright (C) 2010 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++ We find the reciprocal square root and use that to compute the actual
++ square root. */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++ float b;
++#endif
++{
++ if (__builtin_expect (b > 0, 1))
++ {
++#define FMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++#define FNMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++
++ if (__builtin_expect (b != a_inf.value, 1))
++ {
++ double y, x;
++ fenv_t fe;
++
++ fe = fegetenv_register ();
++
++ relax_fenv_state ();
++
++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */
++ y = FMSUB (threehalf, b, b);
++
++ /* Initial estimate. */
++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */
++ x = x * FNMSUB (y, x * x, threehalf);
++ x = x * FNMSUB (y, x * x, threehalf);
++ x = x * FNMSUB (y, x * x, threehalf);
++
++ /* All done. */
++ fesetenv_register (fe);
++ return x * b;
++ }
++ }
++ else if (b < 0)
++ {
++ /* For some reason, some PowerPC32 processors don't implement
++ FE_INVALID_SQRT. */
++#ifdef FE_INVALID_SQRT
++ feraiseexcept (FE_INVALID_SQRT);
++
++ fenv_union_t u = { .fenv = fegetenv_register () };
++ if ((u.l[1] & FE_INVALID) == 0)
++#endif
++ feraiseexcept (FE_INVALID);
++ b = a_nan.value;
++ }
++ return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c libc-e5500/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrt.c 2011-05-18 11:15:22.467987000 -0500
+@@ -0,0 +1,134 @@
++/* Double-precision floating point square root.
++ Copyright (C) 2010 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float two108 = 3.245185536584267269e+32;
++static const float twom54 = 5.551115123125782702e-17;
++static const float half = 0.5;
++
++/* The method is based on the descriptions in:
++
++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++ We find the actual square root and half of its reciprocal
++ simultaneously. */
++
++#ifdef __STDC__
++double
++__ieee754_sqrt (double b)
++#else
++double
++__ieee754_sqrt (b)
++ double b;
++#endif
++{
++ if (__builtin_expect (b > 0, 1))
++ {
++ double y, g, h, d, r;
++ ieee_double_shape_type u;
++
++ if (__builtin_expect (b != a_inf.value, 1))
++ {
++ fenv_t fe;
++
++ fe = fegetenv_register ();
++
++ u.value = b;
++
++ relax_fenv_state ();
++
++ __asm__ ("frsqrte %[estimate], %[x]\n"
++ : [estimate] "=f" (y) : [x] "f" (b));
++
++ /* Following Muller et al, page 168, equation 5.20.
++
++ h goes to 1/(2*sqrt(b))
++ g goes to sqrt(b).
++
++ We need three iterations to get within 1ulp. */
++
++ /* Indicate that these can be performed prior to the branch. GCC
++ insists on sinking them below the branch, however; it seems like
++ they'd be better before the branch so that we can cover any latency
++ from storing the argument and loading its high word. Oh well. */
++
++ g = b * y;
++ h = 0.5 * y;
++
++ /* Handle small numbers by scaling. */
++ if (__builtin_expect ((u.parts.msw & 0x7ff00000) <= 0x02000000, 0))
++ return __ieee754_sqrt (b * two108) * twom54;
++
++#define FMADD(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fmadd %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++#define FNMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ r = FNMSUB (g, h, half);
++ g = FMADD (g, r, g);
++ h = FMADD (h, r, h);
++
++ /* g is now +/- 1ulp, or exactly equal to, the square root of b. */
++
++ /* Final refinement. */
++ d = FNMSUB (g, g, b);
++
++ fesetenv_register (fe);
++ return FMADD (d, h, g);
++ }
++ }
++ else if (b < 0)
++ {
++ /* For some reason, some PowerPC32 processors don't implement
++ FE_INVALID_SQRT. */
++#ifdef FE_INVALID_SQRT
++ feraiseexcept (FE_INVALID_SQRT);
++
++ fenv_union_t u = { .fenv = fegetenv_register () };
++ if ((u.l[1] & FE_INVALID) == 0)
++#endif
++ feraiseexcept (FE_INVALID);
++ b = a_nan.value;
++ }
++ return f_wash (b);
++}
+diff -ruN libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c libc-e5500/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c
+--- libc-orig/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/powerpc/powerpc64/e5500/fpu/e_sqrtf.c 2011-05-18 11:15:22.467987000 -0500
+@@ -0,0 +1,101 @@
++/* Single-precision floating point square root.
++ Copyright (C) 2010 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, write to the Free
++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++ 02111-1307 USA. */
++
++#include <math.h>
++#include <math_private.h>
++#include <fenv_libc.h>
++#include <inttypes.h>
++
++#include <sysdep.h>
++#include <ldsodefs.h>
++
++static const ieee_float_shape_type a_nan = {.word = 0x7fc00000 };
++static const ieee_float_shape_type a_inf = {.word = 0x7f800000 };
++static const float threehalf = 1.5;
++
++/* The method is based on the descriptions in:
++
++ _The Handbook of Floating-Pointer Arithmetic_ by Muller et al., chapter 5;
++ _IA-64 and Elementary Functions: Speed and Precision_ by Markstein, chapter 9
++
++ We find the reciprocal square root and use that to compute the actual
++ square root. */
++
++#ifdef __STDC__
++float
++__ieee754_sqrtf (float b)
++#else
++float
++__ieee754_sqrtf (b)
++ float b;
++#endif
++{
++ if (__builtin_expect (b > 0, 1))
++ {
++#define FMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++#define FNMSUB(a_, c_, b_) \
++ ({ double __r; \
++ __asm__ ("fnmsub %[r], %[a], %[c], %[b]\n" \
++ : [r] "=f" (__r) : [a] "f" (a_), [c] "f" (c_), [b] "f" (b_)); \
++ __r;})
++
++ if (__builtin_expect (b != a_inf.value, 1))
++ {
++ double y, x;
++ fenv_t fe;
++
++ fe = fegetenv_register ();
++
++ relax_fenv_state ();
++
++ /* Compute y = 1.5 * b - b. Uses fewer constants than y = 0.5 * b. */
++ y = FMSUB (threehalf, b, b);
++
++ /* Initial estimate. */
++ __asm__ ("frsqrte %[x], %[b]\n" : [x] "=f" (x) : [b] "f" (b));
++
++ /* Iterate. x_{n+1} = x_n * (1.5 - y * (x_n * x_n)). */
++ x = x * FNMSUB (y, x * x, threehalf);
++ x = x * FNMSUB (y, x * x, threehalf);
++ x = x * FNMSUB (y, x * x, threehalf);
++
++ /* All done. */
++ fesetenv_register (fe);
++ return x * b;
++ }
++ }
++ else if (b < 0)
++ {
++ /* For some reason, some PowerPC32 processors don't implement
++ FE_INVALID_SQRT. */
++#ifdef FE_INVALID_SQRT
++ feraiseexcept (FE_INVALID_SQRT);
++
++ fenv_union_t u = { .fenv = fegetenv_register () };
++ if ((u.l[1] & FE_INVALID) == 0)
++#endif
++ feraiseexcept (FE_INVALID);
++ b = a_nan.value;
++ }
++ return f_washf (b);
++}
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies libc-e5500/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/unix/sysv/linux/powerpc/powerpc32/603e/fpu/Implies 2011-05-18 13:01:33.987988922 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc32/603e/fpu
+diff -ruN libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies libc-e5500/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies
+--- libc-orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies 1969-12-31 18:00:00.000000000 -0600
++++ libc-e5500/sysdeps/unix/sysv/linux/powerpc/powerpc64/e5500/fpu/Implies 2011-05-18 11:15:22.412987000 -0500
+@@ -0,0 +1 @@
++powerpc/powerpc64/e5500/fpu
--- /dev/null
+glibc.fixgcc4.6
+
+Glibc build scripts relies on information given by "gcc -v --help".
+With gcc-4.6 and latter, this information is not printed with "--help"
+anymore, but with "--target-help". This patch should be used until
+glibs sources catches up with gcc.
+
+--- libc/configure.in-orig 2010-06-07 11:11:01.000000000 -0500
++++ libc/configure.in 2010-06-07 11:11:28.000000000 -0500
+@@ -1620,7 +1620,7 @@
+ AC_CACHE_CHECK(for -z relro option,
+ libc_cv_z_relro, [dnl
+ libc_cv_z_relro=no
+- if AC_TRY_COMMAND([${CC-cc} -v --help 2>&1|grep "z relro" 1>&AS_MESSAGE_LOG_FD])
++ if AC_TRY_COMMAND([${CC-cc} -v --target-help 2>&1|grep "z relro" 1>&AS_MESSAGE_LOG_FD])
+ then
+ if AC_TRY_COMMAND([${CC-cc} -Wl,--verbose 2>&1|grep DATA_SEGMENT_RELRO_END 1>&AS_MESSAGE_LOG_FD])
+ then
+--- libc/configure-orig 2010-06-07 11:11:13.000000000 -0500
++++ libc/configure 2010-06-07 11:12:00.000000000 -0500
+@@ -6670,7 +6670,7 @@
+ $as_echo_n "(cached) " >&6
+ else
+ libc_cv_z_relro=no
+- if { ac_try='${CC-cc} -v --help 2>&1|grep "z relro" 1>&5'
++ if { ac_try='${CC-cc} -v --target-help 2>&1|grep "z relro" 1>&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
--- /dev/null
+glibc.readv_proto
+
+Unfortunate choice of variable names. Causes syntax errors on Altivec
+enabled targets.
+
+diff -u libc-orig/sysdeps/unix/sysv/linux/readv.c libc/sysdeps/unix/sysv/linux/readv.c
+--- libc-orig/sysdeps/unix/sysv/linux/readv.c 2011-05-11 11:01:36.625600000 -0500
++++ libc/sysdeps/unix/sysv/linux/readv.c 2011-05-11 11:03:19.443599768 -0500
+@@ -40,20 +40,20 @@
+
+
+ ssize_t
+-__libc_readv (fd, vector, count)
++__libc_readv (fd, vec_tor, count)
+ int fd;
+- const struct iovec *vector;
++ const struct iovec *vec_tor;
+ int count;
+ {
+ ssize_t result;
+
+ if (SINGLE_THREAD_P)
+- result = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vector, count), count);
++ result = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vec_tor, count), count);
+ else
+ {
+ int oldtype = LIBC_CANCEL_ASYNC ();
+
+- result = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vector, count), count);
++ result = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vec_tor, count), count);
+
+ LIBC_CANCEL_RESET (oldtype);
+ }
+@@ -64,7 +64,7 @@
+ if (result >= 0 || errno != EINVAL || count <= UIO_FASTIOV)
+ return result;
+
+- return __atomic_readv_replacement (fd, vector, count);
++ return __atomic_readv_replacement (fd, vec_tor, count);
+ #endif
+ }
+ strong_alias (__libc_readv, __readv)
+diff -u libc-orig/sysdeps/unix/sysv/linux/writev.c libc/sysdeps/unix/sysv/linux/writev.c
+--- libc-orig/sysdeps/unix/sysv/linux/writev.c 2011-05-11 11:01:36.577599548 -0500
++++ libc/sysdeps/unix/sysv/linux/writev.c 2011-05-11 11:03:33.994599785 -0500
+@@ -40,20 +40,20 @@
+
+
+ ssize_t
+-__libc_writev (fd, vector, count)
++__libc_writev (fd, vec_tor, count)
+ int fd;
+- const struct iovec *vector;
++ const struct iovec *vec_tor;
+ int count;
+ {
+ ssize_t result;
+
+ if (SINGLE_THREAD_P)
+- result = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector, count), count);
++ result = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vec_tor, count), count);
+ else
+ {
+ int oldtype = LIBC_CANCEL_ASYNC ();
+
+- result = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector, count), count);
++ result = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vec_tor, count), count);
+
+ LIBC_CANCEL_RESET (oldtype);
+ }
+@@ -64,7 +64,7 @@
+ if (result >= 0 || errno != EINVAL || count <= UIO_FASTIOV)
+ return result;
+
+- return __atomic_writev_replacement (fd, vector, count);
++ return __atomic_writev_replacement (fd, vec_tor, count);
+ #endif
+ }
+ strong_alias (__libc_writev, __writev)
+diff -u libc-orig/include/sys/uio.h libc/include/sys/uio.h
+--- libc-orig/include/sys/uio.h 2011-05-11 11:07:53.953602501 -0500
++++ libc/include/sys/uio.h 2011-05-11 11:08:25.117599576 -0500
+@@ -2,12 +2,12 @@
+ #include <misc/sys/uio.h>
+
+ /* Now define the internal interfaces. */
+-extern ssize_t __readv (int __fd, __const struct iovec *__vector,
++extern ssize_t __readv (int __fd, __const struct iovec *__vec_tor,
+ int __count);
+-extern ssize_t __libc_readv (int __fd, __const struct iovec *__vector,
++extern ssize_t __libc_readv (int __fd, __const struct iovec *__vec_tor,
+ int __count);
+-extern ssize_t __writev (int __fd, __const struct iovec *__vector,
++extern ssize_t __writev (int __fd, __const struct iovec *__vec_tor,
+ int __count);
+-extern ssize_t __libc_writev (int __fd, __const struct iovec *__vector,
++extern ssize_t __libc_writev (int __fd, __const struct iovec *__vec_tor,
+ int __count);
+ #endif
--- /dev/null
+glibc.undefined_static
+
+This works around an old binutils bug, which would delete static
+constants out of the code, thus causing undefined symbols. Not sure if
+this patch is still needed.
+
+diff -rc libc-orig/stdio-common/psiginfo-define.h libc-new/stdio-common/psiginfo-define.h
+*** libc-orig/stdio-common/psiginfo-define.h 2009-04-09 08:12:53.000000000 -0500
+--- libc-new/stdio-common/psiginfo-define.h 2009-04-09 08:20:36.000000000 -0500
+***************
+*** 1,4 ****
+! static const union C(codestrs_t_, NOW) {
+ struct {
+ #define P(n, s) char MF(__LINE__)[sizeof (s)];
+ #include "psiginfo-data.h"
+--- 1,4 ----
+! const union C(codestrs_t_, NOW) {
+ struct {
+ #define P(n, s) char MF(__LINE__)[sizeof (s)];
+ #include "psiginfo-data.h"
+***************
+*** 8,14 ****
+ #define P(n, s) s,
+ #include "psiginfo-data.h"
+ } };
+! static const uint8_t C(codes_, NOW)[] = {
+ #define P(n, s) [(n) - 1] = offsetof (union C(codestrs_t_, NOW), MF(__LINE__)),
+ #include "psiginfo-data.h"
+ };
+--- 8,14 ----
+ #define P(n, s) s,
+ #include "psiginfo-data.h"
+ } };
+! const uint8_t C(codes_, NOW)[] = {
+ #define P(n, s) [(n) - 1] = offsetof (union C(codestrs_t_, NOW), MF(__LINE__)),
+ #include "psiginfo-data.h"
+ };
--- /dev/null
+diff -ruN gcc-4.6.0-orig/gcc/config/rs6000/rs6000-builtin.def gcc-4.6.0-new/gcc/config/rs6000/rs6000-builtin.def
+--- gcc-4.6.0-orig/gcc/config/rs6000/rs6000-builtin.def 2011-02-21 15:38:21.000000000 -0600
++++ gcc-4.6.0-new/gcc/config/rs6000/rs6000-builtin.def 2011-07-25 12:32:26.626006000 -0500
+@@ -750,6 +750,71 @@
+ RS6000_BUILTIN(SPE_BUILTIN_MFSPEFSCR, RS6000_BTC_MISC)
+ RS6000_BUILTIN(SPE_BUILTIN_BRINC, RS6000_BTC_MISC)
+
++/* ISEL builtins. */
++/* Generic versions that get resolved to specific builtins. */
++RS6000_BUILTIN(RS6000_BUILTIN_ISELEQ, RS6000_BTC_PURE)
++RS6000_BUILTIN_EQUATE(ISEL_BUILTIN_OVERLOADED_FIRST,
++ RS6000_BUILTIN_ISELEQ)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELGT, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELLT, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELGTU, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELLTU, RS6000_BTC_PURE)
++/* Same deal, but for 64-bit comparisons. */
++RS6000_BUILTIN(RS6000_BUILTIN_ISELEQD, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELGTD, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELLTD, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELGTDU, RS6000_BTC_PURE)
++RS6000_BUILTIN(RS6000_BUILTIN_ISELLTDU, RS6000_BTC_PURE)
++RS6000_BUILTIN_EQUATE(ISEL_BUILTIN_OVERLOADED_LAST,
++ RS6000_BUILTIN_ISELLTDU)
++
++/* Each set of arguments is polymorphic in selected arguments and return
++ value. */
++#undef RS6000_ISEL_BASE
++#define RS6000_ISEL_BASE(ARG, PRED, CMP) \
++ RS6000_BUILTIN(RS6000_BUILTIN_ISEL_##PRED##CMP##_##ARG##_SS, RS6000_BTC_PURE) \
++ RS6000_BUILTIN(RS6000_BUILTIN_ISEL_##PRED##CMP##_##ARG##_PP, RS6000_BTC_PURE) \
++ RS6000_BUILTIN(RS6000_BUILTIN_ISEL_##PRED##CMP##_##ARG##_UU, RS6000_BTC_PURE)
++#undef RS6000_ISEL_PTR_ARG
++#define RS6000_ISEL_PTR_ARG(PRED, CMP) RS6000_ISEL_BASE(PP, PRED, CMP)
++#undef RS6000_ISEL_SIGNED_ARG
++#define RS6000_ISEL_SIGNED_ARG(PRED, CMP) RS6000_ISEL_BASE(SS, PRED, CMP)
++#undef RS6000_ISEL_UNSIGNED_ARG
++#define RS6000_ISEL_UNSIGNED_ARG(PRED, CMP) RS6000_ISEL_BASE(UU, PRED, CMP)
++
++#undef RS6000_ISEL_EQ
++#define RS6000_ISEL_EQ(CMP) \
++ RS6000_ISEL_PTR_ARG(EQ, CMP) \
++ RS6000_ISEL_SIGNED_ARG(EQ, CMP) \
++ RS6000_ISEL_UNSIGNED_ARG(EQ, CMP)
++
++#undef RS6000_ISEL_LT
++#define RS6000_ISEL_LT(CMP) RS6000_ISEL_SIGNED_ARG(LT, CMP)
++
++#undef RS6000_ISEL_GT
++#define RS6000_ISEL_GT(CMP) RS6000_ISEL_SIGNED_ARG(GT, CMP)
++
++#undef RS6000_ISEL_LTU
++#define RS6000_ISEL_LTU(CMP) \
++ RS6000_ISEL_PTR_ARG(LTU, CMP) \
++ RS6000_ISEL_UNSIGNED_ARG(LTU, CMP)
++
++#undef RS6000_ISEL_GTU
++#define RS6000_ISEL_GTU(CMP) \
++ RS6000_ISEL_PTR_ARG(GTU, CMP) \
++ RS6000_ISEL_UNSIGNED_ARG(GTU, CMP)
++
++RS6000_ISEL_EQ(CMPW)
++RS6000_ISEL_LT(CMPW)
++RS6000_ISEL_GT(CMPW)
++RS6000_ISEL_LTU(CMPW)
++RS6000_ISEL_GTU(CMPW)
++RS6000_ISEL_EQ(CMPD)
++RS6000_ISEL_LT(CMPD)
++RS6000_ISEL_GT(CMPD)
++RS6000_ISEL_LTU(CMPD)
++RS6000_ISEL_GTU(CMPD)
++
+ /* PAIRED builtins. */
+ RS6000_BUILTIN(PAIRED_BUILTIN_DIVV2SF3, RS6000_BTC_MISC)
+ RS6000_BUILTIN(PAIRED_BUILTIN_ABSV2SF2, RS6000_BTC_MISC)
+diff -ruN gcc-4.6.0-orig/gcc/config/rs6000/rs6000.c gcc-4.6.0-new/gcc/config/rs6000/rs6000.c
+--- gcc-4.6.0-orig/gcc/config/rs6000/rs6000.c 2011-03-15 07:57:37.000000000 -0500
++++ gcc-4.6.0-new/gcc/config/rs6000/rs6000.c 2011-07-25 13:19:52.415921000 -0500
+@@ -12402,6 +12402,289 @@
+ return target;
+ }
+
++/* isel builtins are a bit funny, because we want the user to be able to do:
++
++ char *p, *q, *r;
++ int x, y, z;
++ unsigned int a, b, c;
++ ...
++ p = __builtin_iseleq (i, j, q, r);
++ x = __builtin_iseleq (i, j, y, z);
++ a = __builtin_iseleq (i, j, b, c);
++
++ and, of course, i and j may be of several different types depending on the
++ condition.
++
++ We handle this by having generic builtins that
++ TARGET_RESOLVE_OVERLOADED_BUILTIN takes and turns into calls to our
++ specific builtins. */
++
++/* Macros to help constructing the isel_builtin_desc arrays.
++ These closely mirror the macros in rs6000-builtins.def. */
++/* HACK: Use VOIDmode here as a constant approximation to Pmode and fix
++ at runtime. We can't use Pmode because in biarch its definition is
++ not constant. */
++#define ISEL_Pmode VOIDmode
++#define ISEL_BASE(FLAGS, ARG, RESULT, PRED, CMP, MODE, RMODE) \
++ { NULL, FLAGS, RS6000_BUILTIN_ISEL_##PRED##CMP##_##ARG##_##RESULT, \
++ PRED, MODE, RMODE },
++#define ISEL_P_RESULT(FLAGS, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_BASE (FLAGS | ISEL_FLAG_SEL_PTR, ARG, PP, PRED, \
++ CMP, MODE, ISEL_Pmode)
++#define ISEL_S_RESULT(FLAGS, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_BASE (FLAGS | ISEL_FLAG_SEL_SIGNED, ARG, SS, PRED, \
++ CMP, MODE, RMODE)
++#define ISEL_U_RESULT(FLAGS, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_BASE (FLAGS | ISEL_FLAG_SEL_UNSIGNED, ARG, UU, PRED, \
++ CMP, MODE, RMODE)
++
++#define ISEL_EXPAND_ARG(FLAG, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_P_RESULT (FLAG, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_S_RESULT (FLAG, ARG, PRED, CMP, MODE, RMODE) \
++ ISEL_U_RESULT (FLAG, ARG, PRED, CMP, MODE, RMODE)
++#define ISEL_PTR_ARG(PRED, CMP, MODE) \
++ ISEL_EXPAND_ARG (ISEL_FLAG_CMP_PTR, PP, PRED, CMP, ISEL_Pmode, MODE)
++#define ISEL_SIGNED_ARG(PRED, CMP, MODE) \
++ ISEL_EXPAND_ARG (ISEL_FLAG_CMP_SIGNED, SS, PRED, CMP, MODE, MODE)
++#define ISEL_UNSIGNED_ARG(PRED, CMP, MODE) \
++ ISEL_EXPAND_ARG (ISEL_FLAG_CMP_UNSIGNED, UU, PRED, CMP, MODE, MODE)
++
++#define ISEL_EQ(CMP, MODE) \
++ ISEL_PTR_ARG (EQ, CMP, MODE) \
++ ISEL_SIGNED_ARG (EQ, CMP, MODE) \
++ ISEL_UNSIGNED_ARG (EQ, CMP, MODE)
++#define ISEL_LT(CMP, MODE) ISEL_SIGNED_ARG (LT, CMP, MODE)
++#define ISEL_GT(CMP, MODE) ISEL_SIGNED_ARG (GT, CMP, MODE)
++#define ISEL_LTU(CMP, MODE) \
++ ISEL_PTR_ARG (LTU, CMP, MODE) \
++ ISEL_UNSIGNED_ARG (LTU, CMP, MODE)
++#define ISEL_GTU(CMP, MODE) \
++ ISEL_PTR_ARG (GTU, CMP, MODE) \
++ ISEL_UNSIGNED_ARG (GTU, CMP, MODE)
++
++const struct isel_builtin_desc builtin_iselw[32] = {
++ ISEL_EQ (CMPW, SImode)
++ ISEL_LT (CMPW, SImode)
++ ISEL_GT (CMPW, SImode)
++ ISEL_LTU (CMPW, SImode)
++ ISEL_GTU (CMPW, SImode)
++ { "__builtin_iseleq", 0, RS6000_BUILTIN_ISELEQ, EQ, SImode, SImode },
++ { "__builtin_isellt", 0, RS6000_BUILTIN_ISELLT, LT, SImode, SImode },
++ { "__builtin_iselgt", 0, RS6000_BUILTIN_ISELGT, GT, SImode, SImode },
++ { "__builtin_iselltu", 0, RS6000_BUILTIN_ISELLTU, LTU, SImode, SImode },
++ { "__builtin_iselgtu", 0, RS6000_BUILTIN_ISELGTU, GTU, SImode, SImode }
++};
++
++const struct isel_builtin_desc builtin_iseld[32] = {
++ ISEL_EQ (CMPD, DImode)
++ ISEL_LT (CMPD, DImode)
++ ISEL_GT (CMPD, DImode)
++ ISEL_LTU (CMPD, DImode)
++ ISEL_GTU (CMPD, DImode)
++ { "__builtin_isel64eq", 0, RS6000_BUILTIN_ISELEQD, EQ, DImode, DImode },
++ { "__builtin_isel64lt", 0, RS6000_BUILTIN_ISELLTD, LT, DImode, DImode },
++ { "__builtin_isel64gt", 0, RS6000_BUILTIN_ISELGTD, GT, DImode, DImode },
++ { "__builtin_isel64ltu", 0, RS6000_BUILTIN_ISELLTDU, LTU, DImode, DImode },
++ { "__builtin_isel64gtu", 0, RS6000_BUILTIN_ISELGTDU, GTU, DImode, DImode }
++};
++
++/* Return the mode which DESC uses for comparisons. */
++
++static enum machine_mode
++isel_cmp_mode (const struct isel_builtin_desc *desc)
++{
++ enum machine_mode mode = (enum machine_mode) desc->cmp_mode;
++
++ return (mode == VOIDmode ? Pmode : mode);
++}
++
++/* Return the mode in which DESC selects arguments. */
++
++static enum machine_mode
++isel_sel_mode (const struct isel_builtin_desc *desc)
++{
++ enum machine_mode mode = (enum machine_mode) desc->sel_mode;
++
++ return (mode == VOIDmode ? Pmode : mode);
++}
++
++/* Return a tree describing the arguments for DESC according to CMPP:
++ true for comparison arguments, false for select arguments. */
++
++static tree
++isel_argtype (const struct isel_builtin_desc *desc, bool cmpp)
++{
++ switch (desc->arg_flags & (cmpp
++ ? ISEL_FLAG_CMP_MASK
++ : ISEL_FLAG_SEL_MASK))
++ {
++ case ISEL_FLAG_CMP_PTR:
++ case ISEL_FLAG_SEL_PTR:
++ return ptr_type_node;
++ case ISEL_FLAG_CMP_SIGNED:
++ return (isel_cmp_mode (desc) == SImode
++ ? integer_type_node
++ : long_integer_type_node);
++ case ISEL_FLAG_SEL_SIGNED:
++ return (isel_sel_mode (desc) == SImode
++ ? integer_type_node
++ : long_integer_type_node);
++ case ISEL_FLAG_CMP_UNSIGNED:
++ return (isel_cmp_mode (desc) == SImode
++ ? unsigned_type_node
++ : long_unsigned_type_node);
++ case ISEL_FLAG_SEL_UNSIGNED:
++ default:
++ return (isel_sel_mode (desc) == SImode
++ ? unsigned_type_node
++ : long_unsigned_type_node);
++ }
++}
++
++/* Return a mnemonic string describing the argument or result of FLAGS
++ depending on CMPP. */
++
++static const char *
++isel_strdesc (int flags, bool cmpp)
++{
++ switch (flags & (cmpp ? ISEL_FLAG_CMP_MASK : ISEL_FLAG_SEL_MASK))
++ {
++ case ISEL_FLAG_CMP_PTR:
++ case ISEL_FLAG_SEL_PTR:
++ return "p";
++ case ISEL_FLAG_CMP_SIGNED:
++ case ISEL_FLAG_SEL_SIGNED:
++ return "s";
++ case ISEL_FLAG_CMP_UNSIGNED:
++ case ISEL_FLAG_SEL_UNSIGNED:
++ return "u";
++ default:
++ gcc_unreachable ();
++ }
++}
++
++/* Initialize N_DESC isel builtins from DESC. SIGNED_TYPE holds the
++ basic type for signed variants of isel, UNSIGNED_TYPE the type for
++ unsigned variants. */
++
++static void
++rs6000_init_isel_builtins (const struct isel_builtin_desc *desc, int n_descs)
++{
++ int i;
++ const char *is64 = (desc == &builtin_iselw[0] ? "32" : "64");
++
++ for (i = 0; i < n_descs; i++)
++ {
++ const struct isel_builtin_desc *d = &desc[i];
++ tree cmptype, seltype, ftype;
++
++ cmptype = isel_argtype (d, true);
++ seltype = isel_argtype (d, false);
++
++ ftype = build_function_type_list (seltype, cmptype, cmptype,
++ seltype, seltype, NULL_TREE);
++
++ if (d->name)
++ def_builtin (MASK_ISEL, d->name, ftype, d->code);
++ else
++ {
++ char builtin_name[40];
++
++ sprintf (builtin_name, "__builtin_isel%s%s%s%s%s%s",
++ is64,
++ GET_RTX_NAME (d->cmp_code),
++ GET_MODE_NAME (isel_cmp_mode (d)),
++ isel_strdesc (d->arg_flags, true),
++ isel_strdesc (d->arg_flags, false),
++ GET_MODE_NAME (isel_sel_mode (d)));
++
++ def_builtin (MASK_ISEL, ggc_strdup (builtin_name), ftype, d->code);
++ }
++ }
++}
++
++static rtx
++rs6000_expand_isel_builtin (const struct isel_builtin_desc *desc,
++ int n_descs, tree exp, rtx target, int fcode)
++{
++ int i;
++
++ for (i = 0; i < n_descs; i++)
++ {
++ const struct isel_builtin_desc *d = &desc[i];
++
++ if (fcode == (int) d->code)
++ {
++ int opidx;
++ unsigned int j;
++ rtx cmp;
++ rtx operands[4];
++ enum insn_code icode;
++ enum machine_mode opmode;
++ enum machine_mode cmpmode = isel_cmp_mode (d);
++ enum machine_mode selmode = isel_sel_mode (d);
++
++ /* Determine underlying isel insn. */
++ switch (d->cmp_code)
++ {
++ case GTU:
++ case LTU:
++ icode = (Pmode == SImode
++ ? CODE_FOR_isel_unsigned_si
++ : CODE_FOR_isel_unsigned_di);
++ break;
++ default:
++ icode = (Pmode == SImode
++ ? CODE_FOR_isel_signed_si
++ : CODE_FOR_isel_signed_di);
++ break;
++ }
++
++ for (j = 0; j < ARRAY_SIZE (operands); j++)
++ {
++ tree arg = CALL_EXPR_ARG (exp, j);
++
++ /* If we got invalid arguments, bail out before generating
++ bad rtl. */
++ if (arg == error_mark_node)
++ return const0_rtx;
++
++ operands[j] = expand_normal (arg);
++
++ /* Validate. */
++ /* HACK: The isel pattern doesn't actually consume all the
++ operands to the builtin; it only consumes 2 and 3. The
++ other two will be handed off to a compare
++ insn. Unfortunately, said insn is not named, so we
++ can't directly access its insn_data here. Fake it by
++ validating operands 0 and 1 with the isel pattern; that
++ should be good enough. */
++ opidx = (j < 2 ? 2 : j);
++ opmode = (j < 2 ? cmpmode : selmode);
++ if (! (*insn_data[icode].operand[opidx].predicate) (operands[j],
++ opmode))
++ operands[j] = copy_to_mode_reg (opmode, operands[j]);
++ }
++
++ /* Validate target. */
++ if (target == NULL_RTX
++ || GET_MODE (target) != selmode
++ || ! (*insn_data[icode].operand[0].predicate) (target, selmode))
++ target = gen_reg_rtx (selmode);
++
++ /* Generate comparison. */
++ cmp = gen_rtx_fmt_ee ((enum rtx_code)d->cmp_code, cmpmode,
++ operands[0], operands[1]);
++
++ rs6000_emit_int_cmove (target, cmp, operands[2], operands[3]);
++
++ return target;
++ }
++ }
++
++ return NULL_RTX;
++}
++
+ /* Expand an expression EXP that calls a built-in function,
+ with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+@@ -12520,6 +12803,24 @@
+ if (success)
+ return ret;
+ }
++ if (TARGET_ISEL)
++ {
++ ret = rs6000_expand_isel_builtin (builtin_iselw,
++ ARRAY_SIZE (builtin_iselw),
++ exp, target, fcode);
++
++ if (ret != NULL_RTX)
++ return ret;
++ }
++ if (TARGET_ISEL64)
++ {
++ ret = rs6000_expand_isel_builtin (builtin_iseld,
++ ARRAY_SIZE (builtin_iseld),
++ exp, target, fcode);
++
++ if (ret != NULL_RTX)
++ return ret;
++ }
+
+ gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT);
+
+@@ -12738,6 +13039,10 @@
+ spe_init_builtins ();
+ if (TARGET_ALTIVEC)
+ altivec_init_builtins ();
++ if (TARGET_ISEL)
++ rs6000_init_isel_builtins (builtin_iselw, ARRAY_SIZE (builtin_iselw));
++ if (TARGET_ISEL64)
++ rs6000_init_isel_builtins (builtin_iseld, ARRAY_SIZE (builtin_iseld));
+ if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT || TARGET_VSX)
+ rs6000_common_init_builtins ();
+ if (TARGET_FRE)
+diff -ruN gcc-4.6.0-orig/gcc/config/rs6000/rs6000-c.c gcc-4.6.0-new/gcc/config/rs6000/rs6000-c.c
+--- gcc-4.6.0-orig/gcc/config/rs6000/rs6000-c.c 2011-02-02 23:42:19.000000000 -0600
++++ gcc-4.6.0-new/gcc/config/rs6000/rs6000-c.c 2011-07-25 16:07:14.616209000 -0500
+@@ -3439,7 +3439,7 @@
+ /* Implementation of the resolve_overloaded_builtin target hook, to
+ support Altivec's overloaded builtins. */
+
+-tree
++static tree
+ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
+ void *passed_arglist)
+ {
+@@ -3770,3 +3770,148 @@
+ error ("invalid parameter combination for AltiVec intrinsic");
+ return error_mark_node;
+ }
++
++/* Return true if the pair of arguments in ARGS is acceptable according
++ to DECLTYPES and FLAGS. CMPP determines whether this is for the
++ comparison arguments. */
++
++static bool
++isel_arguments_valid (tree *args, tree *decltypes, int flags, bool cmpp)
++{
++ tree type0 = TREE_TYPE (args[0]);
++ tree type1 = TREE_TYPE (args[1]);
++ tree decltype0 = decltypes[0];
++ tree decltype1 = decltypes[1];
++
++ switch (flags & (cmpp ? ISEL_FLAG_CMP_MASK : ISEL_FLAG_SEL_MASK))
++ {
++ /* For pointer arguments and results, we just need to make sure
++ we're receiving pointers, and they can be freely converted to
++ and from void *. For pointer results, we also need to ensure
++ that the types of the passed arguments are compatible: this is
++ similar to what the ?: construct would need to ensure. */
++ case ISEL_FLAG_CMP_PTR:
++ case ISEL_FLAG_SEL_PTR:
++ {
++ /* Results compatible with each other? */
++ if (!lang_hooks.types_compatible_p (type0, type1))
++ return false;
++
++ return (POINTER_TYPE_P (type0)
++ && POINTER_TYPE_P (type1));
++ }
++ break;
++ /* For signed and unsigned arguments and results, we just need to
++ make sure that the argument types are compatible with the
++ declared types; we can insert conversions to make everything
++ match up. */
++ case ISEL_FLAG_CMP_SIGNED:
++ case ISEL_FLAG_SEL_SIGNED:
++ case ISEL_FLAG_CMP_UNSIGNED:
++ case ISEL_FLAG_SEL_UNSIGNED:
++ return (lang_hooks.types_compatible_p (type0, decltype0)
++ && lang_hooks.types_compatible_p (type1, decltype1));
++ default:
++ ;
++ }
++
++ gcc_unreachable ();
++}
++
++/* Determine if FNDECL is a generic isel intrinsic and if it can be
++ resolved to a non-generic version with a proper type using the
++ descriptions found in DESC. Return a call to the non-generic builtin
++ if so. */
++
++static tree
++rs6000_resolve_isel_builtin (location_t loc, tree fndecl,
++ void *passed_arglist,
++ const struct isel_builtin_desc *desc,
++ int n_descs)
++{
++ VEC(tree,gc) *arglist = (VEC(tree,gc) *) passed_arglist;
++ unsigned int nargs = VEC_length (tree, arglist);
++ int i;
++ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
++ const struct isel_builtin_desc *generic = NULL;
++
++ /* Is this even a builtin we care about? */
++ if (fcode < ISEL_BUILTIN_OVERLOADED_FIRST
++ || fcode > ISEL_BUILTIN_OVERLOADED_LAST)
++ return NULL_TREE;
++
++ if (nargs != 4)
++ {
++ error ("isel intrinsics only accept 4 arguments");
++ return error_mark_node;
++ }
++
++ /* Find the generic builtin we're resolving. */
++ for (i = 0; i < n_descs; i++)
++ if (desc[i].code == fcode)
++ {
++ generic = &desc[i];
++ break;
++ }
++
++ /* Happens if we're looking for a 64-bit builtin in the 32-bit
++ descriptors. */
++ if (generic == NULL)
++ return NULL_TREE;
++
++ /* Try all the builtins whose comparison matches the generic one. */
++ for (i = 0; i < n_descs; i++)
++ {
++ const struct isel_builtin_desc *d = &desc[i];
++ int j;
++ tree *argp = VEC_address (tree, arglist);
++ tree impl_fndecl;
++ tree decltypes[4], t;
++ tree converted_args[4];
++
++ if (d == generic || d->cmp_code != generic->cmp_code)
++ continue;
++
++ impl_fndecl = rs6000_builtin_decls[d->code];
++ t = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
++ for (j = 0 ; t != void_list_node; j++, t = TREE_CHAIN (t))
++ decltypes[j] = TREE_VALUE (t);
++
++ if (!isel_arguments_valid (argp, decltypes, d->arg_flags, true)
++ || !isel_arguments_valid (argp+2, decltypes+2, d->arg_flags, false))
++ continue;
++
++ /* We got here, we're ok. Build a new, resolved CALL_EXPR. */
++ for (j = 0; j < 4; j++)
++ converted_args[j] = fold_convert (decltypes[j], argp[j]);
++
++ return build_call_expr_loc (loc, impl_fndecl, 4,
++ converted_args[0], converted_args[1],
++ converted_args[2], converted_args[3]);
++ }
++
++ error ("invalid parameter combination for isel intrinsic");
++ return error_mark_node;
++}
++
++tree
++rs6000_resolve_overloaded_builtin (location_t loc, tree fndecl, void *arglist)
++{
++ tree t;
++
++ t = altivec_resolve_overloaded_builtin (loc, fndecl, arglist);
++ if (t)
++ return t;
++
++ t = rs6000_resolve_isel_builtin (loc, fndecl, arglist,
++ builtin_iselw, ARRAY_SIZE (builtin_iselw));
++ if (t)
++ return t;
++
++ t = rs6000_resolve_isel_builtin (loc, fndecl, arglist,
++ builtin_iseld, ARRAY_SIZE (builtin_iseld));
++ if (t)
++ return t;
++
++ return NULL_TREE;
++}
+diff -ruN gcc-4.6.0-orig/gcc/config/rs6000/rs6000.h gcc-4.6.0-new/gcc/config/rs6000/rs6000.h
+--- gcc-4.6.0-orig/gcc/config/rs6000/rs6000.h 2011-03-07 13:27:09.000000000 -0600
++++ gcc-4.6.0-new/gcc/config/rs6000/rs6000.h 2011-07-25 16:07:04.045105000 -0500
+@@ -535,7 +535,7 @@
+ #define REGISTER_TARGET_PRAGMAS() do { \
+ c_register_pragma (0, "longcall", rs6000_pragma_longcall); \
+ targetm.target_option.pragma_parse = rs6000_pragma_target_parse; \
+- targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
++ targetm.resolve_overloaded_builtin = rs6000_resolve_overloaded_builtin; \
+ } while (0)
+
+ /* Target #defines. */
+@@ -2446,3 +2446,41 @@
+ extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
+ extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+
++/* Values for struct isel_builtin_desc.arg_flags. */
++enum {
++ ISEL_FLAG_CMP_PTR = 0x1,
++ ISEL_FLAG_CMP_SIGNED = 0x2,
++ ISEL_FLAG_CMP_UNSIGNED = 0x4,
++ ISEL_FLAG_CMP_MASK = 0x7,
++ ISEL_FLAG_SEL_PTR = 0x10,
++ ISEL_FLAG_SEL_SIGNED = 0x20,
++ ISEL_FLAG_SEL_UNSIGNED = 0x40,
++ ISEL_FLAG_SEL_MASK = 0x70
++};
++
++struct isel_builtin_desc {
++ /* Name of this builtin. NULL if we should construct it. */
++ const char *name;
++
++ /* Flags for argument combinations accepted by the builtin.
++ Zero if this builtin is a generic builtin, to be resolved later. */
++ int arg_flags;
++
++ /* The code of the builtin. */
++ enum rs6000_builtins code;
++
++ /* rtx_code and machine_mode are not available here; use ints instead. */
++ /* The comparison code the builtin uses. */
++ int cmp_code;
++
++ /* The mode the builtin does comparisons in. */
++ int cmp_mode;
++
++ /* The mode the builtin's selected arguments are in.
++ Also happens to be its result mode. */
++ int sel_mode;
++};
++
++/* Arrays describing isel builtins. */
++extern const struct isel_builtin_desc builtin_iselw[32];
++extern const struct isel_builtin_desc builtin_iseld[32];
+diff -ruN gcc-4.6.0-orig/gcc/config/rs6000/rs6000-protos.h gcc-4.6.0-new/gcc/config/rs6000/rs6000-protos.h
+--- gcc-4.6.0-orig/gcc/config/rs6000/rs6000-protos.h 2011-03-15 07:57:37.000000000 -0500
++++ gcc-4.6.0-new/gcc/config/rs6000/rs6000-protos.h 2011-07-25 16:07:50.484773000 -0500
+@@ -142,7 +142,7 @@
+ unsigned int);
+ extern unsigned int darwin_rs6000_special_round_type_align (tree, unsigned int,
+ unsigned int);
+-extern tree altivec_resolve_overloaded_builtin (location_t, tree, void *);
++extern tree rs6000_resolve_overloaded_builtin (location_t, tree, void *);
+ extern rtx rs6000_libcall_value (enum machine_mode);
+ extern rtx rs6000_va_arg (tree, tree);
+ extern int function_ok_for_sibcall (tree);
+diff -ruN gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel64.c gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel64.c
+--- gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel64.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel64.c 2011-07-25 12:27:55.343932000 -0500
+@@ -0,0 +1,75 @@
++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
++/* { dg-options "-mcpu=e500mc64" } */
++
++#include "builtin-isel.h"
++
++/* Equality comparisons. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64eq
++
++SIGNED64_PROTO
++{
++ L = ISEL_BUILTIN (x, y, a, b);
++ U = ISEL_BUILTIN (x, y, (unsigned long) a, (unsigned long) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ L = ISEL_BUILTIN (p, q, a, b);
++ /* Equality checks explicitly permit unsigned comparison operands. */
++ L = ISEL_BUILTIN ((unsigned long) x, (unsigned long) y, a, b);
++ r = ISEL_BUILTIN ((unsigned long) x, (unsigned long) y, p, q);
++}
++\f
++/* less-than, greater-than. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64lt
++
++SIGNED64_PROTO
++{
++ L = ISEL_BUILTIN (x, y, a, b);
++ U = ISEL_BUILTIN (x, y, (unsigned long) a, (unsigned long) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64gt
++
++SIGNED64_PROTO
++{
++ L = ISEL_BUILTIN (x, y, a, b);
++ U = ISEL_BUILTIN (x, y, (unsigned long) a, (unsigned long) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++}
++\f
++/* Unsigned variants. These permit unsigned and pointer operands for
++ comparison only. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64ltu
++
++UNSIGNED64_PROTO
++{
++ L = ISEL_BUILTIN (x, y, a, b);
++ U = ISEL_BUILTIN (x, y, (unsigned long) a, (unsigned long) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ L = ISEL_BUILTIN (p, q, a, b);
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64gtu
++
++UNSIGNED64_PROTO
++{
++ L = ISEL_BUILTIN (x, y, a, b);
++ U = ISEL_BUILTIN (x, y, (unsigned long) a, (unsigned long) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ L = ISEL_BUILTIN (p, q, a, b);
++}
++
++/* Don't use bare isel, as that'll match function names and the like. */
++/* { dg-final { scan-assembler-times "isel " 26 } } */
+diff -ruN gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel64-errors.c gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel64-errors.c
+--- gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel64-errors.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel64-errors.c 2011-07-25 12:27:55.372965000 -0500
+@@ -0,0 +1,110 @@
++/* Test rejection of invalid parameter combinations in isel builtins. */
++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
++/* { dg-options "-mcpu=e5500" } */
++
++#include "builtin-isel.h"
++
++\f
++/* Equality comparisons. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64eq
++
++SIGNED64_PROTO
++{
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned long) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned long) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((long *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (long *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned long) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned long) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (long *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (long *) q); /* { dg-error "isel intrinsic" } */
++}
++\f
++/* less-than, greater-than. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64lt
++
++SIGNED64_PROTO
++{
++ /* Unsigned comparison should be done with the *u variants. */
++ ISEL_BUILTIN ((unsigned long) x, (unsigned long) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* So should pointer comparison. */
++ ISEL_BUILTIN (p, q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned long) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned long) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((long *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (long *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned long) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned long) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (long *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (long *) q); /* { dg-error "isel intrinsic" } */
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64gt
++
++SIGNED64_PROTO
++{
++ /* Unsigned comparison should be done with the *u variants. */
++ ISEL_BUILTIN ((unsigned long) x, (unsigned long) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* So should pointer comparison. */
++ ISEL_BUILTIN (p, q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned long) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned long) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((long *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (long *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned long) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned long) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (long *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (long *) q); /* { dg-error "isel intrinsic" } */
++}
++\f
++/* Unsigned variants. These permit unsigned and pointer operands for
++ comparison only. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64ltu
++
++UNSIGNED64_PROTO
++{
++ /* Signed comparison should be done with the signed variants. */
++ ISEL_BUILTIN ((long) x, (long) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((long) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (long) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((long *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (long *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned long) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned long) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (long *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (long *) q); /* { dg-error "isel intrinsic" } */
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isel64gtu
++
++UNSIGNED64_PROTO
++{
++ /* Signed comparison should be done with the signed variants. */
++ ISEL_BUILTIN ((long) x, (long) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((long) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (long) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((long *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (long *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned long) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned long) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (long *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (long *) q); /* { dg-error "isel intrinsic" } */
++}
+diff -ruN gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel.c gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel.c
+--- gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel.c 2011-07-25 12:27:55.405959000 -0500
+@@ -0,0 +1,81 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=e500mc" } */
++
++#include "builtin-isel.h"
++
++/* We're not being clever with the preprocessor here because DejaGNU
++ will get confused. We do try to use it to eliminate what duplication
++ we can. */
++
++/* We check to see that the resolution permits polymorphic results. */
++\f
++/* Equality comparisons. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iseleq
++
++SIGNED_PROTO
++{
++ i = ISEL_BUILTIN (x, y, a, b);
++ u = ISEL_BUILTIN (x, y, (unsigned int) a, (unsigned int) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ i = ISEL_BUILTIN (p, q, a, b);
++ /* Equality checks explicitly permit unsigned comparison operands. */
++ i = ISEL_BUILTIN ((unsigned int) x, (unsigned int) y, a, b);
++ r = ISEL_BUILTIN ((unsigned int) x, (unsigned int) y, p, q);
++}
++\f
++/* less-than, greater-than. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isellt
++
++SIGNED_PROTO
++{
++ i = ISEL_BUILTIN (x, y, a, b);
++ u = ISEL_BUILTIN (x, y, (unsigned int) a, (unsigned int) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselgt
++
++SIGNED_PROTO
++{
++ i = ISEL_BUILTIN (x, y, a, b);
++ u = ISEL_BUILTIN (x, y, (unsigned int) a, (unsigned int) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++}
++\f
++/* Unsigned variants. These permit unsigned and pointer operands for
++ comparison only. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselltu
++
++UNSIGNED_PROTO
++{
++ i = ISEL_BUILTIN (x, y, a, b);
++ u = ISEL_BUILTIN (x, y, (unsigned int) a, (unsigned int) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ i = ISEL_BUILTIN (p, q, a, b);
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselgtu
++
++UNSIGNED_PROTO
++{
++ i = ISEL_BUILTIN (x, y, a, b);
++ u = ISEL_BUILTIN (x, y, (unsigned int) a, (unsigned int) b);
++ r = ISEL_BUILTIN (x, y, p, q);
++ r = ISEL_BUILTIN (x, y, (char *) p, (char *) q);
++ i = ISEL_BUILTIN (p, q, a, b);
++}
++
++/* Don't use bare isel, as that'll match function names and the like. */
++/* { dg-final { scan-assembler-times "isel " 26 } } */
+diff -ruN gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel-errors.c gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel-errors.c
+--- gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel-errors.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel-errors.c 2011-07-25 12:27:55.443938000 -0500
+@@ -0,0 +1,117 @@
++/* Test rejection of invalid parameter combinations in isel builtins. */
++/* { dg-do compile } */
++/* { dg-options "-mcpu=e500mc" } */
++
++#include "builtin-isel.h"
++
++/* We're not being clever with the preprocessor here because DejaGNU
++ will get confused. We do try to use it to eliminate what duplication
++ we can. */
++
++/* We check basic resolution of each builtin. We also check to see that
++ the resolution permits polymorphic results. Argument type mismatches
++ and result type mismatches are not permitted, except where noted. */
++\f
++/* Equality comparisons. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iseleq
++
++SIGNED_PROTO
++{
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned int) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned int) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((int *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (int *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned int) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned int) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (int *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (int *) q); /* { dg-error "isel intrinsic" } */
++}
++\f
++/* less-than, greater-than. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME isellt
++
++SIGNED_PROTO
++{
++ /* Unsigned comparison should be done with the *u variants. */
++ ISEL_BUILTIN ((unsigned int) x, (unsigned int) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* So should pointer comparison. */
++ ISEL_BUILTIN (p, q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned int) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned int) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((int *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (int *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned int) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned int) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (int *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (int *) q); /* { dg-error "isel intrinsic" } */
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselgt
++
++SIGNED_PROTO
++{
++ /* Unsigned comparison should be done with the *u variants. */
++ ISEL_BUILTIN ((unsigned int) x, (unsigned int) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* So should pointer comparison. */
++ ISEL_BUILTIN (p, q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((unsigned int) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (unsigned int) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((int *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (int *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned int) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned int) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (int *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (int *) q); /* { dg-error "isel intrinsic" } */
++}
++\f
++/* Unsigned variants. These permit unsigned and pointer operands for
++ comparison only. */
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselltu
++
++UNSIGNED_PROTO
++{
++ /* Signed comparison should be done with the signed variants. */
++ ISEL_BUILTIN ((int) x, (int) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((int) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (int) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((int *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (int *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned int) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned int) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (int *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (int *) q); /* { dg-error "isel intrinsic" } */
++}
++
++#undef FUNCTION_NAME
++#define FUNCTION_NAME iselgtu
++
++UNSIGNED_PROTO
++{
++ /* Signed comparison should be done with the signed variants. */
++ ISEL_BUILTIN ((int) x, (int) y, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in argument type. */
++ ISEL_BUILTIN ((int) x, y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, (int) y, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN ((int *) p, q, a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (p, (int *) q, a, b); /* { dg-error "isel intrinsic" } */
++ /* Mismatches in return type. */
++ ISEL_BUILTIN (x, y, (unsigned int) a, b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, a, (unsigned int) b); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, (int *) p, q); /* { dg-error "isel intrinsic" } */
++ ISEL_BUILTIN (x, y, p, (int *) q); /* { dg-error "isel intrinsic" } */
++}
+diff -ruN gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel.h gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel.h
+--- gcc-4.6.0-orig/gcc/testsuite/gcc.target/powerpc/builtin-isel.h 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/testsuite/gcc.target/powerpc/builtin-isel.h 2011-07-25 12:27:55.483942000 -0500
+@@ -0,0 +1,25 @@
++/* Common definitions for builtin isel testing. */
++
++#define SIGNED_ARGLIST (int x, int y, int a, int b, void *p, void *q)
++#define UNSIGNED_ARGLIST (unsigned int x, unsigned int y, \
++ int a, int b, void *p, void *q)
++
++#define SIGNED_PROTO void FUNCTION_NAME SIGNED_ARGLIST
++#define UNSIGNED_PROTO void FUNCTION_NAME UNSIGNED_ARGLIST
++
++#define SIGNED64_ARGLIST (long x, long y, long a, long b, void *p, void *q)
++#define UNSIGNED64_ARGLIST (unsigned long x, unsigned long y, \
++ long a, long b, void *p, void *q)
++
++#define SIGNED64_PROTO void FUNCTION_NAME SIGNED64_ARGLIST
++#define UNSIGNED64_PROTO void FUNCTION_NAME UNSIGNED64_ARGLIST
++
++#define CONCAT2(X,Y) X##Y
++#define CONCAT(X,Y) CONCAT2(X, Y)
++#define ISEL_BUILTIN CONCAT(__builtin_, FUNCTION_NAME)
++
++volatile int i;
++volatile unsigned int u;
++volatile void *r;
++volatile long L;
++volatile unsigned long U;
--- /dev/null
+--- gcc-4.6.0/gcc/params.def-orig 2011-06-16 11:39:42.412634260 -0500
++++ gcc-4.6.0/gcc/params.def 2011-06-16 11:41:29.457630886 -0500
+@@ -39,6 +39,11 @@
+
+ Be sure to add an entry to invoke.texi summarizing the parameter. */
+
++DEFPARAM (PARAM_CASE_VALUES_THRESHOLD,
++ "case-values-threshold",
++ "Minimum number of case statements for each a jump table will be used",
++ 4, 4, 1000)
++
+ /* The threshold ratio between current and hottest structure counts.
+ We say that if the ratio of the current structure count,
+ calculated by profiling, to the hottest structure count
+--- gcc-4.6.0/gcc/config/rs6000/rs6000.c-orig 2011-06-16 12:24:03.440630751 -0500
++++ gcc-4.6.0/gcc/config/rs6000/rs6000.c 2011-06-16 12:24:51.450630163 -0500
+@@ -1282,6 +1282,7 @@
+ struct cl_target_option *);
+ static bool rs6000_can_inline_p (tree, tree);
+ static void rs6000_set_current_function (tree);
++static unsigned int rs6000_case_values_threshold (void);
+
+ \f
+ /* Default register names. */
+--- gcc-4.6.0/gcc/config/rs6000/rs6000.c-orig 2011-06-16 11:18:27.131631000 -0500
++++ gcc-4.6.0/gcc/config/rs6000/rs6000.c 2011-06-16 11:38:15.225631714 -0500
+@@ -1704,6 +1704,9 @@
+ #undef TARGET_SET_CURRENT_FUNCTION
+ #define TARGET_SET_CURRENT_FUNCTION rs6000_set_current_function
+
++#undef TARGET_CASE_VALUES_THRESHOLD
++#define TARGET_CASE_VALUES_THRESHOLD rs6000_case_values_threshold
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ \f
+
+@@ -28179,6 +28182,12 @@
+ }
+
+ \f
++static unsigned int
++rs6000_case_values_threshold (void)
++{
++ return PARAM_VALUE (PARAM_CASE_VALUES_THRESHOLD);
++}
++\f
+ /* Save the current options */
+
+ static void
+--- gcc-4.6.0/gcc/config/rs6000/rs6000.c-orig 2011-06-17 12:19:00.463631000 -0500
++++ gcc-4.6.0/gcc/config/rs6000/rs6000.c 2011-06-17 12:06:28.904630840 -0500
+@@ -2906,6 +2906,13 @@
+ if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32))
+ rs6000_block_move_inline_limit = (TARGET_POWERPC64 ? 64 : 32);
+
++ if ((rs6000_cpu == PROCESSOR_PPC8540
++ || rs6000_cpu == PROCESSOR_PPCE500MC
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500)
++ && global_options_set.x_param_values[(int) PARAM_CASE_VALUES_THRESHOLD] != true)
++ global_options.x_param_values[(int) PARAM_CASE_VALUES_THRESHOLD] = 8;
++
+ if (global_init_p)
+ {
+ /* If the appropriate debug option is enabled, replace the target hooks
--- /dev/null
+--- gcc-4_6-branch/gcc/Makefile.in.orig 2012-03-06 01:10:15.277196930 -0600
++++ gcc-4_6-branch/gcc/Makefile.in 2012-03-06 01:10:54.083378912 -0600
+@@ -4170,6 +4170,9 @@
+ else \
+ set -e; for ml in `cat fixinc_list`; do \
+ sysroot_headers_suffix=`echo $${ml} | sed -e 's/;.*$$//'`; \
++ if test "x$${sysroot_headers_suffix}" = "x"; then \
++ continue; \
++ fi; \
+ multi_dir=`echo $${ml} | sed -e 's/^[^;]*;//'`; \
+ fix_dir=include-fixed$${multi_dir}; \
+ if ! $(inhibit_libc) && test ! -d ${SYSTEM_HEADER_DIR}; then \
--- /dev/null
+# Problem: Although gcc is prepared to avoid "mfocr" instructions
+ (which takes 5 cycles in our parts and 2 cycles on IBM parts). This
+ instruction is used on the mentioned program. What is suspicious
+ about it, is that the code compiled for 32 bits does not use the
+ instruction. So, it could be a omission in the previous
+ implementation, or a bug, or a new opportunity.
+# Reported by: Performance team (PARC)
+# Owned by: Ping Hu
+# Action:
+ * 'mfocr' flag problem: that 'mfocr' flag was uncorrectly set for E5500,
+ which caused the 'mfocr' instructions generated even on E5500.
+ * avoid generating 'mfcr' and 'mfocr' instructions: due to the fact
+ that both instructions are expensive on Freescale processors.
+ * A target specific flag, -mslow-mfocr, can be used to avoid generating
+ 'mfcr' and 'mfocr' instructions in 64-bit mode, thus restoring legacy
+ operations if desired.
+
+diff -ruN gcc-4.6.2-clean/gcc/config/rs6000/rs6000.c gcc-4.6.2/gcc/config/rs6000/rs6000.c
+--- gcc-4.6.2-clean/gcc/config/rs6000/rs6000.c 2011-11-22 11:11:47.479144000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.c 2011-11-29 16:23:45.074279998 -0600
+@@ -1885,6 +1885,7 @@
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
+ };
+
++
+ /* Look up a processor name for -mcpu=xxx and -mtune=xxx. Return -1 if the
+ name is invalid. */
+
+@@ -2902,6 +2903,10 @@
+ || rs6000_cpu == PROCESSOR_PPCE6500)
+ target_flags &= ~MASK_PPC_GPOPT;
+
++ if (rs6000_cpu == PROCESSOR_PPCE5500)
++ target_flags &= ~MASK_MFCRF;
++
++
+ /* store_one_arg depends on expand_block_move to handle at least the
+ size of reg_parm_stack_space. */
+ if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32))
+diff -ruN gcc-4.6.2-clean/gcc/config/rs6000/rs6000.md gcc-4.6.2/gcc/config/rs6000/rs6000.md
+--- gcc-4.6.2-clean/gcc/config/rs6000/rs6000.md 2011-11-22 11:11:47.036144001 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.md 2011-11-29 16:24:04.705280001 -0600
+@@ -215,6 +215,8 @@
+ ; (one with a '.') will compare; and the size used for arithmetic carries.
+ (define_mode_iterator P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
+
++(define_mode_iterator P2 [(SI "TARGET_32BIT || TARGET_SLOW_MFOCR") (DI "TARGET_64BIT")])
++
+ ; Any hardware-supported floating-point mode
+ (define_mode_iterator FP [
+ (SF "TARGET_HARD_FLOAT
+@@ -2208,9 +2210,9 @@
+
+ (define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
+- (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
++ (compare:CC (neg:P2 (match_operand:P2 1 "gpc_reg_operand" "r,r"))
+ (const_int 0)))
+- (clobber (match_scratch:P 2 "=r,r"))]
++ (clobber (match_scratch:P2 2 "=r,r"))]
+ ""
+ "@
+ neg. %2,%1
+@@ -2220,12 +2222,12 @@
+
+ (define_split
+ [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
+- (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
++ (compare:CC (neg:P2 (match_operand:P2 1 "gpc_reg_operand" ""))
+ (const_int 0)))
+- (clobber (match_scratch:P 2 ""))]
++ (clobber (match_scratch:P2 2 ""))]
+ "reload_completed"
+ [(set (match_dup 2)
+- (neg:P (match_dup 1)))
++ (neg:P2 (match_dup 1)))
+ (set (match_dup 0)
+ (compare:CC (match_dup 2)
+ (const_int 0)))]
+@@ -2233,10 +2235,10 @@
+
+ (define_insn ""
+ [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
+- (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
++ (compare:CC (neg:P2 (match_operand:P2 1 "gpc_reg_operand" "r,r"))
+ (const_int 0)))
+- (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+- (neg:P (match_dup 1)))]
++ (set (match_operand:P2 0 "gpc_reg_operand" "=r,r")
++ (neg:P2 (match_dup 1)))]
+ ""
+ "@
+ neg. %0,%1
+@@ -2246,13 +2248,13 @@
+
+ (define_split
+ [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
+- (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
++ (compare:CC (neg:P2 (match_operand:P2 1 "gpc_reg_operand" ""))
+ (const_int 0)))
+- (set (match_operand:P 0 "gpc_reg_operand" "")
+- (neg:P (match_dup 1)))]
++ (set (match_operand:P2 0 "gpc_reg_operand" "")
++ (neg:P2 (match_dup 1)))]
+ "reload_completed"
+ [(set (match_dup 0)
+- (neg:P (match_dup 1)))
++ (neg:P2 (match_dup 1)))
+ (set (match_dup 2)
+ (compare:CC (match_dup 0)
+ (const_int 0)))]
+@@ -15286,31 +15288,31 @@
+ [(set_attr "length" "12")])
+
+ (define_insn_and_split "*gtu<mode>"
+- [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+- (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+- (match_operand:P 2 "reg_or_short_operand" "rI")))]
++ [(set (match_operand:P2 0 "gpc_reg_operand" "=r")
++ (gtu:P2 (match_operand:P2 1 "gpc_reg_operand" "r")
++ (match_operand:P2 2 "reg_or_short_operand" "rI")))]
+ ""
+ "#"
+ ""
+- [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+- (set (match_dup 0) (neg:P (match_dup 0)))]
++ [(set (match_dup 0) (neg:P2 (gtu:P2 (match_dup 1) (match_dup 2))))
++ (set (match_dup 0) (neg:P2 (match_dup 0)))]
+ "")
+
+ (define_insn_and_split "*gtu<mode>_compare"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
+ (compare:CC
+- (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+- (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
++ (gtu:P2 (match_operand:P2 1 "gpc_reg_operand" "r,r")
++ (match_operand:P2 2 "reg_or_short_operand" "rI,rI"))
+ (const_int 0)))
+- (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+- (gtu:P (match_dup 1) (match_dup 2)))]
++ (set (match_operand:P2 0 "gpc_reg_operand" "=r,r")
++ (gtu:P2 (match_dup 1) (match_dup 2)))]
+ ""
+ "#"
+ ""
+- [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
++ [(set (match_dup 0) (neg:P2 (gtu:P2 (match_dup 1) (match_dup 2))))
+ (parallel [(set (match_dup 3)
+- (compare:CC (neg:P (match_dup 0)) (const_int 0)))
+- (set (match_dup 0) (neg:P (match_dup 0)))])]
++ (compare:CC (neg:P2 (match_dup 0)) (const_int 0)))
++ (set (match_dup 0) (neg:P2 (match_dup 0)))])]
+ "")
+
+ (define_insn_and_split "*plus_gtu<mode>"
+@@ -15345,9 +15347,9 @@
+ "")
+
+ (define_insn "*neg_gtu<mode>"
+- [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+- (neg:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+- (match_operand:P 2 "reg_or_short_operand" "rI"))))]
++ [(set (match_operand:P2 0 "gpc_reg_operand" "=r")
++ (neg:P2 (gtu:P2 (match_operand:P2 1 "gpc_reg_operand" "r")
++ (match_operand:P2 2 "reg_or_short_operand" "rI"))))]
+ ""
+ "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0"
+ [(set_attr "type" "two")
+--- gcc-4.6.2-clean/gcc/config/rs6000/rs6000.opt 2011-11-22 11:11:47.480143999 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.opt 2011-11-29 16:24:16.322280634 -0600
+@@ -381,6 +381,10 @@
+ Target
+ Generate SPE SIMD instructions on E500
+
++mslow-mfocr
++Target Report Var(TARGET_SLOW_MFOCR)
++Generate slow mfocr instructions
++
+ mpaired
+ Target Var(rs6000_paired_float) Save
+ Generate PPC750CL paired-single instructions
--- /dev/null
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/altivec.h gcc-4.6.2/gcc/config/rs6000/altivec.h
+--- gcc-4.6.2-orig/gcc/config/rs6000/altivec.h 2011-02-02 23:42:19.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/altivec.h 2012-03-06 12:33:43.943038996 -0600
+@@ -322,6 +322,30 @@
+ #define vec_vsx_st __builtin_vec_vsx_st
+ #endif
+
++#ifdef __ALTIVEC2__
++/* New Altivec instructions */
++#define vec_absd __builtin_vec_absd
++#define vec_lvexbx __builtin_vec_lvexbx
++#define vec_lvexhx __builtin_vec_lvexhx
++#define vec_lvexwx __builtin_vec_lvexwx
++#define vec_stvexbx __builtin_vec_stvexbx
++#define vec_stvexhx __builtin_vec_stvexhx
++#define vec_stvexwx __builtin_vec_stvexwx
++#define vec_lvswx __builtin_vec_lvswx
++#define vec_lvswxl __builtin_vec_lvswxl
++#define vec_stvswx __builtin_vec_stvswx
++#define vec_stvswxl __builtin_vec_stvswxl
++#define vec_lvsm __builtin_vec_lvsm
++#define vec_lvtlx __builtin_vec_lvtlx
++#define vec_lvtlxl __builtin_vec_lvtlxl
++#define vec_lvtrx __builtin_vec_lvtrx
++#define vec_lvtrxl __builtin_vec_lvtrxl
++#define vec_stvflx __builtin_vec_stvflx
++#define vec_stvflxl __builtin_vec_stvflxl
++#define vec_stvfrx __builtin_vec_stvfrx
++#define vec_stvfrxl __builtin_vec_stvfrxl
++#endif
++
+ /* Predicates.
+ For C++, we use templates in order to allow non-parenthesized arguments.
+ For C, instead, we use macros since non-parenthesized arguments were
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/altivec.md gcc-4.6.2/gcc/config/rs6000/altivec.md
+--- gcc-4.6.2-orig/gcc/config/rs6000/altivec.md 2011-07-08 15:10:18.000000000 -0500
++++ gcc-4.6.2/gcc/config/rs6000/altivec.md 2012-03-06 12:24:35.058038999 -0600
+@@ -91,9 +91,11 @@
+ (UNSPEC_LVSL 194)
+ (UNSPEC_LVSR 195)
+ (UNSPEC_LVE 196)
++ (UNSPEC_LVEX 197)
+ (UNSPEC_STVX 201)
+ (UNSPEC_STVXL 202)
+ (UNSPEC_STVE 203)
++ (UNSPEC_STVEX 204)
+ (UNSPEC_SET_VSCR 213)
+ (UNSPEC_GET_VRSAVE 214)
+ (UNSPEC_LVX 215)
+@@ -123,6 +125,19 @@
+ (UNSPEC_STVLXL 241)
+ (UNSPEC_STVRX 242)
+ (UNSPEC_STVRXL 243)
++ (UNSPEC_LVTLX 244)
++ (UNSPEC_LVTLXL 245)
++ (UNSPEC_LVTRX 246)
++ (UNSPEC_LVTRXL 247)
++ (UNSPEC_STVFLX 248)
++ (UNSPEC_STVFLXL 249)
++ (UNSPEC_STVFRX 250)
++ (UNSPEC_STVFRXL 251)
++ (UNSPEC_LVSWX 252)
++ (UNSPEC_LVSWXL 253)
++ (UNSPEC_LVSM 254)
++ (UNSPEC_STVSWX 255)
++ (UNSPEC_STVSWXL 256)
+ (UNSPEC_VMULWHUB 308)
+ (UNSPEC_VMULWLUB 309)
+ (UNSPEC_VMULWHSB 310)
+@@ -143,6 +158,9 @@
+ (UNSPEC_VUPKLS_V4SF 325)
+ (UNSPEC_VUPKHU_V4SF 326)
+ (UNSPEC_VUPKLU_V4SF 327)
++ (UNSPEC_VABSDUB 328)
++ (UNSPEC_VABSDUH 329)
++ (UNSPEC_VABSDUW 330)
+ ])
+
+ (define_constants
+@@ -323,6 +341,34 @@
+
+ ;; Simple binary operations.
+
++;; absd
++(define_insn "altivec_vabsduw"
++ [(set (match_operand:V4SI 0 "register_operand" "=v")
++ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
++ (match_operand:V4SI 2 "register_operand" "v")]
++ UNSPEC_VABSDUW))]
++ "TARGET_ALTIVEC2"
++ "vabsduw %0,%1,%2"
++ [(set_attr "type" "vecsimple")])
++
++(define_insn "altivec_vabsduh"
++ [(set (match_operand:V8HI 0 "register_operand" "=v")
++ (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
++ (match_operand:V8HI 2 "register_operand" "v")]
++ UNSPEC_VABSDUH))]
++ "TARGET_ALTIVEC2"
++ "vabsduh %0,%1,%2"
++ [(set_attr "type" "vecsimple")])
++
++(define_insn "altivec_vabsdub"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
++ (match_operand:V16QI 2 "register_operand" "v")]
++ UNSPEC_VABSDUB))]
++ "TARGET_ALTIVEC2"
++ "vabsdub %0,%1,%2"
++ [(set_attr "type" "vecsimple")])
++
+ ;; add
+ (define_insn "add<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+@@ -1741,6 +1787,15 @@
+ "lvewx %0,%y1"
+ [(set_attr "type" "vecload")])
+
++(define_insn "altivec_lvex<VI_char>x"
++ [(parallel
++ [(set (match_operand:VI 0 "register_operand" "=v")
++ (match_operand:VI 1 "memory_operand" "Z"))
++ (unspec [(const_int 0)] UNSPEC_LVEX)])]
++ "TARGET_ALTIVEC2"
++ "lvex<VI_char>x %0,%y1"
++ [(set_attr "type" "vecload")])
++
+ (define_insn "altivec_lvxl"
+ [(parallel
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+@@ -1791,6 +1846,13 @@
+ "stvewx %1,%y0"
+ [(set_attr "type" "vecstore")])
+
++(define_insn "altivec_stvex<VI_char>x"
++ [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
++ (unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVEX))]
++ "TARGET_ALTIVEC2"
++ "stvex<VI_char>x %1,%y0"
++ [(set_attr "type" "vecstore")])
++
+ ;; Generate
+ ;; vspltis? SCRATCH0,0
+ ;; vsubu?m SCRATCH2,SCRATCH1,%1
+@@ -2358,7 +2420,7 @@
+ DONE;
+ }")
+
+-;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX, LVRXL,
++;; Vector SIMD PEM v2.06c defines LVLX, LVLXL, LVRX1, LVRXL,
+ ;; STVLX, STVLXL, STVVRX, STVRXL are available only on Cell.
+ (define_insn "altivec_lvlx"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+@@ -2394,8 +2456,8 @@
+
+ (define_insn "altivec_stvlx"
+ [(parallel
+- [(set (match_operand:V4SI 0 "memory_operand" "=Z")
+- (match_operand:V4SI 1 "register_operand" "v"))
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVLX)])]
+ "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+ "stvlx %1,%y0"
+@@ -2403,8 +2465,8 @@
+
+ (define_insn "altivec_stvlxl"
+ [(parallel
+- [(set (match_operand:V4SI 0 "memory_operand" "=Z")
+- (match_operand:V4SI 1 "register_operand" "v"))
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVLXL)])]
+ "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+ "stvlxl %1,%y0"
+@@ -2412,8 +2474,8 @@
+
+ (define_insn "altivec_stvrx"
+ [(parallel
+- [(set (match_operand:V4SI 0 "memory_operand" "=Z")
+- (match_operand:V4SI 1 "register_operand" "v"))
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVRX)])]
+ "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+ "stvrx %1,%y0"
+@@ -2421,13 +2483,123 @@
+
+ (define_insn "altivec_stvrxl"
+ [(parallel
+- [(set (match_operand:V4SI 0 "memory_operand" "=Z")
+- (match_operand:V4SI 1 "register_operand" "v"))
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVRXL)])]
+ "TARGET_ALTIVEC && rs6000_cpu == PROCESSOR_CELL"
+ "stvrxl %1,%y0"
+ [(set_attr "type" "vecstore")])
+
++(define_insn "altivec_lvtlx"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVTLX))]
++ "TARGET_ALTIVEC2"
++ "lvtlx %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_lvtlxl"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVTLXL))]
++ "TARGET_ALTIVEC2"
++ "lvtlxl %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_lvtrx"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVTRX))]
++ "TARGET_ALTIVEC2"
++ "lvtrx %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_lvtrxl"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVTRXL))]
++ "TARGET_ALTIVEC2"
++ "lvtrxl %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_stvflx"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVFLX)])]
++ "TARGET_ALTIVEC2"
++ "stvflx %1,%y0"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "altivec_stvflxl"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVFLXL)])]
++ "TARGET_ALTIVEC2"
++ "stvflxl %1,%y0"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "altivec_stvfrx"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVFRX)])]
++ "TARGET_ALTIVEC2"
++ "stvfrx %1,%y0"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "altivec_stvfrxl"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVFRXL)])]
++ "TARGET_ALTIVEC2"
++ "stvfrxl %1,%y0"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "altivec_lvswx"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVSWX))]
++ "TARGET_ALTIVEC2"
++ "lvswx %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_lvswxl"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVSWXL))]
++ "TARGET_ALTIVEC2"
++ "lvswxl %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_lvsm"
++ [(set (match_operand:V16QI 0 "register_operand" "=v")
++ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")]
++ UNSPEC_LVSM))]
++ "TARGET_ALTIVEC2"
++ "lvsm %0,%y1"
++ [(set_attr "type" "vecload")])
++
++(define_insn "altivec_stvswx"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVSWX)])]
++ "TARGET_ALTIVEC2"
++ "stvswx %1,%y0"
++ [(set_attr "type" "vecstore")])
++
++(define_insn "altivec_stvswxl"
++ [(parallel
++ [(set (match_operand:V16QI 0 "memory_operand" "=Z")
++ (match_operand:V16QI 1 "register_operand" "v"))
++ (unspec [(const_int 0)] UNSPEC_STVSWXL)])]
++ "TARGET_ALTIVEC2"
++ "stvswxl %1,%y0"
++ [(set_attr "type" "vecstore")])
++
+ (define_expand "vec_extract_evenv4si"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "")
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/e5500.md gcc-4.6.2/gcc/config/rs6000/e5500.md
+--- gcc-4.6.2-orig/gcc/config/rs6000/e5500.md 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/e5500.md 2012-03-06 12:16:07.590039001 -0600
+@@ -0,0 +1,176 @@
++;; Pipeline description for Freescale PowerPC e5500 core.
++;; Copyright (C) 2011 Free Software Foundation, Inc.
++;; Contributed by Edmar Wienskoski (edmar@freescale.com)
++;;
++;; This file is part of GCC.
++;;
++;; GCC is free software; you can redistribute it and/or modify it
++;; under the terms of the GNU General Public License as published
++;; by the Free Software Foundation; either version 3, or (at your
++;; option) any later version.
++;;
++;; GCC is distributed in the hope that it will be useful, but WITHOUT
++;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
++;; License for more details.
++;;
++;; You should have received a copy of the GNU General Public License
++;; along with GCC; see the file COPYING3. If not see
++;; <http://www.gnu.org/licenses/>.
++;;
++;; e5500 64-bit SFX(2), CFX, LSU, FPU, BU
++;; Max issue 3 insns/clock cycle (includes 1 branch)
++
++(define_automaton "e5500_most,e5500_long")
++(define_cpu_unit "e5500_decode_0,e5500_decode_1" "e5500_most")
++
++;; SFX.
++(define_cpu_unit "e5500_sfx_0,e5500_sfx_1" "e5500_most")
++
++;; CFX.
++(define_cpu_unit "e5500_cfx_stage0,e5500_cfx_stage1" "e5500_most")
++
++;; Non-pipelined division.
++(define_cpu_unit "e5500_cfx_div" "e5500_long")
++
++;; LSU.
++(define_cpu_unit "e5500_lsu" "e5500_most")
++
++;; FPU.
++(define_cpu_unit "e5500_fpu" "e5500_long")
++
++;; BU.
++(define_cpu_unit "e5500_bu" "e5500_most")
++
++;; The following units are used to make the automata deterministic.
++(define_cpu_unit "present_e5500_decode_0" "e5500_most")
++(define_cpu_unit "present_e5500_sfx_0" "e5500_most")
++(presence_set "present_e5500_decode_0" "e5500_decode_0")
++(presence_set "present_e5500_sfx_0" "e5500_sfx_0")
++
++;; Some useful abbreviations.
++(define_reservation "e5500_decode"
++ "e5500_decode_0|e5500_decode_1+present_e5500_decode_0")
++(define_reservation "e5500_sfx"
++ "e5500_sfx_0|e5500_sfx_1+present_e5500_sfx_0")
++
++;; SFX.
++(define_insn_reservation "e5500_sfx" 1
++ (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
++ shift,cntlz,exts")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx")
++
++(define_insn_reservation "e5500_sfx2" 2
++ (and (eq_attr "type" "cmp,compare,fast_compare,trap")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx")
++
++(define_insn_reservation "e5500_delayed" 2
++ (and (eq_attr "type" "var_shift_rotate,var_delayed_compare,popcnt")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx*2")
++
++(define_insn_reservation "e5500_two" 2
++ (and (eq_attr "type" "two")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_decode+e5500_sfx,e5500_sfx")
++
++(define_insn_reservation "e5500_three" 3
++ (and (eq_attr "type" "three")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,(e5500_decode+e5500_sfx)*2,e5500_sfx")
++
++;; SFX - Mfcr.
++(define_insn_reservation "e5500_mfcr" 4
++ (and (eq_attr "type" "mfcr")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx_0*4")
++
++;; SFX - Mtcrf.
++(define_insn_reservation "e5500_mtcrf" 1
++ (and (eq_attr "type" "mtcr")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx_0")
++
++;; SFX - Mtjmpr.
++(define_insn_reservation "e5500_mtjmpr" 1
++ (and (eq_attr "type" "mtjmpr,mfjmpr")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_sfx")
++
++;; CFX - Multiply.
++(define_insn_reservation "e5500_multiply" 4
++ (and (eq_attr "type" "imul")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_cfx_stage0,e5500_cfx_stage1")
++
++(define_insn_reservation "e5500_multiply_i" 5
++ (and (eq_attr "type" "imul2,imul3,imul_compare")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_cfx_stage0,\
++ e5500_cfx_stage0+e5500_cfx_stage1,e5500_cfx_stage1")
++
++;; CFX - Divide.
++(define_insn_reservation "e5500_divide" 16
++ (and (eq_attr "type" "idiv")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_cfx_stage0+e5500_cfx_div,\
++ e5500_cfx_div*15")
++
++(define_insn_reservation "e5500_divide_d" 26
++ (and (eq_attr "type" "ldiv")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_cfx_stage0+e5500_cfx_div,\
++ e5500_cfx_div*25")
++
++;; LSU - Loads.
++(define_insn_reservation "e5500_load" 3
++ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
++ load_l,sync")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_lsu")
++
++(define_insn_reservation "e5500_fpload" 4
++ (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_lsu")
++
++;; LSU - Stores.
++(define_insn_reservation "e5500_store" 3
++ (and (eq_attr "type" "store,store_ux,store_u,store_c")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_lsu")
++
++(define_insn_reservation "e5500_fpstore" 3
++ (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_lsu")
++
++;; FP.
++(define_insn_reservation "e5500_float" 7
++ (and (eq_attr "type" "fpsimple,fp,fpcompare,dmul")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_fpu")
++
++(define_insn_reservation "e5500_sdiv" 20
++ (and (eq_attr "type" "sdiv")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_fpu*20")
++
++(define_insn_reservation "e5500_ddiv" 35
++ (and (eq_attr "type" "ddiv")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_fpu*35")
++
++;; BU.
++(define_insn_reservation "e5500_branch" 1
++ (and (eq_attr "type" "jmpreg,branch,isync")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_bu")
++
++;; BU - CR logical.
++(define_insn_reservation "e5500_cr_logical" 1
++ (and (eq_attr "type" "cr_logical,delayed_cr")
++ (eq_attr "cpu" "ppce5500"))
++ "e5500_decode,e5500_bu")
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/e6500.md gcc-4.6.2/gcc/config/rs6000/e6500.md
+--- gcc-4.6.2-orig/gcc/config/rs6000/e6500.md 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/e6500.md 2012-03-06 12:16:25.573039002 -0600
+@@ -0,0 +1,213 @@
++;; Pipeline description for Freescale PowerPC e6500 core.
++;; Copyright (C) 2011 Free Software Foundation, Inc.
++;; Contributed by Edmar Wienskoski (edmar@freescale.com)
++;;
++;; This file is part of GCC.
++;;
++;; GCC is free software; you can redistribute it and/or modify it
++;; under the terms of the GNU General Public License as published
++;; by the Free Software Foundation; either version 3, or (at your
++;; option) any later version.
++;;
++;; GCC is distributed in the hope that it will be useful, but WITHOUT
++;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
++;; License for more details.
++;;
++;; You should have received a copy of the GNU General Public License
++;; along with GCC; see the file COPYING3. If not see
++;; <http://www.gnu.org/licenses/>.
++;;
++;; e6500 64-bit SFX(2), CFX, LSU, FPU, BU, VSFX, VCFX, VFPU, VPERM
++;; Max issue 3 insns/clock cycle (includes 1 branch)
++
++(define_automaton "e6500_most,e6500_long,e6500_vec")
++(define_cpu_unit "e6500_decode_0,e6500_decode_1" "e6500_most")
++
++;; SFX.
++(define_cpu_unit "e6500_sfx_0,e6500_sfx_1" "e6500_most")
++
++;; CFX.
++(define_cpu_unit "e6500_cfx_stage0,e6500_cfx_stage1" "e6500_most")
++
++;; Non-pipelined division.
++(define_cpu_unit "e6500_cfx_div" "e6500_long")
++
++;; LSU.
++(define_cpu_unit "e6500_lsu" "e6500_most")
++
++;; FPU.
++(define_cpu_unit "e6500_fpu" "e6500_long")
++
++;; BU.
++(define_cpu_unit "e6500_bu" "e6500_most")
++
++;; Altivec unit
++(define_cpu_unit "e6500_vec,e6500_vecperm" "e6500_vec")
++
++;; The following units are used to make the automata deterministic.
++(define_cpu_unit "present_e6500_decode_0" "e6500_most")
++(define_cpu_unit "present_e6500_sfx_0" "e6500_most")
++(presence_set "present_e6500_decode_0" "e6500_decode_0")
++(presence_set "present_e6500_sfx_0" "e6500_sfx_0")
++
++;; Some useful abbreviations.
++(define_reservation "e6500_decode"
++ "e6500_decode_0|e6500_decode_1+present_e6500_decode_0")
++(define_reservation "e6500_sfx"
++ "e6500_sfx_0|e6500_sfx_1+present_e6500_sfx_0")
++
++;; SFX.
++(define_insn_reservation "e6500_sfx" 1
++ (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
++ shift,cntlz,exts")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx")
++
++(define_insn_reservation "e6500_sfx2" 2
++ (and (eq_attr "type" "cmp,compare,fast_compare,trap")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx")
++
++(define_insn_reservation "e6500_delayed" 2
++ (and (eq_attr "type" "var_shift_rotate,var_delayed_compare,popcnt")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx*2")
++
++(define_insn_reservation "e6500_two" 2
++ (and (eq_attr "type" "two")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_decode+e6500_sfx,e6500_sfx")
++
++(define_insn_reservation "e6500_three" 3
++ (and (eq_attr "type" "three")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,(e6500_decode+e6500_sfx)*2,e6500_sfx")
++
++;; SFX - Mfcr.
++(define_insn_reservation "e6500_mfcr" 4
++ (and (eq_attr "type" "mfcr")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx_0*4")
++
++;; SFX - Mtcrf.
++(define_insn_reservation "e6500_mtcrf" 1
++ (and (eq_attr "type" "mtcr")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx_0")
++
++;; SFX - Mtjmpr.
++(define_insn_reservation "e6500_mtjmpr" 1
++ (and (eq_attr "type" "mtjmpr,mfjmpr")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_sfx")
++
++;; CFX - Multiply.
++(define_insn_reservation "e6500_multiply" 4
++ (and (eq_attr "type" "imul")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_cfx_stage0,e6500_cfx_stage1")
++
++(define_insn_reservation "e6500_multiply_i" 5
++ (and (eq_attr "type" "imul2,imul3,imul_compare")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_cfx_stage0,\
++ e6500_cfx_stage0+e6500_cfx_stage1,e6500_cfx_stage1")
++
++;; CFX - Divide.
++(define_insn_reservation "e6500_divide" 16
++ (and (eq_attr "type" "idiv")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_cfx_stage0+e6500_cfx_div,\
++ e6500_cfx_div*15")
++
++(define_insn_reservation "e6500_divide_d" 26
++ (and (eq_attr "type" "ldiv")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_cfx_stage0+e6500_cfx_div,\
++ e6500_cfx_div*25")
++
++;; LSU - Loads.
++(define_insn_reservation "e6500_load" 3
++ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
++ load_l,sync")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++(define_insn_reservation "e6500_fpload" 4
++ (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++(define_insn_reservation "e6500_vecload" 4
++ (and (eq_attr "type" "vecload")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++;; LSU - Stores.
++(define_insn_reservation "e6500_store" 3
++ (and (eq_attr "type" "store,store_ux,store_u,store_c")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++(define_insn_reservation "e6500_fpstore" 3
++ (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++(define_insn_reservation "e6500_vecstore" 4
++ (and (eq_attr "type" "vecstore")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_lsu")
++
++;; FP.
++(define_insn_reservation "e6500_float" 7
++ (and (eq_attr "type" "fpsimple,fp,fpcompare,dmul")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_fpu")
++
++(define_insn_reservation "e6500_sdiv" 20
++ (and (eq_attr "type" "sdiv")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_fpu*20")
++
++(define_insn_reservation "e6500_ddiv" 35
++ (and (eq_attr "type" "ddiv")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_fpu*35")
++
++;; BU.
++(define_insn_reservation "e6500_branch" 1
++ (and (eq_attr "type" "jmpreg,branch,isync")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_bu")
++
++;; BU - CR logical.
++(define_insn_reservation "e6500_cr_logical" 1
++ (and (eq_attr "type" "cr_logical,delayed_cr")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_bu")
++
++;; VSFX.
++(define_insn_reservation "e6500_vecsimple" 1
++ (and (eq_attr "type" "vecsimple,veccmp")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_vec")
++
++;; VCFX.
++(define_insn_reservation "e6500_veccomplex" 4
++ (and (eq_attr "type" "veccomplex")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_vec")
++
++;; VFPU.
++(define_insn_reservation "e6500_vecfloat" 6
++ (and (eq_attr "type" "vecfloat")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_vec")
++
++;; VPERM.
++(define_insn_reservation "e6500_vecperm" 2
++ (and (eq_attr "type" "vecperm")
++ (eq_attr "cpu" "ppce6500"))
++ "e6500_decode,e6500_vecperm")
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000-builtin.def gcc-4.6.2/gcc/config/rs6000/rs6000-builtin.def
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000-builtin.def 2011-02-21 15:38:21.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000-builtin.def 2012-03-06 12:37:40.248039025 -0600
+@@ -224,6 +224,9 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEBX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEHX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEWX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEXBX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEXHX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVEXWX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVXL, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVX, RS6000_BTC_MEM)
+@@ -231,14 +234,30 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVLXL, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVRX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_LVRXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVTLX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVTLXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVTRX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVTRXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVSWX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVSWXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_LVSM, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEBX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEHX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEWX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEXBX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEXHX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVEXWX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVXL, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVLX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVLXL, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVRX, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_STVRXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVFLX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVFLXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVFRX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVFRXL, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVSWX, RS6000_BTC_MEM)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_STVSWXL, RS6000_BTC_MEM)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPBFP_P, RS6000_BTC_FP_PURE)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPEQFP_P, RS6000_BTC_FP_PURE)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPEQUB_P, RS6000_BTC_CONST)
+@@ -275,6 +294,9 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_EXT_V4SF, RS6000_BTC_CONST)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_COPYSIGN_V4SF, RS6000_BTC_CONST)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VRECIPFP, RS6000_BTC_FP_PURE)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_ABSDUB, RS6000_BTC_CONST)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_ABSDUH, RS6000_BTC_CONST)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_ABSDUW, RS6000_BTC_CONST)
+
+ /* Altivec overloaded builtins. */
+ /* For now, don't set the classification for overloaded functions.
+@@ -286,6 +308,7 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPGT_P, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VCMPGE_P, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ABS, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ABSD, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ABSS, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ADD, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_ADDC, RS6000_BTC_MISC)
+@@ -321,10 +344,20 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEBX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEHX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEWX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEXBX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEXHX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVEXWX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVLX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVLXL, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVRX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVRXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVTLX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVTLXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVTRX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVTRXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVSWX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVSWXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVSM, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVSL, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_LVSR, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_MADD, RS6000_BTC_MISC)
+@@ -389,10 +422,19 @@
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEBX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEHX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEWX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEXBX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEXHX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVEXWX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVLX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVLXL, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVRX, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVRXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVFLX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVFLXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVFRX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVFRXL, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVSWX, RS6000_BTC_MISC)
++RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_STVSWXL, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_SUB, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_SUBC, RS6000_BTC_MISC)
+ RS6000_BUILTIN(ALTIVEC_BUILTIN_VEC_SUBS, RS6000_BTC_MISC)
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000.c gcc-4.6.2/gcc/config/rs6000/rs6000.c
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000.c 2011-09-18 17:01:56.000000000 -0500
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.c 2012-03-06 12:44:04.689039002 -0600
+@@ -779,6 +779,44 @@
+ 1, /* prefetch streams /*/
+ };
+
++/* Instruction costs on PPCE5500 processors. */
++static const
++struct processor_costs ppce5500_cost = {
++ COSTS_N_INSNS (5), /* mulsi */
++ COSTS_N_INSNS (5), /* mulsi_const */
++ COSTS_N_INSNS (5), /* mulsi_const9 */
++ COSTS_N_INSNS (5), /* muldi */
++ COSTS_N_INSNS (14), /* divsi */
++ COSTS_N_INSNS (14), /* divdi */
++ COSTS_N_INSNS (7), /* fp */
++ COSTS_N_INSNS (10), /* dmul */
++ COSTS_N_INSNS (36), /* sdiv */
++ COSTS_N_INSNS (66), /* ddiv */
++ 64, /* cache line size */
++ 32, /* l1 cache */
++ 128, /* l2 cache */
++ 1, /* prefetch streams /*/
++};
++
++/* Instruction costs on PPCE6500 processors. */
++static const
++struct processor_costs ppce6500_cost = {
++ COSTS_N_INSNS (5), /* mulsi */
++ COSTS_N_INSNS (5), /* mulsi_const */
++ COSTS_N_INSNS (5), /* mulsi_const9 */
++ COSTS_N_INSNS (5), /* muldi */
++ COSTS_N_INSNS (14), /* divsi */
++ COSTS_N_INSNS (14), /* divdi */
++ COSTS_N_INSNS (7), /* fp */
++ COSTS_N_INSNS (10), /* dmul */
++ COSTS_N_INSNS (36), /* sdiv */
++ COSTS_N_INSNS (66), /* ddiv */
++ 64, /* cache line size */
++ 32, /* l1 cache */
++ 128, /* l2 cache */
++ 1, /* prefetch streams /*/
++};
++
+ /* Instruction costs on AppliedMicro Titan processors. */
+ static const
+ struct processor_costs titan_cost = {
+@@ -1690,7 +1728,7 @@
+ | 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_ALTIVEC2)
+ };
+
+ /* Masks for instructions set at various powerpc ISAs. */
+@@ -1785,6 +1823,12 @@
+ | MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
+ | MASK_PPC_GFXOPT | MASK_ISEL},
++ {"e5500", PROCESSOR_PPCE5500, POWERPC_BASE_MASK | MASK_POWERPC64
++ | MASK_PPC_GFXOPT | MASK_ISEL | MASK_CMPB | MASK_POPCNTB
++ | MASK_POPCNTD},
++ {"e6500", PROCESSOR_PPCE6500, POWERPC_7400_MASK | MASK_POWERPC64
++ | MASK_MFCRF | MASK_ISEL | MASK_CMPB | MASK_POPCNTB | MASK_POPCNTD
++ | MASK_ALTIVEC2},
+ {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
+ {"970", PROCESSOR_POWER4,
+ POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
+@@ -2742,13 +2786,19 @@
+ : PROCESSOR_DEFAULT));
+
+ if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
+- || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
++ || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64
++ || rs6000_cpu == PROCESSOR_PPCE5500)
+ {
+ if (TARGET_ALTIVEC)
+ error ("AltiVec not supported in this target");
+ if (TARGET_SPE)
+ error ("SPE not supported in this target");
+ }
++ if (rs6000_cpu == PROCESSOR_PPCE6500)
++ {
++ if (TARGET_SPE)
++ error ("SPE not supported in this target");
++ }
+
+ /* Disable Cell microcode if we are optimizing for the Cell
+ and not optimizing for size. */
+@@ -2843,9 +2893,16 @@
+ user's opinion, though. */
+ if (rs6000_block_move_inline_limit == 0
+ && (rs6000_cpu == PROCESSOR_PPCE500MC
+- || rs6000_cpu == PROCESSOR_PPCE500MC64))
++ || rs6000_cpu == PROCESSOR_PPCE500MC64
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500))
+ rs6000_block_move_inline_limit = 128;
+
++ /* Those machines does not have fsqrt instruction */
++ if (rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500)
++ target_flags &= ~MASK_PPC_GPOPT;
++
+ /* store_one_arg depends on expand_block_move to handle at least the
+ size of reg_parm_stack_space. */
+ if (rs6000_block_move_inline_limit < (TARGET_POWERPC64 ? 64 : 32))
+@@ -2977,7 +3034,9 @@
+ #endif
+
+ if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
+- || rs6000_cpu == PROCESSOR_PPCE500MC64)
++ || rs6000_cpu == PROCESSOR_PPCE500MC64
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500)
+ {
+ /* The e500 and e500mc do not have string instructions, and we set
+ MASK_STRING above when optimizing for size. */
+@@ -3024,7 +3083,9 @@
+ || rs6000_cpu == PROCESSOR_POWER6
+ || rs6000_cpu == PROCESSOR_POWER7
+ || rs6000_cpu == PROCESSOR_PPCE500MC
+- || rs6000_cpu == PROCESSOR_PPCE500MC64);
++ || rs6000_cpu == PROCESSOR_PPCE500MC64
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500);
+
+ /* Allow debug switches to override the above settings. These are set to -1
+ in rs6000.opt to indicate the user hasn't directly set the switch. */
+@@ -3246,6 +3307,14 @@
+ rs6000_cost = &ppce500mc64_cost;
+ break;
+
++ case PROCESSOR_PPCE5500:
++ rs6000_cost = &ppce5500_cost;
++ break;
++
++ case PROCESSOR_PPCE6500:
++ rs6000_cost = &ppce6500_cost;
++ break;
++
+ case PROCESSOR_TITAN:
+ rs6000_cost = &titan_cost;
+ break;
+@@ -10212,6 +10281,9 @@
+ { MASK_ALTIVEC, CODE_FOR_addv8hi3, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
+ { MASK_ALTIVEC, CODE_FOR_addv4si3, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
+ { MASK_ALTIVEC, CODE_FOR_addv4sf3, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
++ { MASK_ALTIVEC2, CODE_FOR_altivec_vabsdub, "__builtin_altivec_vabsdub", ALTIVEC_BUILTIN_ABSDUB },
++ { MASK_ALTIVEC2, CODE_FOR_altivec_vabsduh, "__builtin_altivec_vabsduh", ALTIVEC_BUILTIN_ABSDUH },
++ { MASK_ALTIVEC2, CODE_FOR_altivec_vabsduw, "__builtin_altivec_vabsduw", ALTIVEC_BUILTIN_ABSDUW },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
+@@ -10372,6 +10444,7 @@
+ { MASK_VSX, CODE_FOR_vec_interleave_highv2df, "__builtin_vsx_mergeh_2df", VSX_BUILTIN_VEC_MERGEH_V2DF },
+ { MASK_VSX, CODE_FOR_vec_interleave_highv2di, "__builtin_vsx_mergeh_2di", VSX_BUILTIN_VEC_MERGEH_V2DI },
+
++ { MASK_ALTIVEC2, CODE_FOR_nothing, "__builtin_vec_absd", ALTIVEC_BUILTIN_VEC_ABSD },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
+ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
+@@ -11803,6 +11876,12 @@
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, exp);
+ case ALTIVEC_BUILTIN_STVEWX:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, exp);
++ case ALTIVEC_BUILTIN_STVEXBX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvexbx, exp);
++ case ALTIVEC_BUILTIN_STVEXHX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvexhx, exp);
++ case ALTIVEC_BUILTIN_STVEXWX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvexwx, exp);
+ case ALTIVEC_BUILTIN_STVXL:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, exp);
+
+@@ -11814,6 +11893,18 @@
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrx, exp);
+ case ALTIVEC_BUILTIN_STVRXL:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvrxl, exp);
++ case ALTIVEC_BUILTIN_STVFLX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvflx, exp);
++ case ALTIVEC_BUILTIN_STVFLXL:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvflxl, exp);
++ case ALTIVEC_BUILTIN_STVFRX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvfrx, exp);
++ case ALTIVEC_BUILTIN_STVFRXL:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvfrxl, exp);
++ case ALTIVEC_BUILTIN_STVSWX:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvswx, exp);
++ case ALTIVEC_BUILTIN_STVSWXL:
++ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvswxl, exp);
+
+ case VSX_BUILTIN_STXVD2X_V2DF:
+ return altivec_expand_stv_builtin (CODE_FOR_vsx_store_v2df, exp);
+@@ -11948,6 +12039,15 @@
+ case ALTIVEC_BUILTIN_LVEWX:
+ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx,
+ exp, target, false);
++ case ALTIVEC_BUILTIN_LVEXBX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvexbx,
++ exp, target, false);
++ case ALTIVEC_BUILTIN_LVEXHX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvexhx,
++ exp, target, false);
++ case ALTIVEC_BUILTIN_LVEXWX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvexwx,
++ exp, target, false);
+ case ALTIVEC_BUILTIN_LVXL:
+ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl,
+ exp, target, false);
+@@ -11966,6 +12066,27 @@
+ case ALTIVEC_BUILTIN_LVRXL:
+ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvrxl,
+ exp, target, true);
++ case ALTIVEC_BUILTIN_LVTLX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvtlx,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVTLXL:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvtlxl,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVTRX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvtrx,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVTRXL:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvtrxl,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVSWX:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvswx,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVSWXL:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvswxl,
++ exp, target, true);
++ case ALTIVEC_BUILTIN_LVSM:
++ return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsm,
++ exp, target, true);
+ case VSX_BUILTIN_LXVD2X_V2DF:
+ return altivec_expand_lv_builtin (CODE_FOR_vsx_load_v2df,
+ exp, target, false);
+@@ -13278,6 +13399,9 @@
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvexbx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEXBX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvexhx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEXHX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvexwx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVEXWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVXL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVX);
+@@ -13285,6 +13409,9 @@
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvexbx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEXBX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvexhx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEXHX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvexwx", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVEXWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL);
+@@ -13293,12 +13420,18 @@
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvexbx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEXBX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvexhx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEXHX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvexwx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEXWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvexwx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEXWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvexbx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEXBX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvexhx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEXHX);
+
+ def_builtin (MASK_VSX, "__builtin_vsx_lxvd2x_v2df", v2df_ftype_long_pcvoid,
+ VSX_BUILTIN_LXVD2X_V2DF);
+@@ -13351,6 +13484,33 @@
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVRXL);
+ }
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvtlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVTLX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvtlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVTLXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvtrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVTRX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvtrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVTRXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvtlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVTLX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvtlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVTLXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvtrx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVTRX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvtrxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVTRXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvflx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVFLX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvflxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVFLXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvfrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVFRX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvfrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVFRXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvflx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVFLX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvflxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVFLXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvfrx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVFRX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvfrxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVFRXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvswx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvswxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSWXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvswx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvswxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSWXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_lvsm", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVSM);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_lvsm", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSM);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvswx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVSWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_altivec_stvswxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVSWXL);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvswx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVSWX);
++ def_builtin (MASK_ALTIVEC2, "__builtin_vec_stvswxl", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_VEC_STVSWXL);
++
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_splats", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_SPLATS);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_promote", opaque_ftype_opaque, ALTIVEC_BUILTIN_VEC_PROMOTE);
+@@ -13668,6 +13828,9 @@
+ case ALTIVEC_BUILTIN_VMULEUH_UNS:
+ case ALTIVEC_BUILTIN_VMULOUB_UNS:
+ case ALTIVEC_BUILTIN_VMULOUH_UNS:
++ case ALTIVEC_BUILTIN_ABSDUB:
++ case ALTIVEC_BUILTIN_ABSDUH:
++ case ALTIVEC_BUILTIN_ABSDUW:
+ h.uns_p[0] = 1;
+ h.uns_p[1] = 1;
+ h.uns_p[2] = 1;
+@@ -23250,6 +23413,7 @@
+ || rs6000_cpu_attr == CPU_PPC750
+ || rs6000_cpu_attr == CPU_PPC7400
+ || rs6000_cpu_attr == CPU_PPC7450
++ || rs6000_cpu_attr == CPU_PPCE5500
+ || rs6000_cpu_attr == CPU_POWER4
+ || rs6000_cpu_attr == CPU_POWER5
+ || rs6000_cpu_attr == CPU_POWER7
+@@ -23794,6 +23958,8 @@
+ case CPU_PPCE300C3:
+ case CPU_PPCE500MC:
+ case CPU_PPCE500MC64:
++ case CPU_PPCE5500:
++ case CPU_PPCE6500:
+ case CPU_TITAN:
+ return 2;
+ case CPU_RIOS2:
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000-c.c gcc-4.6.2/gcc/config/rs6000/rs6000-c.c
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000-c.c 2011-02-02 23:42:19.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000-c.c 2012-03-06 12:54:55.964038969 -0600
+@@ -310,6 +310,8 @@
+ /* Enable context-sensitive macros. */
+ cpp_get_callbacks (pfile)->macro_to_expand = rs6000_macro_to_expand;
+ }
++ if (TARGET_ALTIVEC2)
++ builtin_define ("__ALTIVEC2__");
+ }
+ if (rs6000_cpu == PROCESSOR_CELL)
+ builtin_define ("__PPU__");
+@@ -569,6 +571,24 @@
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+
+ /* Binary AltiVec/VSX builtins. */
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUB,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUB,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUB,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUH,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUH,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUH,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUW,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUW,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_ABSD, ALTIVEC_BUILTIN_ABSDUW,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+@@ -1084,6 +1104,24 @@
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEBX, ALTIVEC_BUILTIN_LVEBX,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXWX, ALTIVEC_BUILTIN_LVEXWX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXWX, ALTIVEC_BUILTIN_LVEXWX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXWX, ALTIVEC_BUILTIN_LVEXWX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXWX, ALTIVEC_BUILTIN_LVEXWX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXWX, ALTIVEC_BUILTIN_LVEXWX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXHX, ALTIVEC_BUILTIN_LVEXHX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXHX, ALTIVEC_BUILTIN_LVEXHX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXBX, ALTIVEC_BUILTIN_LVEXBX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVEXBX, ALTIVEC_BUILTIN_LVEXBX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+@@ -1336,6 +1374,258 @@
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVRXL, ALTIVEC_BUILTIN_LVRXL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLX, ALTIVEC_BUILTIN_LVTLX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTLXL, ALTIVEC_BUILTIN_LVTLXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRX, ALTIVEC_BUILTIN_LVTRX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVTRXL, ALTIVEC_BUILTIN_LVTRXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWX, ALTIVEC_BUILTIN_LVSWX,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSWXL, ALTIVEC_BUILTIN_LVSWXL,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
++ { ALTIVEC_BUILTIN_VEC_LVSM, ALTIVEC_BUILTIN_LVSM,
++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUB,
+@@ -2812,6 +3102,46 @@
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXWX, ALTIVEC_BUILTIN_STVEXWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXHX, ALTIVEC_BUILTIN_STVEXHX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
++ { ALTIVEC_BUILTIN_VEC_STVEXBX, ALTIVEC_BUILTIN_STVEXBX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+@@ -3016,6 +3346,222 @@
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_STVRXL, ALTIVEC_BUILTIN_STVRXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLX, ALTIVEC_BUILTIN_STVFLX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFLXL, ALTIVEC_BUILTIN_STVFLXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRX, ALTIVEC_BUILTIN_STVFRX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVFRXL, ALTIVEC_BUILTIN_STVFRXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWX, ALTIVEC_BUILTIN_STVSWX,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
++ { ALTIVEC_BUILTIN_VEC_STVSWXL, ALTIVEC_BUILTIN_STVSWXL,
++ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000.h gcc-4.6.2/gcc/config/rs6000/rs6000.h
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000.h 2011-07-27 13:17:15.000000000 -0500
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.h 2012-03-06 12:16:25.582039002 -0600
+@@ -168,6 +168,8 @@
+ %{mcpu=e300c3: -me300} \
+ %{mcpu=e500mc: -me500mc} \
+ %{mcpu=e500mc64: -me500mc64} \
++%{mcpu=e5500: -me5500} \
++%{mcpu=e6500: -me6500} \
+ %{maltivec: -maltivec} \
+ %{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \
+ -many"
+@@ -477,13 +479,15 @@
+
+ #define TARGET_FCTIDZ TARGET_FCFID
+ #define TARGET_STFIWX TARGET_PPC_GFXOPT
+-#define TARGET_LFIWAX TARGET_CMPB
+-#define TARGET_LFIWZX TARGET_POPCNTD
+-#define TARGET_FCFIDS TARGET_POPCNTD
+-#define TARGET_FCFIDU TARGET_POPCNTD
+-#define TARGET_FCFIDUS TARGET_POPCNTD
+-#define TARGET_FCTIDUZ TARGET_POPCNTD
+-#define TARGET_FCTIWUZ TARGET_POPCNTD
++#define TARGET_LFIWAX (TARGET_CMPB && rs6000_cpu != PROCESSOR_PPCE5500 \
++ && rs6000_cpu != PROCESSOR_PPCE6500)
++#define TARGET_LFIWZX (TARGET_POPCNTD && rs6000_cpu != PROCESSOR_PPCE5500 \
++ && rs6000_cpu != PROCESSOR_PPCE6500)
++#define TARGET_FCFIDS TARGET_LFIWZX
++#define TARGET_FCFIDU TARGET_LFIWZX
++#define TARGET_FCFIDUS TARGET_LFIWZX
++#define TARGET_FCTIDUZ TARGET_LFIWZX
++#define TARGET_FCTIWUZ TARGET_LFIWZX
+
+ /* E500 processors only support plain "sync", not lwsync. */
+ #define TARGET_NO_LWSYNC TARGET_E500
+@@ -494,10 +498,14 @@
+
+ #define TARGET_FRE (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_DOUBLE_FLOAT \
+- && (TARGET_POPCNTB || VECTOR_UNIT_VSX_P (DFmode)))
++ && (TARGET_POPCNTB || VECTOR_UNIT_VSX_P (DFmode)) \
++ && rs6000_cpu != PROCESSOR_PPCE5500 \
++ && rs6000_cpu != PROCESSOR_PPCE6500)
+
+ #define TARGET_FRSQRTES (TARGET_HARD_FLOAT && TARGET_POPCNTB \
+- && TARGET_FPRS && TARGET_SINGLE_FLOAT)
++ && TARGET_FPRS && TARGET_SINGLE_FLOAT \
++ && rs6000_cpu != PROCESSOR_PPCE5500 \
++ && rs6000_cpu != PROCESSOR_PPCE6500)
+
+ #define TARGET_FRSQRTE (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && TARGET_DOUBLE_FLOAT \
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000.md gcc-4.6.2/gcc/config/rs6000/rs6000.md
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000.md 2011-09-19 11:41:20.000000000 -0500
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.md 2012-03-06 12:16:25.584039002 -0600
+@@ -126,7 +126,7 @@
+ \f
+ ;; Define an insn type attribute. This is used in function unit delay
+ ;; computations.
+-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel"
++(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt"
+ (const_string "integer"))
+
+ ;; Define floating point instruction sub-types for use with Xfpu.md
+@@ -148,7 +148,7 @@
+ ;; Processor type -- this attribute must exactly match the processor_type
+ ;; enumeration in rs6000.h.
+
+-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2,titan"
++(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,power4,power5,power6,power7,cell,ppca2,titan"
+ (const (symbol_ref "rs6000_cpu_attr")))
+
+
+@@ -176,6 +176,8 @@
+ (include "e300c2c3.md")
+ (include "e500mc.md")
+ (include "e500mc64.md")
++(include "e5500.md")
++(include "e6500.md")
+ (include "power4.md")
+ (include "power5.md")
+ (include "power6.md")
+@@ -2302,13 +2304,17 @@
+ (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
+ UNSPEC_POPCNTB))]
+ "TARGET_POPCNTB"
+- "popcntb %0,%1")
++ "popcntb %0,%1"
++ [(set_attr "length" "4")
++ (set_attr "type" "popcnt")])
+
+ (define_insn "popcntd<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
+ "TARGET_POPCNTD"
+- "popcnt<wd> %0,%1")
++ "popcnt<wd> %0,%1"
++ [(set_attr "length" "4")
++ (set_attr "type" "popcnt")])
+
+ (define_expand "popcount<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+@@ -5957,10 +5963,10 @@
+ && ((TARGET_PPC_GFXOPT
+ && !HONOR_NANS (<MODE>mode)
+ && !HONOR_SIGNED_ZEROS (<MODE>mode))
+- || TARGET_CMPB
++ || TARGET_LFIWAX
+ || VECTOR_UNIT_VSX_P (<MODE>mode))"
+ {
+- if (TARGET_CMPB || VECTOR_UNIT_VSX_P (<MODE>mode))
++ if (TARGET_LFIWAX || VECTOR_UNIT_VSX_P (<MODE>mode))
+ {
+ emit_insn (gen_copysign<mode>3_fcpsgn (operands[0], operands[1],
+ operands[2]));
+@@ -5979,7 +5985,7 @@
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<rreg2>")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<rreg2>")]
+ UNSPEC_COPYSIGN))]
+- "TARGET_CMPB && !VECTOR_UNIT_VSX_P (<MODE>mode)"
++ "TARGET_LFIWAX && !VECTOR_UNIT_VSX_P (<MODE>mode)"
+ "fcpsgn %0,%2,%1"
+ [(set_attr "type" "fp")])
+
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000.opt gcc-4.6.2/gcc/config/rs6000/rs6000.opt
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000.opt 2010-11-29 19:47:54.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000.opt 2012-03-06 12:16:25.584039002 -0600
+@@ -179,6 +179,10 @@
+ Target Report Mask(ALTIVEC) Save
+ Use AltiVec instructions
+
++maltivec2
++Target Report Mask(ALTIVEC2) Save
++Use AltiVec PowerPC V2.07 instructions
++
+ mhard-dfp
+ Target Report Mask(DFP) Save
+ Use decimal floating point instructions
+diff -ruN gcc-4.6.2-orig/gcc/config/rs6000/rs6000-opts.h gcc-4.6.2/gcc/config/rs6000/rs6000-opts.h
+--- gcc-4.6.2-orig/gcc/config/rs6000/rs6000-opts.h 2010-11-19 11:27:18.000000000 -0600
++++ gcc-4.6.2/gcc/config/rs6000/rs6000-opts.h 2012-03-06 12:16:25.584039002 -0600
+@@ -53,6 +53,8 @@
+ PROCESSOR_PPCE300C3,
+ PROCESSOR_PPCE500MC,
+ PROCESSOR_PPCE500MC64,
++ PROCESSOR_PPCE5500,
++ PROCESSOR_PPCE6500,
+ PROCESSOR_POWER4,
+ PROCESSOR_POWER5,
+ PROCESSOR_POWER6,
+diff -ruN gcc-4.6.2-orig/gcc/config.gcc gcc-4.6.2/gcc/config.gcc
+--- gcc-4.6.2-orig/gcc/config.gcc 2011-07-22 11:44:50.000000000 -0500
++++ gcc-4.6.2/gcc/config.gcc 2012-03-06 12:16:25.585039002 -0600
+@@ -396,7 +396,7 @@
+ extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
+ need_64bit_hwint=yes
+ case x$with_cpu in
+- xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64)
++ xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500)
+ cpu_is_64bit=yes
+ ;;
+ esac
+@@ -3501,8 +3501,8 @@
+ | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
+ | 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
+ | 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
+- | a2 | e300c[23] | 854[08] | e500mc | e500mc64 | titan\
+- | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
++ | a2 | e300c[23] | 854[08] | e500mc | e500mc64 | e5500 | e6500 \
++ | titan | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
+ # OK
+ ;;
+ *)
+diff -ruN gcc-4.6.2-orig/gcc/doc/extend.texi gcc-4.6.2/gcc/doc/extend.texi
+--- gcc-4.6.2-orig/gcc/doc/extend.texi 2011-10-24 09:55:45.000000000 -0500
++++ gcc-4.6.2/gcc/doc/extend.texi 2012-03-06 12:56:49.399039002 -0600
+@@ -12509,6 +12509,291 @@
+ @samp{vec_vsx_st} builtins will always generate the VSX @samp{LXVD2X},
+ @samp{LXVW4X}, @samp{STXVD2X}, and @samp{STXVW4X} instructions.
+
++Using @option{-maltivec2} will extend the Altivec interface with the
++following additional functions:
++
++@smallexample
++vector unsigned char vec_absd (vector unsigned char, vector unsigned char);
++vector unsigned char vec_absd (vector bool char, vector unsigned char);
++vector unsigned char vec_absd (vector unsigned char, vector bool char);
++vector unsigned short vec_absd (vector unsigned short, vector unsigned short);
++vector unsigned short vec_absd (vector bool short, vector unsigned short);
++vector unsigned short vec_absd (vector unsigned short, vector bool short);
++vector unsigned int vec_absd (vector unsigned int, vector unsigned int);
++vector unsigned int vec_absd (vector bool int, vector unsigned int);
++vector unsigned int vec_absd (vector unsigned int, vector bool int);
++
++vector signed char vec_lvexbx (long, signed char *);
++vector unsigned char vec_lvexbx (long, unsigned char *);
++vector signed short vec_lvexhx (long, signed short *);
++vector unsigned short vec_lvexhx (long, unsigned short *);
++vector float vec_lvexwx (long, float *);
++vector signed int vec_lvexwx (long, signed int *);
++vector unsigned int vec_lvexwx (long, unsigned int *);
++vector signed int vec_lvexwx (long, signed long *);
++vector unsigned int vec_lvexwx (long, unsigned long *);
++
++void vec_stvexbx (vector signed char, long, signed char *);
++void vec_stvexbx (vector unsigned char, long, unsigned char *);
++void vec_stvexbx (vector bool char, long, signed char *);
++void vec_stvexbx (vector bool char, long, unsigned char *);
++void vec_stvexbx (vector signed char, long, void *);
++void vec_stvexbx (vector unsigned char, long, void *);
++void vec_stvexhx (vector signed short, long, signed short *);
++void vec_stvexhx (vector unsigned short, long, unsigned short *);
++void vec_stvexhx (vector bool short, long, signed short *);
++void vec_stvexhx (vector bool short, long, unsigned short *);
++void vec_stvexhx (vector signed short, long, void *);
++void vec_stvexhx (vector unsigned short, long, void *);
++void vec_stvexwx (vector float, long, float *);
++void vec_stvexwx (vector signed int, long, signed int *);
++void vec_stvexwx (vector unsigned int, long, unsigned int *);
++void vec_stvexwx (vector bool int, long, signed int *);
++void vec_stvexwx (vector bool int, long, unsigned int *);
++void vec_stvexwx (vector float, long, void *);
++void vec_stvexwx (vector signed int, long, void *);
++void vec_stvexwx (vector unsigned int, long, void *);
++
++vector float vec_lvtlx (long, vector float *);
++vector float vec_lvtlx (long, float *);
++vector bool int vec_lvtlx (long, vector bool int *);
++vector signed int vec_lvtlx (long, vector signed int *);
++vector signed int vec_lvtlx (long, signed int *);
++vector unsigned int vec_lvtlx (long, vector unsigned int *);
++vector unsigned int vec_lvtlx (long, unsigned int *);
++vector bool short vec_lvtlx (long, vector bool short *);
++vector pixel vec_lvtlx (long, vector pixel *);
++vector signed short vec_lvtlx (long, vector signed short *);
++vector signed short vec_lvtlx (long, signed short *);
++vector unsigned short vec_lvtlx (long, vector unsigned short *);
++vector unsigned short vec_lvtlx (long, unsigned short *);
++vector bool char vec_lvtlx (long, vector bool char *);
++vector signed char vec_lvtlx (long, vector signed char *);
++vector signed char vec_lvtlx (long, signed char *);
++vector unsigned char vec_lvtlx (long, vector unsigned char *);
++vector unsigned char vec_lvtlx (long, unsigned char *);
++vector float vec_lvtlxl (long, vector float *);
++vector float vec_lvtlxl (long, float *);
++vector bool int vec_lvtlxl (long, vector bool int *);
++vector signed int vec_lvtlxl (long, vector signed int *);
++vector signed int vec_lvtlxl (long, signed int *);
++vector unsigned int vec_lvtlxl (long, vector unsigned int *);
++vector unsigned int vec_lvtlxl (long, unsigned int *);
++vector bool short vec_lvtlxl (long, vector bool short *);
++vector pixel vec_lvtlxl (long, vector pixel *);
++vector signed short vec_lvtlxl (long, vector signed short *);
++vector signed short vec_lvtlxl (long, signed short *);
++vector unsigned short vec_lvtlxl (long, vector unsigned short *);
++vector unsigned short vec_lvtlxl (long, unsigned short *);
++vector bool char vec_lvtlxl (long, vector bool char *);
++vector signed char vec_lvtlxl (long, vector signed char *);
++vector signed char vec_lvtlxl (long, signed char *);
++vector unsigned char vec_lvtlxl (long, vector unsigned char *);
++vector unsigned char vec_lvtlxl (long, unsigned char *);
++vector float vec_lvtrx (long, vector float *);
++vector float vec_lvtrx (long, float *);
++vector bool int vec_lvtrx (long, vector bool int *);
++vector signed int vec_lvtrx (long, vector signed int *);
++vector signed int vec_lvtrx (long, signed int *);
++vector unsigned int vec_lvtrx (long, vector unsigned int *);
++vector unsigned int vec_lvtrx (long, unsigned int *);
++vector bool short vec_lvtrx (long, vector bool short *);
++vector pixel vec_lvtrx (long, vector pixel *);
++vector signed short vec_lvtrx (long, vector signed short *);
++vector signed short vec_lvtrx (long, signed short *);
++vector unsigned short vec_lvtrx (long, vector unsigned short *);
++vector unsigned short vec_lvtrx (long, unsigned short *);
++vector bool char vec_lvtrx (long, vector bool char *);
++vector signed char vec_lvtrx (long, vector signed char *);
++vector signed char vec_lvtrx (long, signed char *);
++vector unsigned char vec_lvtrx (long, vector unsigned char *);
++vector unsigned char vec_lvtrx (long, unsigned char *);
++vector float vec_lvtrxl (long, vector float *);
++vector float vec_lvtrxl (long, float *);
++vector bool int vec_lvtrxl (long, vector bool int *);
++vector signed int vec_lvtrxl (long, vector signed int *);
++vector signed int vec_lvtrxl (long, signed int *);
++vector unsigned int vec_lvtrxl (long, vector unsigned int *);
++vector unsigned int vec_lvtrxl (long, unsigned int *);
++vector bool short vec_lvtrxl (long, vector bool short *);
++vector pixel vec_lvtrxl (long, vector pixel *);
++vector signed short vec_lvtrxl (long, vector signed short *);
++vector signed short vec_lvtrxl (long, signed short *);
++vector unsigned short vec_lvtrxl (long, vector unsigned short *);
++vector unsigned short vec_lvtrxl (long, unsigned short *);
++vector bool char vec_lvtrxl (long, vector bool char *);
++vector signed char vec_lvtrxl (long, vector signed char *);
++vector signed char vec_lvtrxl (long, signed char *);
++vector unsigned char vec_lvtrxl (long, vector unsigned char *);
++vector unsigned char vec_lvtrxl (long, unsigned char *);
++
++void vec_stvflx (vector float, long, vector float *);
++void vec_stvflx (vector float, long, float *);
++void vec_stvflx (vector bool int, long, vector bool int *);
++void vec_stvflx (vector signed int, long, vector signed int *);
++void vec_stvflx (vector signed int, long, signed int *);
++void vec_stvflx (vector unsigned int, long, vector unsigned int *);
++void vec_stvflx (vector unsigned int, long, unsigned int *);
++void vec_stvflx (vector bool short, long, vector bool short *);
++void vec_stvflx (vector pixel, long, vector pixel *);
++void vec_stvflx (vector signed short, long, vector signed short *);
++void vec_stvflx (vector signed short, long, signed short *);
++void vec_stvflx (vector unsigned short, long, vector unsigned short *);
++void vec_stvflx (vector unsigned short, long, unsigned short *);
++void vec_stvflx (vector bool char, long, vector bool char *);
++void vec_stvflx (vector signed char, long, vector signed char *);
++void vec_stvflx (vector signed char, long, signed char *);
++void vec_stvflx (vector unsigned char, long, vector unsigned char *);
++void vec_stvflx (vector unsigned char, long, unsigned char *);
++void vec_stvflxl (vector float, long, vector float *);
++void vec_stvflxl (vector float, long, float *);
++void vec_stvflxl (vector bool int, long, vector bool int *);
++void vec_stvflxl (vector signed int, long, vector signed int *);
++void vec_stvflxl (vector signed int, long, signed int *);
++void vec_stvflxl (vector unsigned int, long, vector unsigned int *);
++void vec_stvflxl (vector unsigned int, long, unsigned int *);
++void vec_stvflxl (vector bool short, long, vector bool short *);
++void vec_stvflxl (vector pixel, long, vector pixel *);
++void vec_stvflxl (vector signed short, long, vector signed short *);
++void vec_stvflxl (vector signed short, long, signed short *);
++void vec_stvflxl (vector unsigned short, long, vector unsigned short *);
++void vec_stvflxl (vector unsigned short, long, unsigned short *);
++void vec_stvflxl (vector bool char, long, vector bool char *);
++void vec_stvflxl (vector signed char, long, vector signed char *);
++void vec_stvflxl (vector signed char, long, signed char *);
++void vec_stvflxl (vector unsigned char, long, vector unsigned char *);
++void vec_stvflxl (vector unsigned char, long, unsigned char *);
++void vec_stvfrx (vector float, long, vector float *);
++void vec_stvfrx (vector float, long, float *);
++void vec_stvfrx (vector bool int, long, vector bool int *);
++void vec_stvfrx (vector signed int, long, vector signed int *);
++void vec_stvfrx (vector signed int, long, signed int *);
++void vec_stvfrx (vector unsigned int, long, vector unsigned int *);
++void vec_stvfrx (vector unsigned int, long, unsigned int *);
++void vec_stvfrx (vector bool short, long, vector bool short *);
++void vec_stvfrx (vector pixel, long, vector pixel *);
++void vec_stvfrx (vector signed short, long, vector signed short *);
++void vec_stvfrx (vector signed short, long, signed short *);
++void vec_stvfrx (vector unsigned short, long, vector unsigned short *);
++void vec_stvfrx (vector unsigned short, long, unsigned short *);
++void vec_stvfrx (vector bool char, long, vector bool char *);
++void vec_stvfrx (vector signed char, long, vector signed char *);
++void vec_stvfrx (vector signed char, long, signed char *);
++void vec_stvfrx (vector unsigned char, long, vector unsigned char *);
++void vec_stvfrx (vector unsigned char, long, unsigned char *);
++void vec_stvfrxl (vector float, long, vector float *);
++void vec_stvfrxl (vector float, long, float *);
++void vec_stvfrxl (vector bool int, long, vector bool int *);
++void vec_stvfrxl (vector signed int, long, vector signed int *);
++void vec_stvfrxl (vector signed int, long, signed int *);
++void vec_stvfrxl (vector unsigned int, long, vector unsigned int *);
++void vec_stvfrxl (vector unsigned int, long, unsigned int *);
++void vec_stvfrxl (vector bool short, long, vector bool short *);
++void vec_stvfrxl (vector pixel, long, vector pixel *);
++void vec_stvfrxl (vector signed short, long, vector signed short *);
++void vec_stvfrxl (vector signed short, long, signed short *);
++void vec_stvfrxl (vector unsigned short, long, vector unsigned short *);
++void vec_stvfrxl (vector unsigned short, long, unsigned short *);
++void vec_stvfrxl (vector bool char, long, vector bool char *);
++void vec_stvfrxl (vector signed char, long, vector signed char *);
++void vec_stvfrxl (vector signed char, long, signed char *);
++void vec_stvfrxl (vector unsigned char, long, vector unsigned char *);
++void vec_stvfrxl (vector unsigned char, long, unsigned char *);
++
++vector float vec_lvswx (long, vector float *);
++vector float vec_lvswx (long, float *);
++vector bool int vec_lvswx (long, vector bool int *);
++vector signed int vec_lvswx (long, vector signed int *);
++vector signed int vec_lvswx (long, signed int *);
++vector unsigned int vec_lvswx (long, vector unsigned int *);
++vector unsigned int vec_lvswx (long, unsigned int *);
++vector bool short vec_lvswx (long, vector bool short *);
++vector pixel vec_lvswx (long, vector pixel *);
++vector signed short vec_lvswx (long, vector signed short *);
++vector signed short vec_lvswx (long, signed short *);
++vector unsigned short vec_lvswx (long, vector unsigned short *);
++vector unsigned short vec_lvswx (long, unsigned short *);
++vector bool char vec_lvswx (long, vector bool char *);
++vector signed char vec_lvswx (long, vector signed char *);
++vector signed char vec_lvswx (long, signed char *);
++vector unsigned char vec_lvswx (long, vector unsigned char *);
++vector unsigned char vec_lvswx (long, unsigned char *);
++vector float vec_lvswxl (long, vector float *);
++vector float vec_lvswxl (long, float *);
++vector bool int vec_lvswxl (long, vector bool int *);
++vector signed int vec_lvswxl (long, vector signed int *);
++vector signed int vec_lvswxl (long, signed int *);
++vector unsigned int vec_lvswxl (long, vector unsigned int *);
++vector unsigned int vec_lvswxl (long, unsigned int *);
++vector bool short vec_lvswxl (long, vector bool short *);
++vector pixel vec_lvswxl (long, vector pixel *);
++vector signed short vec_lvswxl (long, vector signed short *);
++vector signed short vec_lvswxl (long, signed short *);
++vector unsigned short vec_lvswxl (long, vector unsigned short *);
++vector unsigned short vec_lvswxl (long, unsigned short *);
++vector bool char vec_lvswxl (long, vector bool char *);
++vector signed char vec_lvswxl (long, vector signed char *);
++vector signed char vec_lvswxl (long, signed char *);
++vector unsigned char vec_lvswxl (long, vector unsigned char *);
++vector unsigned char vec_lvswxl (long, unsigned char *);
++
++void vec_stvswx (vector float, long, vector float *);
++void vec_stvswx (vector float, long, float *);
++void vec_stvswx (vector bool int, long, vector bool int *);
++void vec_stvswx (vector signed int, long, vector signed int *);
++void vec_stvswx (vector signed int, long, signed int *);
++void vec_stvswx (vector unsigned int, long, vector unsigned int *);
++void vec_stvswx (vector unsigned int, long, unsigned int *);
++void vec_stvswx (vector bool short, long, vector bool short *);
++void vec_stvswx (vector pixel, long, vector pixel *);
++void vec_stvswx (vector signed short, long, vector signed short *);
++void vec_stvswx (vector signed short, long, signed short *);
++void vec_stvswx (vector unsigned short, long, vector unsigned short *);
++void vec_stvswx (vector unsigned short, long, unsigned short *);
++void vec_stvswx (vector bool char, long, vector bool char *);
++void vec_stvswx (vector signed char, long, vector signed char *);
++void vec_stvswx (vector signed char, long, signed char *);
++void vec_stvswx (vector unsigned char, long, vector unsigned char *);
++void vec_stvswx (vector unsigned char, long, unsigned char *);
++void vec_stvswxl (vector float, long, vector float *);
++void vec_stvswxl (vector float, long, float *);
++void vec_stvswxl (vector bool int, long, vector bool int *);
++void vec_stvswxl (vector signed int, long, vector signed int *);
++void vec_stvswxl (vector signed int, long, signed int *);
++void vec_stvswxl (vector unsigned int, long, vector unsigned int *);
++void vec_stvswxl (vector unsigned int, long, unsigned int *);
++void vec_stvswxl (vector bool short, long, vector bool short *);
++void vec_stvswxl (vector pixel, long, vector pixel *);
++void vec_stvswxl (vector signed short, long, vector signed short *);
++void vec_stvswxl (vector signed short, long, signed short *);
++void vec_stvswxl (vector unsigned short, long, vector unsigned short *);
++void vec_stvswxl (vector unsigned short, long, unsigned short *);
++void vec_stvswxl (vector bool char, long, vector bool char *);
++void vec_stvswxl (vector signed char, long, vector signed char *);
++void vec_stvswxl (vector signed char, long, signed char *);
++void vec_stvswxl (vector unsigned char, long, vector unsigned char *);
++void vec_stvswxl (vector unsigned char, long, unsigned char *);
++
++vector float vec_lvsm (long, vector float *);
++vector float vec_lvsm (long, float *);
++vector bool int vec_lvsm (long, vector bool int *);
++vector signed int vec_lvsm (long, vector signed int *);
++vector signed int vec_lvsm (long, signed int *);
++vector unsigned int vec_lvsm (long, vector unsigned int *);
++vector unsigned int vec_lvsm (long, unsigned int *);
++vector bool short vec_lvsm (long, vector bool short *);
++vector pixel vec_lvsm (long, vector pixel *);
++vector signed short vec_lvsm (long, vector signed short *);
++vector signed short vec_lvsm (long, signed short *);
++vector unsigned short vec_lvsm (long, vector unsigned short *);
++vector unsigned short vec_lvsm (long, unsigned short *);
++vector bool char vec_lvsm (long, vector bool char *);
++vector signed char vec_lvsm (long, vector signed char *);
++vector signed char vec_lvsm (long, signed char *);
++vector unsigned char vec_lvsm (long, vector unsigned char *);
++vector unsigned char vec_lvsm (long, unsigned char *);
++@end smallexample
++
+ GCC provides a few other builtins on Powerpc to access certain instructions:
+ @smallexample
+ float __builtin_recipdivf (float, float);
+diff -ruN gcc-4.6.2-orig/gcc/doc/invoke.texi gcc-4.6.2/gcc/doc/invoke.texi
+--- gcc-4.6.2-orig/gcc/doc/invoke.texi 2011-10-24 07:22:21.000000000 -0500
++++ gcc-4.6.2/gcc/doc/invoke.texi 2012-03-06 12:56:49.402039002 -0600
+@@ -770,7 +770,7 @@
+ -mcmodel=@var{code-model} @gol
+ -mpower -mno-power -mpower2 -mno-power2 @gol
+ -mpowerpc -mpowerpc64 -mno-powerpc @gol
+--maltivec -mno-altivec @gol
++-maltivec -mno-altivec -maltivec2 -mno-altivec2 @gol
+ -mpowerpc-gpopt -mno-powerpc-gpopt @gol
+ -mpowerpc-gfxopt -mno-powerpc-gfxopt @gol
+ -mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb -mpopcntd -mno-popcntd @gol
+@@ -15536,16 +15536,21 @@
+ The @option{-mpopcntb} option allows GCC to generate the popcount and
+ double precision FP reciprocal estimate instruction implemented on the
+ POWER5 processor and other processors that support the PowerPC V2.02
+-architecture.
+-The @option{-mpopcntd} option allows GCC to generate the popcount
+-instruction implemented on the POWER7 processor and other processors
+-that support the PowerPC V2.06 architecture.
++architecture. On the e5500 and e6500 processors, only the popcount
++instruction is generated.
++The @option{-mpopcntd} option allows GCC to generate the popcount and
++double word to FP conversion instructions implemented on the POWER7
++processor and other processors that support the PowerPC V2.06
++architecture. On the e5500 and e6500 processors, only the popcount
++instruction is generated.
+ The @option{-mfprnd} option allows GCC to generate the FP round to
+ integer instructions implemented on the POWER5+ processor and other
+ processors that support the PowerPC V2.03 architecture.
+ The @option{-mcmpb} option allows GCC to generate the compare bytes
+-instruction implemented on the POWER6 processor and other processors
+-that support the PowerPC V2.05 architecture.
++and copy sign instructions implemented on the POWER6 processor and
++other processors that support the PowerPC V2.05 architecture. On the
++e5500 and e6500 processors, only the compare bytes instruction is
++generated.
+ The @option{-mmfpgpr} option allows GCC to generate the FP move to/from
+ general purpose register instructions implemented on the POWER6X
+ processor and other processors that support the extended PowerPC V2.05
+@@ -15592,11 +15597,13 @@
+ @samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{630}, @samp{740},
+ @samp{7400}, @samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
+ @samp{860}, @samp{970}, @samp{8540}, @samp{a2}, @samp{e300c2},
+-@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{ec603e}, @samp{G3},
+-@samp{G4}, @samp{G5}, @samp{titan}, @samp{power}, @samp{power2}, @samp{power3},
+-@samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x},
+-@samp{power7}, @samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
+-@samp{rios1}, @samp{rios2}, @samp{rsc}, and @samp{rs64}.
++@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{e5500},
++@samp{e6500}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
++@samp{titan}, @samp{power}, @samp{power2}, @samp{power3},
++@samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6},
++@samp{power6x}, @samp{power7}, @samp{common}, @samp{powerpc},
++@samp{powerpc64}, @samp{rios}, @samp{rios1}, @samp{rios2}, @samp{rsc},
++and @samp{rs64}.
+
+ @option{-mcpu=common} selects a completely generic processor. Code
+ generated under this option will run on any POWER or PowerPC processor.
+@@ -15617,10 +15624,11 @@
+ The @option{-mcpu} options automatically enable or disable the
+ following options:
+
+-@gccoptlist{-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple @gol
+--mnew-mnemonics -mpopcntb -mpopcntd -mpower -mpower2 -mpowerpc64 @gol
+--mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float -mdouble-float @gol
+--msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx}
++@gccoptlist{-maltivec -maltivec2 -mfprnd -mhard-float -mmfcrf
++-mmultiple @gol -mnew-mnemonics -mpopcntb -mpopcntd -mpower -mpower2
++-mpowerpc64 @gol -mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float
++-mdouble-float @gol -msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr
++-mvsx}
+
+ The particular options set for any particular CPU will vary between
+ compiler versions, depending on what setting seems to produce optimal
+@@ -15671,6 +15679,16 @@
+ @option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
+ enhancements.
+
++@item -maltivec2
++@itemx -mno-altivec2
++@opindex maltivec2
++@opindex mno-altivec2
++Generate code that uses (does not use) AltiVec2 instructions, and also
++enable the use of built-in functions that allow more direct access to
++the AltiVec2 instruction set. You may also need to set
++@option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
++enhancements.
++
+ @item -mvrsave
+ @itemx -mno-vrsave
+ @opindex mvrsave
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-10.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-10.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-10.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-10.c 2012-03-06 12:31:05.152039004 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvtlx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc1(long a, void *p) { return __builtin_altivec_lvtlx (a,p); }
++vsf llx01(long a, vsf *p) { return __builtin_vec_lvtlx (a,p); }
++vsf llx02(long a, sf *p) { return __builtin_vec_lvtlx (a,p); }
++vbi llx03(long a, vbi *p) { return __builtin_vec_lvtlx (a,p); }
++vsi llx04(long a, vsi *p) { return __builtin_vec_lvtlx (a,p); }
++vsi llx05(long a, si *p) { return __builtin_vec_lvtlx (a,p); }
++vui llx06(long a, vui *p) { return __builtin_vec_lvtlx (a,p); }
++vui llx07(long a, ui *p) { return __builtin_vec_lvtlx (a,p); }
++vbs llx08(long a, vbs *p) { return __builtin_vec_lvtlx (a,p); }
++vp llx09(long a, vp *p) { return __builtin_vec_lvtlx (a,p); }
++vss llx10(long a, vss *p) { return __builtin_vec_lvtlx (a,p); }
++vss llx11(long a, ss *p) { return __builtin_vec_lvtlx (a,p); }
++vus llx12(long a, vus *p) { return __builtin_vec_lvtlx (a,p); }
++vus llx13(long a, us *p) { return __builtin_vec_lvtlx (a,p); }
++vbc llx14(long a, vbc *p) { return __builtin_vec_lvtlx (a,p); }
++vsc llx15(long a, vsc *p) { return __builtin_vec_lvtlx (a,p); }
++vsc llx16(long a, sc *p) { return __builtin_vec_lvtlx (a,p); }
++vuc llx17(long a, vuc *p) { return __builtin_vec_lvtlx (a,p); }
++vuc llx18(long a, uc *p) { return __builtin_vec_lvtlx (a,p); }
++vsf Dllx01(long a, vsf *p) { return vec_lvtlx (a,p); }
++vsf Dllx02(long a, sf *p) { return vec_lvtlx (a,p); }
++vbi Dllx03(long a, vbi *p) { return vec_lvtlx (a,p); }
++vsi Dllx04(long a, vsi *p) { return vec_lvtlx (a,p); }
++vsi Dllx05(long a, si *p) { return vec_lvtlx (a,p); }
++vui Dllx06(long a, vui *p) { return vec_lvtlx (a,p); }
++vui Dllx07(long a, ui *p) { return vec_lvtlx (a,p); }
++vbs Dllx08(long a, vbs *p) { return vec_lvtlx (a,p); }
++vp Dllx09(long a, vp *p) { return vec_lvtlx (a,p); }
++vss Dllx10(long a, vss *p) { return vec_lvtlx (a,p); }
++vss Dllx11(long a, ss *p) { return vec_lvtlx (a,p); }
++vus Dllx12(long a, vus *p) { return vec_lvtlx (a,p); }
++vus Dllx13(long a, us *p) { return vec_lvtlx (a,p); }
++vbc Dllx14(long a, vbc *p) { return vec_lvtlx (a,p); }
++vsc Dllx15(long a, vsc *p) { return vec_lvtlx (a,p); }
++vsc Dllx16(long a, sc *p) { return vec_lvtlx (a,p); }
++vuc Dllx17(long a, vuc *p) { return vec_lvtlx (a,p); }
++vuc Dllx18(long a, uc *p) { return vec_lvtlx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-11.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-11.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-11.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-11.c 2012-03-06 12:31:05.153039004 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvtlxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc2(long a, void *p) { return __builtin_altivec_lvtlxl (a,p); }
++vsf llxl01(long a, vsf *p) { return __builtin_vec_lvtlxl (a,p); }
++vsf llxl02(long a, sf *p) { return __builtin_vec_lvtlxl (a,p); }
++vbi llxl03(long a, vbi *p) { return __builtin_vec_lvtlxl (a,p); }
++vsi llxl04(long a, vsi *p) { return __builtin_vec_lvtlxl (a,p); }
++vsi llxl05(long a, si *p) { return __builtin_vec_lvtlxl (a,p); }
++vui llxl06(long a, vui *p) { return __builtin_vec_lvtlxl (a,p); }
++vui llxl07(long a, ui *p) { return __builtin_vec_lvtlxl (a,p); }
++vbs llxl08(long a, vbs *p) { return __builtin_vec_lvtlxl (a,p); }
++vp llxl09(long a, vp *p) { return __builtin_vec_lvtlxl (a,p); }
++vss llxl10(long a, vss *p) { return __builtin_vec_lvtlxl (a,p); }
++vss llxl11(long a, ss *p) { return __builtin_vec_lvtlxl (a,p); }
++vus llxl12(long a, vus *p) { return __builtin_vec_lvtlxl (a,p); }
++vus llxl13(long a, us *p) { return __builtin_vec_lvtlxl (a,p); }
++vbc llxl14(long a, vbc *p) { return __builtin_vec_lvtlxl (a,p); }
++vsc llxl15(long a, vsc *p) { return __builtin_vec_lvtlxl (a,p); }
++vsc llxl16(long a, sc *p) { return __builtin_vec_lvtlxl (a,p); }
++vuc llxl17(long a, vuc *p) { return __builtin_vec_lvtlxl (a,p); }
++vuc llxl18(long a, uc *p) { return __builtin_vec_lvtlxl (a,p); }
++vsf Dllxl01(long a, vsf *p) { return vec_lvtlxl (a,p); }
++vsf Dllxl02(long a, sf *p) { return vec_lvtlxl (a,p); }
++vbi Dllxl03(long a, vbi *p) { return vec_lvtlxl (a,p); }
++vsi Dllxl04(long a, vsi *p) { return vec_lvtlxl (a,p); }
++vsi Dllxl05(long a, si *p) { return vec_lvtlxl (a,p); }
++vui Dllxl06(long a, vui *p) { return vec_lvtlxl (a,p); }
++vui Dllxl07(long a, ui *p) { return vec_lvtlxl (a,p); }
++vbs Dllxl08(long a, vbs *p) { return vec_lvtlxl (a,p); }
++vp Dllxl09(long a, vp *p) { return vec_lvtlxl (a,p); }
++vss Dllxl10(long a, vss *p) { return vec_lvtlxl (a,p); }
++vss Dllxl11(long a, ss *p) { return vec_lvtlxl (a,p); }
++vus Dllxl12(long a, vus *p) { return vec_lvtlxl (a,p); }
++vus Dllxl13(long a, us *p) { return vec_lvtlxl (a,p); }
++vbc Dllxl14(long a, vbc *p) { return vec_lvtlxl (a,p); }
++vsc Dllxl15(long a, vsc *p) { return vec_lvtlxl (a,p); }
++vsc Dllxl16(long a, sc *p) { return vec_lvtlxl (a,p); }
++vuc Dllxl17(long a, vuc *p) { return vec_lvtlxl (a,p); }
++vuc Dllxl18(long a, uc *p) { return vec_lvtlxl (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-12.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-12.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-12.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-12.c 2012-03-06 12:31:05.153039004 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvtrx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc3(long a, void *p) { return __builtin_altivec_lvtrx (a,p); }
++vsf lrx01(long a, vsf *p) { return __builtin_vec_lvtrx (a,p); }
++vsf lrx02(long a, sf *p) { return __builtin_vec_lvtrx (a,p); }
++vbi lrx03(long a, vbi *p) { return __builtin_vec_lvtrx (a,p); }
++vsi lrx04(long a, vsi *p) { return __builtin_vec_lvtrx (a,p); }
++vsi lrx05(long a, si *p) { return __builtin_vec_lvtrx (a,p); }
++vui lrx06(long a, vui *p) { return __builtin_vec_lvtrx (a,p); }
++vui lrx07(long a, ui *p) { return __builtin_vec_lvtrx (a,p); }
++vbs lrx08(long a, vbs *p) { return __builtin_vec_lvtrx (a,p); }
++vp lrx09(long a, vp *p) { return __builtin_vec_lvtrx (a,p); }
++vss lrx10(long a, vss *p) { return __builtin_vec_lvtrx (a,p); }
++vss lrx11(long a, ss *p) { return __builtin_vec_lvtrx (a,p); }
++vus lrx12(long a, vus *p) { return __builtin_vec_lvtrx (a,p); }
++vus lrx13(long a, us *p) { return __builtin_vec_lvtrx (a,p); }
++vbc lrx14(long a, vbc *p) { return __builtin_vec_lvtrx (a,p); }
++vsc lrx15(long a, vsc *p) { return __builtin_vec_lvtrx (a,p); }
++vsc lrx16(long a, sc *p) { return __builtin_vec_lvtrx (a,p); }
++vuc lrx17(long a, vuc *p) { return __builtin_vec_lvtrx (a,p); }
++vuc lrx18(long a, uc *p) { return __builtin_vec_lvtrx (a,p); }
++vsf Dlrx01(long a, vsf *p) { return vec_lvtrx (a,p); }
++vsf Dlrx02(long a, sf *p) { return vec_lvtrx (a,p); }
++vbi Dlrx03(long a, vbi *p) { return vec_lvtrx (a,p); }
++vsi Dlrx04(long a, vsi *p) { return vec_lvtrx (a,p); }
++vsi Dlrx05(long a, si *p) { return vec_lvtrx (a,p); }
++vui Dlrx06(long a, vui *p) { return vec_lvtrx (a,p); }
++vui Dlrx07(long a, ui *p) { return vec_lvtrx (a,p); }
++vbs Dlrx08(long a, vbs *p) { return vec_lvtrx (a,p); }
++vp Dlrx09(long a, vp *p) { return vec_lvtrx (a,p); }
++vss Dlrx10(long a, vss *p) { return vec_lvtrx (a,p); }
++vss Dlrx11(long a, ss *p) { return vec_lvtrx (a,p); }
++vus Dlrx12(long a, vus *p) { return vec_lvtrx (a,p); }
++vus Dlrx13(long a, us *p) { return vec_lvtrx (a,p); }
++vbc Dlrx14(long a, vbc *p) { return vec_lvtrx (a,p); }
++vsc Dlrx15(long a, vsc *p) { return vec_lvtrx (a,p); }
++vsc Dlrx16(long a, sc *p) { return vec_lvtrx (a,p); }
++vuc Dlrx17(long a, vuc *p) { return vec_lvtrx (a,p); }
++vuc Dlrx18(long a, uc *p) { return vec_lvtrx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-13.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-13.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-13.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-13.c 2012-03-06 12:31:05.153039004 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvtrxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc4(long a, void *p) { return __builtin_altivec_lvtrxl (a,p); }
++vsf lrxl01(long a, vsf *p) { return __builtin_vec_lvtrxl (a,p); }
++vsf lrxl02(long a, sf *p) { return __builtin_vec_lvtrxl (a,p); }
++vbi lrxl03(long a, vbi *p) { return __builtin_vec_lvtrxl (a,p); }
++vsi lrxl04(long a, vsi *p) { return __builtin_vec_lvtrxl (a,p); }
++vsi lrxl05(long a, si *p) { return __builtin_vec_lvtrxl (a,p); }
++vui lrxl06(long a, vui *p) { return __builtin_vec_lvtrxl (a,p); }
++vui lrxl07(long a, ui *p) { return __builtin_vec_lvtrxl (a,p); }
++vbs lrxl08(long a, vbs *p) { return __builtin_vec_lvtrxl (a,p); }
++vp lrxl09(long a, vp *p) { return __builtin_vec_lvtrxl (a,p); }
++vss lrxl10(long a, vss *p) { return __builtin_vec_lvtrxl (a,p); }
++vss lrxl11(long a, ss *p) { return __builtin_vec_lvtrxl (a,p); }
++vus lrxl12(long a, vus *p) { return __builtin_vec_lvtrxl (a,p); }
++vus lrxl13(long a, us *p) { return __builtin_vec_lvtrxl (a,p); }
++vbc lrxl14(long a, vbc *p) { return __builtin_vec_lvtrxl (a,p); }
++vsc lrxl15(long a, vsc *p) { return __builtin_vec_lvtrxl (a,p); }
++vsc lrxl16(long a, sc *p) { return __builtin_vec_lvtrxl (a,p); }
++vuc lrxl17(long a, vuc *p) { return __builtin_vec_lvtrxl (a,p); }
++vuc lrxl18(long a, uc *p) { return __builtin_vec_lvtrxl (a,p); }
++vsf Dlrxl01(long a, vsf *p) { return vec_lvtrxl (a,p); }
++vsf Dlrxl02(long a, sf *p) { return vec_lvtrxl (a,p); }
++vbi Dlrxl03(long a, vbi *p) { return vec_lvtrxl (a,p); }
++vsi Dlrxl04(long a, vsi *p) { return vec_lvtrxl (a,p); }
++vsi Dlrxl05(long a, si *p) { return vec_lvtrxl (a,p); }
++vui Dlrxl06(long a, vui *p) { return vec_lvtrxl (a,p); }
++vui Dlrxl07(long a, ui *p) { return vec_lvtrxl (a,p); }
++vbs Dlrxl08(long a, vbs *p) { return vec_lvtrxl (a,p); }
++vp Dlrxl09(long a, vp *p) { return vec_lvtrxl (a,p); }
++vss Dlrxl10(long a, vss *p) { return vec_lvtrxl (a,p); }
++vss Dlrxl11(long a, ss *p) { return vec_lvtrxl (a,p); }
++vus Dlrxl12(long a, vus *p) { return vec_lvtrxl (a,p); }
++vus Dlrxl13(long a, us *p) { return vec_lvtrxl (a,p); }
++vbc Dlrxl14(long a, vbc *p) { return vec_lvtrxl (a,p); }
++vsc Dlrxl15(long a, vsc *p) { return vec_lvtrxl (a,p); }
++vsc Dlrxl16(long a, sc *p) { return vec_lvtrxl (a,p); }
++vuc Dlrxl17(long a, vuc *p) { return vec_lvtrxl (a,p); }
++vuc Dlrxl18(long a, uc *p) { return vec_lvtrxl (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-14.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-14.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-14.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-14.c 2012-03-06 12:31:05.154039003 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvflx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc1(vsc v, long a, void *p) { __builtin_altivec_stvflx (v,a,p); }
++void slx01(vsf v, long a, vsf *p) { __builtin_vec_stvflx (v,a,p); }
++void slx02(vsf v, long a, sf *p) { __builtin_vec_stvflx (v,a,p); }
++void slx03(vbi v, long a, vbi *p) { __builtin_vec_stvflx (v,a,p); }
++void slx04(vsi v, long a, vsi *p) { __builtin_vec_stvflx (v,a,p); }
++void slx05(vsi v, long a, si *p) { __builtin_vec_stvflx (v,a,p); }
++void slx06(vui v, long a, vui *p) { __builtin_vec_stvflx (v,a,p); }
++void slx07(vui v, long a, ui *p) { __builtin_vec_stvflx (v,a,p); }
++void slx08(vbs v, long a, vbs *p) { __builtin_vec_stvflx (v,a,p); }
++void slx09(vp v, long a, vp *p) { __builtin_vec_stvflx (v,a,p); }
++void slx10(vss v, long a, vss *p) { __builtin_vec_stvflx (v,a,p); }
++void slx11(vss v, long a, ss *p) { __builtin_vec_stvflx (v,a,p); }
++void slx12(vus v, long a, vus *p) { __builtin_vec_stvflx (v,a,p); }
++void slx13(vus v, long a, us *p) { __builtin_vec_stvflx (v,a,p); }
++void slx14(vbc v, long a, vbc *p) { __builtin_vec_stvflx (v,a,p); }
++void slx15(vsc v, long a, vsc *p) { __builtin_vec_stvflx (v,a,p); }
++void slx16(vsc v, long a, sc *p) { __builtin_vec_stvflx (v,a,p); }
++void slx17(vuc v, long a, vuc *p) { __builtin_vec_stvflx (v,a,p); }
++void slx18(vuc v, long a, uc *p) { __builtin_vec_stvflx (v,a,p); }
++void Dslx01(vsf v, long a, vsf *p) { vec_stvflx (v,a,p); }
++void Dslx02(vsf v, long a, sf *p) { vec_stvflx (v,a,p); }
++void Dslx03(vbi v, long a, vbi *p) { vec_stvflx (v,a,p); }
++void Dslx04(vsi v, long a, vsi *p) { vec_stvflx (v,a,p); }
++void Dslx05(vsi v, long a, si *p) { vec_stvflx (v,a,p); }
++void Dslx06(vui v, long a, vui *p) { vec_stvflx (v,a,p); }
++void Dslx07(vui v, long a, ui *p) { vec_stvflx (v,a,p); }
++void Dslx08(vbs v, long a, vbs *p) { vec_stvflx (v,a,p); }
++void Dslx09(vp v, long a, vp *p) { vec_stvflx (v,a,p); }
++void Dslx10(vss v, long a, vss *p) { vec_stvflx (v,a,p); }
++void Dslx11(vss v, long a, ss *p) { vec_stvflx (v,a,p); }
++void Dslx12(vus v, long a, vus *p) { vec_stvflx (v,a,p); }
++void Dslx13(vus v, long a, us *p) { vec_stvflx (v,a,p); }
++void Dslx14(vbc v, long a, vbc *p) { vec_stvflx (v,a,p); }
++void Dslx15(vsc v, long a, vsc *p) { vec_stvflx (v,a,p); }
++void Dslx16(vsc v, long a, sc *p) { vec_stvflx (v,a,p); }
++void Dslx17(vuc v, long a, vuc *p) { vec_stvflx (v,a,p); }
++void Dslx18(vuc v, long a, uc *p) { vec_stvflx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-15.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-15.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-15.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-15.c 2012-03-06 12:31:05.154039003 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvflxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc2(vsc v, long a, void *p) { __builtin_altivec_stvflxl (v,a,p); }
++void slxl01(vsf v, long a, vsf *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl02(vsf v, long a, sf *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl03(vbi v, long a, vbi *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl04(vsi v, long a, vsi *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl05(vsi v, long a, si *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl06(vui v, long a, vui *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl07(vui v, long a, ui *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl08(vbs v, long a, vbs *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl09(vp v, long a, vp *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl10(vss v, long a, vss *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl11(vss v, long a, ss *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl12(vus v, long a, vus *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl13(vus v, long a, us *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl14(vbc v, long a, vbc *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl15(vsc v, long a, vsc *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl16(vsc v, long a, sc *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl17(vuc v, long a, vuc *p) { __builtin_vec_stvflxl (v,a,p); }
++void slxl18(vuc v, long a, uc *p) { __builtin_vec_stvflxl (v,a,p); }
++void Dslxl01(vsf v, long a, vsf *p) { vec_stvflxl (v,a,p); }
++void Dslxl02(vsf v, long a, sf *p) { vec_stvflxl (v,a,p); }
++void Dslxl03(vbi v, long a, vbi *p) { vec_stvflxl (v,a,p); }
++void Dslxl04(vsi v, long a, vsi *p) { vec_stvflxl (v,a,p); }
++void Dslxl05(vsi v, long a, si *p) { vec_stvflxl (v,a,p); }
++void Dslxl06(vui v, long a, vui *p) { vec_stvflxl (v,a,p); }
++void Dslxl07(vui v, long a, ui *p) { vec_stvflxl (v,a,p); }
++void Dslxl08(vbs v, long a, vbs *p) { vec_stvflxl (v,a,p); }
++void Dslxl09(vp v, long a, vp *p) { vec_stvflxl (v,a,p); }
++void Dslxl10(vss v, long a, vss *p) { vec_stvflxl (v,a,p); }
++void Dslxl11(vss v, long a, ss *p) { vec_stvflxl (v,a,p); }
++void Dslxl12(vus v, long a, vus *p) { vec_stvflxl (v,a,p); }
++void Dslxl13(vus v, long a, us *p) { vec_stvflxl (v,a,p); }
++void Dslxl14(vbc v, long a, vbc *p) { vec_stvflxl (v,a,p); }
++void Dslxl15(vsc v, long a, vsc *p) { vec_stvflxl (v,a,p); }
++void Dslxl16(vsc v, long a, sc *p) { vec_stvflxl (v,a,p); }
++void Dslxl17(vuc v, long a, vuc *p) { vec_stvflxl (v,a,p); }
++void Dslxl18(vuc v, long a, uc *p) { vec_stvflxl (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-16.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-16.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-16.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-16.c 2012-03-06 12:31:05.154039003 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvfrx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc3(vsc v, long a, void *p) { __builtin_altivec_stvfrx (v,a,p); }
++void srx01(vsf v, long a, vsf *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx02(vsf v, long a, sf *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx03(vbi v, long a, vbi *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx04(vsi v, long a, vsi *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx05(vsi v, long a, si *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx06(vui v, long a, vui *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx07(vui v, long a, ui *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx08(vbs v, long a, vbs *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx09(vp v, long a, vp *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx10(vss v, long a, vss *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx11(vss v, long a, ss *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx12(vus v, long a, vus *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx13(vus v, long a, us *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx14(vbc v, long a, vbc *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx15(vsc v, long a, vsc *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx16(vsc v, long a, sc *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx17(vuc v, long a, vuc *p) { __builtin_vec_stvfrx (v,a,p); }
++void srx18(vuc v, long a, uc *p) { __builtin_vec_stvfrx (v,a,p); }
++void Dsrx01(vsf v, long a, vsf *p) { vec_stvfrx (v,a,p); }
++void Dsrx02(vsf v, long a, sf *p) { vec_stvfrx (v,a,p); }
++void Dsrx03(vbi v, long a, vbi *p) { vec_stvfrx (v,a,p); }
++void Dsrx04(vsi v, long a, vsi *p) { vec_stvfrx (v,a,p); }
++void Dsrx05(vsi v, long a, si *p) { vec_stvfrx (v,a,p); }
++void Dsrx06(vui v, long a, vui *p) { vec_stvfrx (v,a,p); }
++void Dsrx07(vui v, long a, ui *p) { vec_stvfrx (v,a,p); }
++void Dsrx08(vbs v, long a, vbs *p) { vec_stvfrx (v,a,p); }
++void Dsrx09(vp v, long a, vp *p) { vec_stvfrx (v,a,p); }
++void Dsrx10(vss v, long a, vss *p) { vec_stvfrx (v,a,p); }
++void Dsrx11(vss v, long a, ss *p) { vec_stvfrx (v,a,p); }
++void Dsrx12(vus v, long a, vus *p) { vec_stvfrx (v,a,p); }
++void Dsrx13(vus v, long a, us *p) { vec_stvfrx (v,a,p); }
++void Dsrx14(vbc v, long a, vbc *p) { vec_stvfrx (v,a,p); }
++void Dsrx15(vsc v, long a, vsc *p) { vec_stvfrx (v,a,p); }
++void Dsrx16(vsc v, long a, sc *p) { vec_stvfrx (v,a,p); }
++void Dsrx17(vuc v, long a, vuc *p) { vec_stvfrx (v,a,p); }
++void Dsrx18(vuc v, long a, uc *p) { vec_stvfrx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-17.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-17.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-17.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-17.c 2012-03-06 12:31:05.155039001 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvfrxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc4(vsc v, long a, void *p) { __builtin_altivec_stvfrxl (v,a,p); }
++void srxl01(vsf v, long a, vsf *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl02(vsf v, long a, sf *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl03(vbi v, long a, vbi *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl04(vsi v, long a, vsi *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl05(vsi v, long a, si *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl06(vui v, long a, vui *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl07(vui v, long a, ui *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl08(vbs v, long a, vbs *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl09(vp v, long a, vp *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl10(vss v, long a, vss *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl11(vss v, long a, ss *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl12(vus v, long a, vus *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl13(vus v, long a, us *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl14(vbc v, long a, vbc *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl15(vsc v, long a, vsc *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl16(vsc v, long a, sc *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl17(vuc v, long a, vuc *p) { __builtin_vec_stvfrxl (v,a,p); }
++void srxl18(vuc v, long a, uc *p) { __builtin_vec_stvfrxl (v,a,p); }
++void Dsrxl01(vsf v, long a, vsf *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl02(vsf v, long a, sf *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl03(vbi v, long a, vbi *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl04(vsi v, long a, vsi *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl05(vsi v, long a, si *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl06(vui v, long a, vui *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl07(vui v, long a, ui *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl08(vbs v, long a, vbs *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl09(vp v, long a, vp *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl10(vss v, long a, vss *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl11(vss v, long a, ss *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl12(vus v, long a, vus *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl13(vus v, long a, us *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl14(vbc v, long a, vbc *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl15(vsc v, long a, vsc *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl16(vsc v, long a, sc *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl17(vuc v, long a, vuc *p) { vec_stvfrxl (v,a,p); }
++void Dsrxl18(vuc v, long a, uc *p) { vec_stvfrxl (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-18.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-18.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-18.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-18.c 2012-03-06 12:31:05.155039001 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvswx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc ls1(long a, void *p) { return __builtin_altivec_lvswx (a,p); }
++vsf ls01(long a, vsf *p) { return __builtin_vec_lvswx (a,p); }
++vsf ls02(long a, sf *p) { return __builtin_vec_lvswx (a,p); }
++vbi ls03(long a, vbi *p) { return __builtin_vec_lvswx (a,p); }
++vsi ls04(long a, vsi *p) { return __builtin_vec_lvswx (a,p); }
++vsi ls05(long a, si *p) { return __builtin_vec_lvswx (a,p); }
++vui ls06(long a, vui *p) { return __builtin_vec_lvswx (a,p); }
++vui ls07(long a, ui *p) { return __builtin_vec_lvswx (a,p); }
++vbs ls08(long a, vbs *p) { return __builtin_vec_lvswx (a,p); }
++vp ls09(long a, vp *p) { return __builtin_vec_lvswx (a,p); }
++vss ls10(long a, vss *p) { return __builtin_vec_lvswx (a,p); }
++vss ls11(long a, ss *p) { return __builtin_vec_lvswx (a,p); }
++vus ls12(long a, vus *p) { return __builtin_vec_lvswx (a,p); }
++vus ls13(long a, us *p) { return __builtin_vec_lvswx (a,p); }
++vbc ls14(long a, vbc *p) { return __builtin_vec_lvswx (a,p); }
++vsc ls15(long a, vsc *p) { return __builtin_vec_lvswx (a,p); }
++vsc ls16(long a, sc *p) { return __builtin_vec_lvswx (a,p); }
++vuc ls17(long a, vuc *p) { return __builtin_vec_lvswx (a,p); }
++vuc ls18(long a, uc *p) { return __builtin_vec_lvswx (a,p); }
++vsf Dls01(long a, vsf *p) { return vec_lvswx (a,p); }
++vsf Dls02(long a, sf *p) { return vec_lvswx (a,p); }
++vbi Dls03(long a, vbi *p) { return vec_lvswx (a,p); }
++vsi Dls04(long a, vsi *p) { return vec_lvswx (a,p); }
++vsi Dls05(long a, si *p) { return vec_lvswx (a,p); }
++vui Dls06(long a, vui *p) { return vec_lvswx (a,p); }
++vui Dls07(long a, ui *p) { return vec_lvswx (a,p); }
++vbs Dls08(long a, vbs *p) { return vec_lvswx (a,p); }
++vp Dls09(long a, vp *p) { return vec_lvswx (a,p); }
++vss Dls10(long a, vss *p) { return vec_lvswx (a,p); }
++vss Dls11(long a, ss *p) { return vec_lvswx (a,p); }
++vus Dls12(long a, vus *p) { return vec_lvswx (a,p); }
++vus Dls13(long a, us *p) { return vec_lvswx (a,p); }
++vbc Dls14(long a, vbc *p) { return vec_lvswx (a,p); }
++vsc Dls15(long a, vsc *p) { return vec_lvswx (a,p); }
++vsc Dls16(long a, sc *p) { return vec_lvswx (a,p); }
++vuc Dls17(long a, vuc *p) { return vec_lvswx (a,p); }
++vuc Dls18(long a, uc *p) { return vec_lvswx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-19.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-19.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-19.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-19.c 2012-03-06 12:31:05.155039001 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvswxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc ls2l(long a, void *p) { return __builtin_altivec_lvswxl (a,p); }
++vsf lsl01(long a, vsf *p) { return __builtin_vec_lvswxl (a,p); }
++vsf lsl02(long a, sf *p) { return __builtin_vec_lvswxl (a,p); }
++vbi lsl03(long a, vbi *p) { return __builtin_vec_lvswxl (a,p); }
++vsi lsl04(long a, vsi *p) { return __builtin_vec_lvswxl (a,p); }
++vsi lsl05(long a, si *p) { return __builtin_vec_lvswxl (a,p); }
++vui lsl06(long a, vui *p) { return __builtin_vec_lvswxl (a,p); }
++vui lsl07(long a, ui *p) { return __builtin_vec_lvswxl (a,p); }
++vbs lsl08(long a, vbs *p) { return __builtin_vec_lvswxl (a,p); }
++vp lsl09(long a, vp *p) { return __builtin_vec_lvswxl (a,p); }
++vss lsl10(long a, vss *p) { return __builtin_vec_lvswxl (a,p); }
++vss lsl11(long a, ss *p) { return __builtin_vec_lvswxl (a,p); }
++vus lsl12(long a, vus *p) { return __builtin_vec_lvswxl (a,p); }
++vus lsl13(long a, us *p) { return __builtin_vec_lvswxl (a,p); }
++vbc lsl14(long a, vbc *p) { return __builtin_vec_lvswxl (a,p); }
++vsc lsl15(long a, vsc *p) { return __builtin_vec_lvswxl (a,p); }
++vsc lsl16(long a, sc *p) { return __builtin_vec_lvswxl (a,p); }
++vuc lsl17(long a, vuc *p) { return __builtin_vec_lvswxl (a,p); }
++vuc lsl18(long a, uc *p) { return __builtin_vec_lvswxl (a,p); }
++vsf Dlsl01(long a, vsf *p) { return vec_lvswxl (a,p); }
++vsf Dlsl02(long a, sf *p) { return vec_lvswxl (a,p); }
++vbi Dlsl03(long a, vbi *p) { return vec_lvswxl (a,p); }
++vsi Dlsl04(long a, vsi *p) { return vec_lvswxl (a,p); }
++vsi Dlsl05(long a, si *p) { return vec_lvswxl (a,p); }
++vui Dlsl06(long a, vui *p) { return vec_lvswxl (a,p); }
++vui Dlsl07(long a, ui *p) { return vec_lvswxl (a,p); }
++vbs Dlsl08(long a, vbs *p) { return vec_lvswxl (a,p); }
++vp Dlsl09(long a, vp *p) { return vec_lvswxl (a,p); }
++vss Dlsl10(long a, vss *p) { return vec_lvswxl (a,p); }
++vss Dlsl11(long a, ss *p) { return vec_lvswxl (a,p); }
++vus Dlsl12(long a, vus *p) { return vec_lvswxl (a,p); }
++vus Dlsl13(long a, us *p) { return vec_lvswxl (a,p); }
++vbc Dlsl14(long a, vbc *p) { return vec_lvswxl (a,p); }
++vsc Dlsl15(long a, vsc *p) { return vec_lvswxl (a,p); }
++vsc Dlsl16(long a, sc *p) { return vec_lvswxl (a,p); }
++vuc Dlsl17(long a, vuc *p) { return vec_lvswxl (a,p); }
++vuc Dlsl18(long a, uc *p) { return vec_lvswxl (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-1.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-1.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-1.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-1.c 2012-03-06 12:31:05.156039000 -0600
+@@ -0,0 +1,36 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "vabsdub" 7 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vuc fa1b(vuc a, vuc b) { return __builtin_altivec_vabsdub (a,b); }
++vuc ad1(vuc a, vuc b) { return __builtin_vec_absd (a,b); }
++vuc ad2(vbc a, vuc b) { return __builtin_vec_absd (a,b); }
++vuc ad3(vuc a, vbc b) { return __builtin_vec_absd (a,b); }
++vuc Dad1(vuc a, vuc b) { return vec_absd (a,b); }
++vuc Dad2(vbc a, vuc b) { return vec_absd (a,b); }
++vuc Dad3(vuc a, vbc b) { return vec_absd (a,b); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-20.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-20.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-20.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-20.c 2012-03-06 12:31:05.156039000 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvswx" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void ss1(vsc v, long a, vsc *p) { __builtin_altivec_stvswx (v,a,p); }
++void ssx01(vsf v, long a, vsf *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx02(vsf v, long a, sf *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx03(vbi v, long a, vbi *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx04(vsi v, long a, vsi *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx05(vsi v, long a, si *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx06(vui v, long a, vui *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx07(vui v, long a, ui *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx08(vbs v, long a, vbs *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx09(vp v, long a, vp *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx10(vss v, long a, vss *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx11(vss v, long a, ss *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx12(vus v, long a, vus *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx13(vus v, long a, us *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx14(vbc v, long a, vbc *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx15(vsc v, long a, vsc *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx16(vsc v, long a, sc *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx17(vuc v, long a, vuc *p) { __builtin_vec_stvswx (v,a,p); }
++void ssx18(vuc v, long a, uc *p) { __builtin_vec_stvswx (v,a,p); }
++void Dssx01(vsf v, long a, vsf *p) { vec_stvswx (v,a,p); }
++void Dssx02(vsf v, long a, sf *p) { vec_stvswx (v,a,p); }
++void Dssx03(vbi v, long a, vbi *p) { vec_stvswx (v,a,p); }
++void Dssx04(vsi v, long a, vsi *p) { vec_stvswx (v,a,p); }
++void Dssx05(vsi v, long a, si *p) { vec_stvswx (v,a,p); }
++void Dssx06(vui v, long a, vui *p) { vec_stvswx (v,a,p); }
++void Dssx07(vui v, long a, ui *p) { vec_stvswx (v,a,p); }
++void Dssx08(vbs v, long a, vbs *p) { vec_stvswx (v,a,p); }
++void Dssx09(vp v, long a, vp *p) { vec_stvswx (v,a,p); }
++void Dssx10(vss v, long a, vss *p) { vec_stvswx (v,a,p); }
++void Dssx11(vss v, long a, ss *p) { vec_stvswx (v,a,p); }
++void Dssx12(vus v, long a, vus *p) { vec_stvswx (v,a,p); }
++void Dssx13(vus v, long a, us *p) { vec_stvswx (v,a,p); }
++void Dssx14(vbc v, long a, vbc *p) { vec_stvswx (v,a,p); }
++void Dssx15(vsc v, long a, vsc *p) { vec_stvswx (v,a,p); }
++void Dssx16(vsc v, long a, sc *p) { vec_stvswx (v,a,p); }
++void Dssx17(vuc v, long a, vuc *p) { vec_stvswx (v,a,p); }
++void Dssx18(vuc v, long a, uc *p) { vec_stvswx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-21.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-21.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-21.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-21.c 2012-03-06 12:31:05.156039000 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvswxl" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void ss2l(vsc v, long a, vsc *p) { __builtin_altivec_stvswxl (v,a,p); }
++void ssxl01(vsf v, long a, vsf *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl02(vsf v, long a, sf *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl03(vbi v, long a, vbi *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl04(vsi v, long a, vsi *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl05(vsi v, long a, si *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl06(vui v, long a, vui *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl07(vui v, long a, ui *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl08(vbs v, long a, vbs *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl09(vp v, long a, vp *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl10(vss v, long a, vss *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl11(vss v, long a, ss *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl12(vus v, long a, vus *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl13(vus v, long a, us *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl14(vbc v, long a, vbc *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl15(vsc v, long a, vsc *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl16(vsc v, long a, sc *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl17(vuc v, long a, vuc *p) { __builtin_vec_stvswxl (v,a,p); }
++void ssxl18(vuc v, long a, uc *p) { __builtin_vec_stvswxl (v,a,p); }
++void Dssxl01(vsf v, long a, vsf *p) { vec_stvswxl (v,a,p); }
++void Dssxl02(vsf v, long a, sf *p) { vec_stvswxl (v,a,p); }
++void Dssxl03(vbi v, long a, vbi *p) { vec_stvswxl (v,a,p); }
++void Dssxl04(vsi v, long a, vsi *p) { vec_stvswxl (v,a,p); }
++void Dssxl05(vsi v, long a, si *p) { vec_stvswxl (v,a,p); }
++void Dssxl06(vui v, long a, vui *p) { vec_stvswxl (v,a,p); }
++void Dssxl07(vui v, long a, ui *p) { vec_stvswxl (v,a,p); }
++void Dssxl08(vbs v, long a, vbs *p) { vec_stvswxl (v,a,p); }
++void Dssxl09(vp v, long a, vp *p) { vec_stvswxl (v,a,p); }
++void Dssxl10(vss v, long a, vss *p) { vec_stvswxl (v,a,p); }
++void Dssxl11(vss v, long a, ss *p) { vec_stvswxl (v,a,p); }
++void Dssxl12(vus v, long a, vus *p) { vec_stvswxl (v,a,p); }
++void Dssxl13(vus v, long a, us *p) { vec_stvswxl (v,a,p); }
++void Dssxl14(vbc v, long a, vbc *p) { vec_stvswxl (v,a,p); }
++void Dssxl15(vsc v, long a, vsc *p) { vec_stvswxl (v,a,p); }
++void Dssxl16(vsc v, long a, sc *p) { vec_stvswxl (v,a,p); }
++void Dssxl17(vuc v, long a, vuc *p) { vec_stvswxl (v,a,p); }
++void Dssxl18(vuc v, long a, uc *p) { vec_stvswxl (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-22.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-22.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-22.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-22.c 2012-03-06 12:31:05.157039001 -0600
+@@ -0,0 +1,66 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvsm" 37 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lsm(long a, void *p) { return __builtin_altivec_lvsm (a,p); }
++vsf lm01(long a, vsf *p) { return __builtin_vec_lvsm (a,p); }
++vsf lm02(long a, sf *p) { return __builtin_vec_lvsm (a,p); }
++vbi lm03(long a, vbi *p) { return __builtin_vec_lvsm (a,p); }
++vsi lm04(long a, vsi *p) { return __builtin_vec_lvsm (a,p); }
++vsi lm05(long a, si *p) { return __builtin_vec_lvsm (a,p); }
++vui lm06(long a, vui *p) { return __builtin_vec_lvsm (a,p); }
++vui lm07(long a, ui *p) { return __builtin_vec_lvsm (a,p); }
++vbs lm08(long a, vbs *p) { return __builtin_vec_lvsm (a,p); }
++vp lm09(long a, vp *p) { return __builtin_vec_lvsm (a,p); }
++vss lm10(long a, vss *p) { return __builtin_vec_lvsm (a,p); }
++vss lm11(long a, ss *p) { return __builtin_vec_lvsm (a,p); }
++vus lm12(long a, vus *p) { return __builtin_vec_lvsm (a,p); }
++vus lm13(long a, us *p) { return __builtin_vec_lvsm (a,p); }
++vbc lm14(long a, vbc *p) { return __builtin_vec_lvsm (a,p); }
++vsc lm15(long a, vsc *p) { return __builtin_vec_lvsm (a,p); }
++vsc lm16(long a, sc *p) { return __builtin_vec_lvsm (a,p); }
++vuc lm17(long a, vuc *p) { return __builtin_vec_lvsm (a,p); }
++vuc lm18(long a, uc *p) { return __builtin_vec_lvsm (a,p); }
++vsf Dlm01(long a, vsf *p) { return vec_lvsm (a,p); }
++vsf Dlm02(long a, sf *p) { return vec_lvsm (a,p); }
++vbi Dlm03(long a, vbi *p) { return vec_lvsm (a,p); }
++vsi Dlm04(long a, vsi *p) { return vec_lvsm (a,p); }
++vsi Dlm05(long a, si *p) { return vec_lvsm (a,p); }
++vui Dlm06(long a, vui *p) { return vec_lvsm (a,p); }
++vui Dlm07(long a, ui *p) { return vec_lvsm (a,p); }
++vbs Dlm08(long a, vbs *p) { return vec_lvsm (a,p); }
++vp Dlm09(long a, vp *p) { return vec_lvsm (a,p); }
++vss Dlm10(long a, vss *p) { return vec_lvsm (a,p); }
++vss Dlm11(long a, ss *p) { return vec_lvsm (a,p); }
++vus Dlm12(long a, vus *p) { return vec_lvsm (a,p); }
++vus Dlm13(long a, us *p) { return vec_lvsm (a,p); }
++vbc Dlm14(long a, vbc *p) { return vec_lvsm (a,p); }
++vsc Dlm15(long a, vsc *p) { return vec_lvsm (a,p); }
++vsc Dlm16(long a, sc *p) { return vec_lvsm (a,p); }
++vuc Dlm17(long a, vuc *p) { return vec_lvsm (a,p); }
++vuc Dlm18(long a, uc *p) { return vec_lvsm (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-2.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-2.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-2.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-2.c 2012-03-06 12:31:05.157039001 -0600
+@@ -0,0 +1,36 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "vabsduh" 7 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vus fa2h(vus a, vus b) { return __builtin_altivec_vabsduh (a,b); }
++vus ad4(vus a, vus b) { return __builtin_vec_absd (a,b); }
++vus ad5(vbs a, vus b) { return __builtin_vec_absd (a,b); }
++vus ad6(vus a, vbs b) { return __builtin_vec_absd (a,b); }
++vus Dad4(vus a, vus b) { return vec_absd (a,b); }
++vus Dad5(vbs a, vus b) { return vec_absd (a,b); }
++vus Dad6(vus a, vbs b) { return vec_absd (a,b); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-3.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-3.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-3.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-3.c 2012-03-06 12:31:05.157039001 -0600
+@@ -0,0 +1,36 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "vabsduw" 7 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vui fa3w(vui a, vui b) { return __builtin_altivec_vabsduw (a,b); }
++vui ad7(vui a, vui b) { return __builtin_vec_absd (a,b); }
++vui ad8(vbi a, vui b) { return __builtin_vec_absd (a,b); }
++vui ad9(vui a, vbi b) { return __builtin_vec_absd (a,b); }
++vui Dad7(vui a, vui b) { return vec_absd (a,b); }
++vui Dad8(vbi a, vui b) { return vec_absd (a,b); }
++vui Dad9(vui a, vbi b) { return vec_absd (a,b); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-4.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-4.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-4.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-4.c 2012-03-06 12:31:05.158039002 -0600
+@@ -0,0 +1,34 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvexbx" 5 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc le1b(long a, void *p) { return __builtin_altivec_lvexbx (a,p); }
++vsc leb1(long a, sc *p) { return __builtin_vec_lvexbx (a,p); }
++vuc leb2(long a, uc *p) { return __builtin_vec_lvexbx (a,p); }
++vsc Dleb1(long a, sc *p) { return vec_lvexbx (a,p); }
++vuc Dleb2(long a, uc *p) { return vec_lvexbx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-5.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-5.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-5.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-5.c 2012-03-06 12:31:05.158039002 -0600
+@@ -0,0 +1,34 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvexhx" 5 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vss le2h(long a, void *p) { return __builtin_altivec_lvexhx (a,p); }
++vss leh1(long a, ss *p) { return __builtin_vec_lvexhx (a,p); }
++vus leh2(long a, us *p) { return __builtin_vec_lvexhx (a,p); }
++vss Dleh1(long a, ss *p) { return vec_lvexhx (a,p); }
++vus Dleh2(long a, us *p) { return vec_lvexhx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-6.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-6.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-6.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-6.c 2012-03-06 12:31:05.158039002 -0600
+@@ -0,0 +1,40 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "lvexwx" 11 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsi le3w(long a, void *p) { return __builtin_altivec_lvexwx (a,p); }
++vsf lew1(long a, sf *p) { return __builtin_vec_lvexwx (a,p); }
++vsi lew2(long a, si *p) { return __builtin_vec_lvexwx (a,p); }
++vui lew3(long a, ui *p) { return __builtin_vec_lvexwx (a,p); }
++vsi lew4(long a, sl *p) { return __builtin_vec_lvexwx (a,p); }
++vui lew5(long a, ul *p) { return __builtin_vec_lvexwx (a,p); }
++vsf Dlew1(long a, sf *p) { return vec_lvexwx (a,p); }
++vsi Dlew2(long a, si *p) { return vec_lvexwx (a,p); }
++vui Dlew3(long a, ui *p) { return vec_lvexwx (a,p); }
++vsi Dlew4(long a, sl *p) { return vec_lvexwx (a,p); }
++vui Dlew5(long a, ul *p) { return vec_lvexwx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-7.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-7.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-7.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-7.c 2012-03-06 12:31:05.159039002 -0600
+@@ -0,0 +1,42 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvexbx" 13 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void se1b(vsc v, long a, vsc *p) { __builtin_altivec_stvexbx (v,a,p); }
++void seb1(vsc v, long a, sc *p) { __builtin_vec_stvexbx (v,a,p); }
++void seb2(vuc v, long a, uc *p) { __builtin_vec_stvexbx (v,a,p); }
++void seb3(vbc v, long a, sc *p) { __builtin_vec_stvexbx (v,a,p); }
++void seb4(vbc v, long a, uc *p) { __builtin_vec_stvexbx (v,a,p); }
++void seb5(vsc v, long a, void *p) { __builtin_vec_stvexbx (v,a,p); }
++void seb6(vuc v, long a, void *p) { __builtin_vec_stvexbx (v,a,p); }
++void Dseb1(vsc v, long a, sc *p) { vec_stvexbx (v,a,p); }
++void Dseb2(vuc v, long a, uc *p) { vec_stvexbx (v,a,p); }
++void Dseb3(vbc v, long a, sc *p) { vec_stvexbx (v,a,p); }
++void Dseb4(vbc v, long a, uc *p) { vec_stvexbx (v,a,p); }
++void Dseb5(vsc v, long a, void *p) { vec_stvexbx (v,a,p); }
++void Dseb6(vuc v, long a, void *p) { vec_stvexbx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-8.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-8.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-8.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-8.c 2012-03-06 12:31:05.159039002 -0600
+@@ -0,0 +1,42 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvexhx" 13 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void se2h(vss v, long a, vss *p) { __builtin_altivec_stvexhx (v,a,p); }
++void seh1(vss v, long a, ss *p) { __builtin_vec_stvexhx (v,a,p); }
++void seh2(vus v, long a, us *p) { __builtin_vec_stvexhx (v,a,p); }
++void seh3(vbs v, long a, ss *p) { __builtin_vec_stvexhx (v,a,p); }
++void seh4(vbs v, long a, us *p) { __builtin_vec_stvexhx (v,a,p); }
++void seh5(vss v, long a, void *p) { __builtin_vec_stvexhx (v,a,p); }
++void seh6(vus v, long a, void *p) { __builtin_vec_stvexhx (v,a,p); }
++void Dseh1(vss v, long a, ss *p) { vec_stvexhx (v,a,p); }
++void Dseh2(vus v, long a, us *p) { vec_stvexhx (v,a,p); }
++void Dseh3(vbs v, long a, ss *p) { vec_stvexhx (v,a,p); }
++void Dseh4(vbs v, long a, us *p) { vec_stvexhx (v,a,p); }
++void Dseh5(vss v, long a, void *p) { vec_stvexhx (v,a,p); }
++void Dseh6(vus v, long a, void *p) { vec_stvexhx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-9.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-9.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-9.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/altivec2_builtin-9.c 2012-03-06 12:31:05.159039002 -0600
+@@ -0,0 +1,46 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -maltivec2" } */
++/* { dg-final { scan-assembler-times "stvexwx" 17 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void se3w(vsi v, long a, vsi *p) { __builtin_altivec_stvexwx (v,a,p); }
++void sew1(vsf v, long a, sf *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew2(vsi v, long a, si *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew3(vui v, long a, ui *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew4(vbi v, long a, si *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew5(vbi v, long a, ui *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew6(vsf v, long a, void *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew7(vsi v, long a, void *p) { __builtin_vec_stvexwx (v,a,p); }
++void sew8(vui v, long a, void *p) { __builtin_vec_stvexwx (v,a,p); }
++void Dsew1(vsf v, long a, sf *p) { vec_stvexwx (v,a,p); }
++void Dsew2(vsi v, long a, si *p) { vec_stvexwx (v,a,p); }
++void Dsew3(vui v, long a, ui *p) { vec_stvexwx (v,a,p); }
++void Dsew4(vbi v, long a, si *p) { vec_stvexwx (v,a,p); }
++void Dsew5(vbi v, long a, ui *p) { vec_stvexwx (v,a,p); }
++void Dsew6(vsf v, long a, void *p) { vec_stvexwx (v,a,p); }
++void Dsew7(vsi v, long a, void *p) { vec_stvexwx (v,a,p); }
++void Dsew8(vui v, long a, void *p) { vec_stvexwx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-1.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-1.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-1.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-1.c 2012-03-06 12:31:15.921038995 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "lvlx" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc1(long a, void *p) { return __builtin_altivec_lvlx (a,p); }
++vsf llx01(long a, vsf *p) { return __builtin_vec_lvlx (a,p); }
++vsf llx02(long a, sf *p) { return __builtin_vec_lvlx (a,p); }
++vbi llx03(long a, vbi *p) { return __builtin_vec_lvlx (a,p); }
++vsi llx04(long a, vsi *p) { return __builtin_vec_lvlx (a,p); }
++vsi llx05(long a, si *p) { return __builtin_vec_lvlx (a,p); }
++vui llx06(long a, vui *p) { return __builtin_vec_lvlx (a,p); }
++vui llx07(long a, ui *p) { return __builtin_vec_lvlx (a,p); }
++vbs llx08(long a, vbs *p) { return __builtin_vec_lvlx (a,p); }
++vp llx09(long a, vp *p) { return __builtin_vec_lvlx (a,p); }
++vss llx10(long a, vss *p) { return __builtin_vec_lvlx (a,p); }
++vss llx11(long a, ss *p) { return __builtin_vec_lvlx (a,p); }
++vus llx12(long a, vus *p) { return __builtin_vec_lvlx (a,p); }
++vus llx13(long a, us *p) { return __builtin_vec_lvlx (a,p); }
++vbc llx14(long a, vbc *p) { return __builtin_vec_lvlx (a,p); }
++vsc llx15(long a, vsc *p) { return __builtin_vec_lvlx (a,p); }
++vsc llx16(long a, sc *p) { return __builtin_vec_lvlx (a,p); }
++vuc llx17(long a, vuc *p) { return __builtin_vec_lvlx (a,p); }
++vuc llx18(long a, uc *p) { return __builtin_vec_lvlx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-2.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-2.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-2.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-2.c 2012-03-06 12:31:15.921038995 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "lvlxl" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc2(long a, void *p) { return __builtin_altivec_lvlxl (a,p); }
++vsf llxl01(long a, vsf *p) { return __builtin_vec_lvlxl (a,p); }
++vsf llxl02(long a, sf *p) { return __builtin_vec_lvlxl (a,p); }
++vbi llxl03(long a, vbi *p) { return __builtin_vec_lvlxl (a,p); }
++vsi llxl04(long a, vsi *p) { return __builtin_vec_lvlxl (a,p); }
++vsi llxl05(long a, si *p) { return __builtin_vec_lvlxl (a,p); }
++vui llxl06(long a, vui *p) { return __builtin_vec_lvlxl (a,p); }
++vui llxl07(long a, ui *p) { return __builtin_vec_lvlxl (a,p); }
++vbs llxl08(long a, vbs *p) { return __builtin_vec_lvlxl (a,p); }
++vp llxl09(long a, vp *p) { return __builtin_vec_lvlxl (a,p); }
++vss llxl10(long a, vss *p) { return __builtin_vec_lvlxl (a,p); }
++vss llxl11(long a, ss *p) { return __builtin_vec_lvlxl (a,p); }
++vus llxl12(long a, vus *p) { return __builtin_vec_lvlxl (a,p); }
++vus llxl13(long a, us *p) { return __builtin_vec_lvlxl (a,p); }
++vbc llxl14(long a, vbc *p) { return __builtin_vec_lvlxl (a,p); }
++vsc llxl15(long a, vsc *p) { return __builtin_vec_lvlxl (a,p); }
++vsc llxl16(long a, sc *p) { return __builtin_vec_lvlxl (a,p); }
++vuc llxl17(long a, vuc *p) { return __builtin_vec_lvlxl (a,p); }
++vuc llxl18(long a, uc *p) { return __builtin_vec_lvlxl (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-3.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-3.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-3.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-3.c 2012-03-06 12:31:15.922038996 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "lvrx" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc3(long a, void *p) { return __builtin_altivec_lvrx (a,p); }
++vsf lrx01(long a, vsf *p) { return __builtin_vec_lvrx (a,p); }
++vsf lrx02(long a, sf *p) { return __builtin_vec_lvrx (a,p); }
++vbi lrx03(long a, vbi *p) { return __builtin_vec_lvrx (a,p); }
++vsi lrx04(long a, vsi *p) { return __builtin_vec_lvrx (a,p); }
++vsi lrx05(long a, si *p) { return __builtin_vec_lvrx (a,p); }
++vui lrx06(long a, vui *p) { return __builtin_vec_lvrx (a,p); }
++vui lrx07(long a, ui *p) { return __builtin_vec_lvrx (a,p); }
++vbs lrx08(long a, vbs *p) { return __builtin_vec_lvrx (a,p); }
++vp lrx09(long a, vp *p) { return __builtin_vec_lvrx (a,p); }
++vss lrx10(long a, vss *p) { return __builtin_vec_lvrx (a,p); }
++vss lrx11(long a, ss *p) { return __builtin_vec_lvrx (a,p); }
++vus lrx12(long a, vus *p) { return __builtin_vec_lvrx (a,p); }
++vus lrx13(long a, us *p) { return __builtin_vec_lvrx (a,p); }
++vbc lrx14(long a, vbc *p) { return __builtin_vec_lvrx (a,p); }
++vsc lrx15(long a, vsc *p) { return __builtin_vec_lvrx (a,p); }
++vsc lrx16(long a, sc *p) { return __builtin_vec_lvrx (a,p); }
++vuc lrx17(long a, vuc *p) { return __builtin_vec_lvrx (a,p); }
++vuc lrx18(long a, uc *p) { return __builtin_vec_lvrx (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-4.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-4.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-4.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-4.c 2012-03-06 12:31:15.922038996 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "lvrxl" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++vsc lc4(long a, void *p) { return __builtin_altivec_lvrxl (a,p); }
++vsf lrxl01(long a, vsf *p) { return __builtin_vec_lvrxl (a,p); }
++vsf lrxl02(long a, sf *p) { return __builtin_vec_lvrxl (a,p); }
++vbi lrxl03(long a, vbi *p) { return __builtin_vec_lvrxl (a,p); }
++vsi lrxl04(long a, vsi *p) { return __builtin_vec_lvrxl (a,p); }
++vsi lrxl05(long a, si *p) { return __builtin_vec_lvrxl (a,p); }
++vui lrxl06(long a, vui *p) { return __builtin_vec_lvrxl (a,p); }
++vui lrxl07(long a, ui *p) { return __builtin_vec_lvrxl (a,p); }
++vbs lrxl08(long a, vbs *p) { return __builtin_vec_lvrxl (a,p); }
++vp lrxl09(long a, vp *p) { return __builtin_vec_lvrxl (a,p); }
++vss lrxl10(long a, vss *p) { return __builtin_vec_lvrxl (a,p); }
++vss lrxl11(long a, ss *p) { return __builtin_vec_lvrxl (a,p); }
++vus lrxl12(long a, vus *p) { return __builtin_vec_lvrxl (a,p); }
++vus lrxl13(long a, us *p) { return __builtin_vec_lvrxl (a,p); }
++vbc lrxl14(long a, vbc *p) { return __builtin_vec_lvrxl (a,p); }
++vsc lrxl15(long a, vsc *p) { return __builtin_vec_lvrxl (a,p); }
++vsc lrxl16(long a, sc *p) { return __builtin_vec_lvrxl (a,p); }
++vuc lrxl17(long a, vuc *p) { return __builtin_vec_lvrxl (a,p); }
++vuc lrxl18(long a, uc *p) { return __builtin_vec_lvrxl (a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-5.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-5.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-5.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-5.c 2012-03-06 12:31:15.922038996 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "stvlx" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc1(vsc v, long a, void *p) { __builtin_altivec_stvlx (v,a,p); }
++void slx01(vsf v, long a, vsf *p) { __builtin_vec_stvlx (v,a,p); }
++void slx02(vsf v, long a, sf *p) { __builtin_vec_stvlx (v,a,p); }
++void slx03(vbi v, long a, vbi *p) { __builtin_vec_stvlx (v,a,p); }
++void slx04(vsi v, long a, vsi *p) { __builtin_vec_stvlx (v,a,p); }
++void slx05(vsi v, long a, si *p) { __builtin_vec_stvlx (v,a,p); }
++void slx06(vui v, long a, vui *p) { __builtin_vec_stvlx (v,a,p); }
++void slx07(vui v, long a, ui *p) { __builtin_vec_stvlx (v,a,p); }
++void slx08(vbs v, long a, vbs *p) { __builtin_vec_stvlx (v,a,p); }
++void slx09(vp v, long a, vp *p) { __builtin_vec_stvlx (v,a,p); }
++void slx10(vss v, long a, vss *p) { __builtin_vec_stvlx (v,a,p); }
++void slx11(vss v, long a, ss *p) { __builtin_vec_stvlx (v,a,p); }
++void slx12(vus v, long a, vus *p) { __builtin_vec_stvlx (v,a,p); }
++void slx13(vus v, long a, us *p) { __builtin_vec_stvlx (v,a,p); }
++void slx14(vbc v, long a, vbc *p) { __builtin_vec_stvlx (v,a,p); }
++void slx15(vsc v, long a, vsc *p) { __builtin_vec_stvlx (v,a,p); }
++void slx16(vsc v, long a, sc *p) { __builtin_vec_stvlx (v,a,p); }
++void slx17(vuc v, long a, vuc *p) { __builtin_vec_stvlx (v,a,p); }
++void slx18(vuc v, long a, uc *p) { __builtin_vec_stvlx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-6.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-6.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-6.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-6.c 2012-03-06 12:31:15.923039000 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "stvlxl" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc2(vsc v, long a, void *p) { __builtin_altivec_stvlxl (v,a,p); }
++void slxl01(vsf v, long a, vsf *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl02(vsf v, long a, sf *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl03(vbi v, long a, vbi *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl04(vsi v, long a, vsi *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl05(vsi v, long a, si *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl06(vui v, long a, vui *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl07(vui v, long a, ui *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl08(vbs v, long a, vbs *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl09(vp v, long a, vp *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl10(vss v, long a, vss *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl11(vss v, long a, ss *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl12(vus v, long a, vus *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl13(vus v, long a, us *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl14(vbc v, long a, vbc *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl15(vsc v, long a, vsc *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl16(vsc v, long a, sc *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl17(vuc v, long a, vuc *p) { __builtin_vec_stvlxl (v,a,p); }
++void slxl18(vuc v, long a, uc *p) { __builtin_vec_stvlxl (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-7.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-7.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-7.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-7.c 2012-03-06 12:31:15.923039000 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "stvrx" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc3(vsc v, long a, void *p) { __builtin_altivec_stvrx (v,a,p); }
++void srx01(vsf v, long a, vsf *p) { __builtin_vec_stvrx (v,a,p); }
++void srx02(vsf v, long a, sf *p) { __builtin_vec_stvrx (v,a,p); }
++void srx03(vbi v, long a, vbi *p) { __builtin_vec_stvrx (v,a,p); }
++void srx04(vsi v, long a, vsi *p) { __builtin_vec_stvrx (v,a,p); }
++void srx05(vsi v, long a, si *p) { __builtin_vec_stvrx (v,a,p); }
++void srx06(vui v, long a, vui *p) { __builtin_vec_stvrx (v,a,p); }
++void srx07(vui v, long a, ui *p) { __builtin_vec_stvrx (v,a,p); }
++void srx08(vbs v, long a, vbs *p) { __builtin_vec_stvrx (v,a,p); }
++void srx09(vp v, long a, vp *p) { __builtin_vec_stvrx (v,a,p); }
++void srx10(vss v, long a, vss *p) { __builtin_vec_stvrx (v,a,p); }
++void srx11(vss v, long a, ss *p) { __builtin_vec_stvrx (v,a,p); }
++void srx12(vus v, long a, vus *p) { __builtin_vec_stvrx (v,a,p); }
++void srx13(vus v, long a, us *p) { __builtin_vec_stvrx (v,a,p); }
++void srx14(vbc v, long a, vbc *p) { __builtin_vec_stvrx (v,a,p); }
++void srx15(vsc v, long a, vsc *p) { __builtin_vec_stvrx (v,a,p); }
++void srx16(vsc v, long a, sc *p) { __builtin_vec_stvrx (v,a,p); }
++void srx17(vuc v, long a, vuc *p) { __builtin_vec_stvrx (v,a,p); }
++void srx18(vuc v, long a, uc *p) { __builtin_vec_stvrx (v,a,p); }
+diff -ruN gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-8.c gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-8.c
+--- gcc-4.6.2-orig/gcc/testsuite/gcc.target/powerpc/cell_builtin-8.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.2/gcc/testsuite/gcc.target/powerpc/cell_builtin-8.c 2012-03-06 12:31:15.923039000 -0600
+@@ -0,0 +1,48 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_altivec_ok } */
++/* { dg-options "-O2 -maltivec -mcpu=cell" } */
++/* { dg-final { scan-assembler-times "stvrxl" 19 } } */
++
++#include <altivec.h>
++
++typedef __vector signed char vsc;
++typedef __vector signed short vss;
++typedef __vector signed int vsi;
++typedef __vector unsigned char vuc;
++typedef __vector unsigned short vus;
++typedef __vector unsigned int vui;
++typedef __vector bool char vbc;
++typedef __vector bool short vbs;
++typedef __vector bool int vbi;
++typedef __vector float vsf;
++typedef __vector pixel vp;
++typedef signed char sc;
++typedef signed short ss;
++typedef signed int si;
++typedef signed long sl;
++typedef unsigned char uc;
++typedef unsigned short us;
++typedef unsigned int ui;
++typedef unsigned long ul;
++typedef float sf;
++
++void sc4(vsc v, long a, void *p) { __builtin_altivec_stvrxl (v,a,p); }
++void srxl01(vsf v, long a, vsf *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl02(vsf v, long a, sf *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl03(vbi v, long a, vbi *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl04(vsi v, long a, vsi *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl05(vsi v, long a, si *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl06(vui v, long a, vui *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl07(vui v, long a, ui *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl08(vbs v, long a, vbs *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl09(vp v, long a, vp *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl10(vss v, long a, vss *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl11(vss v, long a, ss *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl12(vus v, long a, vus *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl13(vus v, long a, us *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl14(vbc v, long a, vbc *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl15(vsc v, long a, vsc *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl16(vsc v, long a, sc *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl17(vuc v, long a, vuc *p) { __builtin_vec_stvrxl (v,a,p); }
++void srxl18(vuc v, long a, uc *p) { __builtin_vec_stvrxl (v,a,p); }
--- /dev/null
+diff -ruN gcc-4.4.0/gcc/config/rs6000/rs6000.c gcc-4.4.0-e500mc64/gcc/config/rs6000/rs6000.c
+--- gcc-4.4.0/gcc/config/rs6000/rs6000.c 2009-03-17 15:18:21.000000000 -0500
++++ gcc-4.4.0-e500mc64/gcc/config/rs6000/rs6000.c 2009-12-04 10:36:44.000000000 -0600
+@@ -11032,6 +11059,14 @@
+ mode = SImode;
+ gen_func.mov = gen_movsi;
+ }
++ else if (TARGET_COPY_UNALIGNED && bytes == 3 && offset > 0)
++ {
++ /* We generate a single unaligned SI move instead of 2 (HI, QI) */
++ move_bytes = 3;
++ mode = SImode;
++ gen_func.mov = gen_movsi;
++ offset--;
++ }
+ else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
+ { /* move 2 bytes */
+ move_bytes = 2;
+diff -ruN gcc-4.4.0/gcc/config/rs6000/rs6000.opt gcc-4.4.0-e500mc64/gcc/config/rs6000/rs6000.opt
+--- gcc-4.4.0/gcc/config/rs6000/rs6000.opt 2009-02-20 09:20:38.000000000 -0600
++++ gcc-4.4.0-e500mc64/gcc/config/rs6000/rs6000.opt 2009-09-30 13:51:17.000000000 -0500
+@@ -201,6 +201,10 @@
+ Target RejectNegative Joined
+ -misel=yes/no Deprecated option. Use -misel/-mno-isel instead
+
++mcopy-unaligned
++Target Report Var(TARGET_COPY_UNALIGNED)
++Generate unaligned word load and stores to move 3 bytes
++
+ mspe
+ Target
+ Generate SPE SIMD instructions on E500
--- /dev/null
+Eliminate sign and zero extensions in PPC generated code
+A new module is introduced 'extelim.c' and a new RTL pass is introduced.
+The '-f[no-]extelim' flag controls this pass and is enabled at -O2 and above.
+The algorithm is based on the paper "Effective Sign Extension Elimination", Kawahito, et. al.
+More details on implementation in the extelim.c module.
+
+--- gcc-4.6-branch-clean/gcc/opts.c 2011-07-27 12:02:02.483850879 -0500
++++ gcc-4.6-branch/gcc/opts.c 2011-07-25 17:59:00.911975444 -0500
+@@ -492,6 +492,7 @@
+ { OPT_LEVELS_2_PLUS, OPT_falign_jumps, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_falign_labels, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_falign_functions, NULL, 1 },
++ { OPT_LEVELS_2_PLUS, OPT_fextelim, NULL, 1 },
+
+ /* -O3 optimizations. */
+ { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
+--- gcc-4.6-branch-clean/gcc/tree-pass.h 2011-07-27 12:02:02.485981448 -0500
++++ gcc-4.6-branch/gcc/tree-pass.h 2011-07-25 17:59:00.912976334 -0500
+@@ -483,6 +483,7 @@
+ extern struct rtl_opt_pass pass_initial_value_sets;
+ extern struct rtl_opt_pass pass_unshare_all_rtl;
+ extern struct rtl_opt_pass pass_instantiate_virtual_regs;
++extern struct rtl_opt_pass pass_rtl_extelim;
+ extern struct rtl_opt_pass pass_rtl_fwprop;
+ extern struct rtl_opt_pass pass_rtl_fwprop_addr;
+ extern struct rtl_opt_pass pass_jump2;
+--- gcc-4.6-branch-clean/gcc/timevar.def 2011-07-27 12:02:02.487999008 -0500
++++ gcc-4.6-branch/gcc/timevar.def 2011-07-25 17:59:00.913979563 -0500
+@@ -180,6 +180,7 @@
+ DEFTIMEVAR (TV_VARCONST , "varconst")
+ DEFTIMEVAR (TV_LOWER_SUBREG , "lower subreg")
+ DEFTIMEVAR (TV_JUMP , "jump")
++DEFTIMEVAR (TV_EXTELIM , "extension elimination")
+ DEFTIMEVAR (TV_FWPROP , "forward prop")
+ DEFTIMEVAR (TV_CSE , "CSE")
+ DEFTIMEVAR (TV_DCE , "dead code elimination")
+--- gcc-4.6-branch-clean/gcc/common.opt 2011-07-27 12:02:02.490978128 -0500
++++ gcc-4.6-branch/gcc/common.opt 2011-07-25 17:59:00.915979093 -0500
+@@ -996,6 +996,10 @@
+ Common Report Var(flag_eliminate_dwarf2_dups)
+ Perform DWARF2 duplicate elimination
+
++fextelim
++Common Report Var(flag_extelim)
++Perform zero/sign extension removal
++
+ fipa-sra
+ Common Report Var(flag_ipa_sra) Init(0) Optimization
+ Perform interprocedural reduction of aggregates
+--- gcc-4.6-branch-clean/gcc/Makefile.in 2011-07-27 12:02:02.498976606 -0500
++++ gcc-4.6-branch/gcc/Makefile.in 2011-07-25 17:59:00.919975303 -0500
+@@ -1233,6 +1233,7 @@
+ explow.o \
+ expmed.o \
+ expr.o \
++ extelim.o \
+ final.o \
+ fixed-value.o \
+ fold-const.o \
+@@ -2891,6 +2892,11 @@
+ reload.h langhooks.h intl.h $(TM_P_H) $(TARGET_H) \
+ tree-iterator.h gt-expr.h $(MACHMODE_H) $(TIMEVAR_H) $(TREE_FLOW_H) \
+ $(TREE_PASS_H) $(DF_H) $(DIAGNOSTIC_H) vecprim.h $(SSAEXPAND_H)
++extelim.o : extelim.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
++ $(TREE_H) $(TM_P_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h $(BASIC_BLOCK_H) \
++ insn-config.h $(FUNCTION_H) $(EXPR_H) $(INSN_ATTR_H) $(RECOG_H) \
++ toplev.h $(TARGET_H) $(TIMEVAR_H) $(OPTABS_H) insn-codes.h \
++ output.h $(PARAMS_H) $(TREE_PASS_H) $(CGRAPH_H)
+ dojump.o : dojump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
+ $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) $(OPTABS_H) $(INSN_ATTR_H) insn-config.h \
+ langhooks.h $(GGC_H) gt-dojump.h vecprim.h $(BASIC_BLOCK_H) output.h
+--- gcc-4.6-branch-clean/gcc/passes.c 2011-07-27 12:02:02.502976386 -0500
++++ gcc-4.6-branch/gcc/passes.c 2011-07-25 17:59:00.922975752 -0500
+@@ -990,6 +990,7 @@
+ NEXT_PASS (pass_web);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_cse2);
++ NEXT_PASS (pass_rtl_extelim);
+ NEXT_PASS (pass_rtl_dse1);
+ NEXT_PASS (pass_rtl_fwprop_addr);
+ NEXT_PASS (pass_inc_dec);
+--- gcc-4.6.1-clean/gcc/extelim.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.1/gcc/extelim.c 2011-11-14 15:43:10.041143996 -0600
+@@ -0,0 +1,3407 @@
++/* Redundant extension elimination
++ Copyright (C) 2010 Free Software Foundation, Inc.
++ Contributed by John Russo (john.russo@freescale.com)
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++/*
++PURPOSE: Implement a method for eliminating redundant and superflous sign
++extension instructions from 64-bit PPC e5500 generated code.
++
++MOTIVATING EXAMPLE:
++The Nullstone loop_6.c kernel looks like:
++ int i;
++ int a[100];
++
++ ref_int_p (&a[0]);
++
++ for (i=2; i<100; i++)
++ a[i] = a[i-1] + a[i-2];
++
++The final, generated code for the loop body is:
++
++32-bit 64-bit
++add r25,r11,r0 add r5,r5,r8
++add r26,r0,r25 addi r4,r4,12
++stw r25,0(r9) add r27,r5,r8
++add r27,r25,r26 stw r5,0(r9)
++stw r26,4(r9) extsw r12,r27 <===
++add r28,r26,r27 stw r27,4(r9)
++stw r27,8(r9) add r6,r5,r12
++add r29,r27,r28 add r28,r6,r12
++stw r28,12(r9) stw r6,8(r9)
++add r30,r28,r29 extsw r0,r28 <===
++stw r29,16(r9) stw r28,12(r9)
++add r12,r29,r30 add r7,r6,r0
++stw r30,20(r9) add r29,r7,r0
++add r3,r30,r12 stw r7,16(r9)
++stw r12,24(r9) extsw r3,r29 <===
++add r4,r12,r3 stw r29,20(r9)
++stw r3,28(r9) add r10,r7,r3
++add r5,r3,r4 add r30,r10,r3
++stw r4,32(r9) stw r10,24(r9)
++add r6,r4,r5 extsw r8,r30 <===
++stw r5,36(r9) stw r30,28(r9)
++add r7,r5,r6 add r11,r10,r8
++stw r6,40(r9) add r12,r11,r8
++add r8,r6,r7 stw r11,32(r9)
++stw r7,44(r9) extsw r26,r12 <===
++add r10,r7,r8 stw r12,36(r9)
++stw r8,48(r9) add r0,r11,r26
++add r11,r8,r10 add r3,r0,r26
++stw r10,52(r9) stw r0,40(r9)
++add r0,r10,r11 subfic r26,r4,100
++stw r11,56(r9) stw r3,44(r9)
++stw r0,60(r9) extsw r5,r0 <===
++addi r9,r9,64 extsw r8,r3 <===
++bdnz+ 10000640 extsw r4,r4 <===
++ clrldi r26,r26,32
++ addi r9,r9,48
++ bdnz+ 10000890
++
++GENERAL APPROACH:
++Consider a machine whose native register size is 64-bits
++
++0 3132 63
++|-----------||-----------|
++
++where bit 63 is the LSB and bit 0 is the MSB of a long int
++and bit 63 is the LSB and bit 32 is the MSB of an int.
++
++Sign and zero extension are inserted to RTL to preserve the
++operation's semantics when the operands used are not the
++native register size since normally the machine only performs
++the operation using a native register size. In practice, many
++of the inserted extensions are not necessary.
++
++First, the extension may simply be redundant. That is, the
++same operation is performed on the same operands. The redundant
++extensions can be eliminated.
++
++Secondly, if the extended portion of the register (the "upper" bits)
++are not essential to the calculations performed on the output of the
++extension, then the extension is not necessary. For example, given
++int (32-bit) inputs and outputs:
++
++c = a + b
++d = sxt(c)
++e = d + 1;
++
++The "upper" bits of d (bit 0-31) do not affect the calculation
++of e. It doesn't matter what the "upper" bits of d are, the int result
++e is the same regardless of the sxt instruction.
++
++Thirdly, the extensions may not be necessary if the operands are
++already extended and the operation preserves the extended bits.
++
++a = mem[&b] ; sign extending load
++c = a + 1
++d = sxt(c)
++
++Here, a is generated by a sign extending load, the operation
++does nothing to invalidate the extension to c, thus the extension
++on c to d is not necessary.
++
++In each case, the redundant extension must be replaced by a copy,
++with the copy to be optimized out in later phases.
++
++The three cases described above form the general idea behind the
++algorithms implemented here to eliminate redundant and unneccessary
++extensions.
++
++Sign extensions do not have to be preserved for overflow conditions
++since signed overflow behavior is not defined in C. For example,
++take a 16-bit variable in a 32-bit register. It is ok
++for 0x0000_7fff to overflow to 0x0000_8000 and not 0xffff_8000.
++This implies that it is not necessary to preserve the sign
++extension.
++
++Unsigned overflow extension need to be preserved because
++unsigned overflow is modulo. For example, a 16-bit unsigned
++overflow of 0x0000_FFFF must be 0x0000_0000 in a 32-bit register,
++not 0x0001_0000. In order to remove the unsigned zero extension,
++we would need to range check the variable to be sure it doesn't
++overflow.
++
++RTL ANALYSIS:
++I looked at the RTL representation after RTL generation (.expand) and
++after the first forward propagation (.fwprop1). Since RTL is not compact
++when printing out, I reduced the .fwprop1 RTL to this pseudocode:
++
++(note: sxt,zxt mean double word length, 64-bit, extension).
++
++(1) r198 = m[r113+ #112] ; load a[0]
++(2) r174 = sxt(r198)
++(3) r199 = m[r113+ #116] ; load a[1]
++(4) r186 = sxt(r199)
++(5) r181 = r113 + #120 ; load &a[2]
++(6) r180 = 2 ; i = 2
++(7) L1:
++(8) r200 = r174 + r186 ; t1 = a[i-1] + a[i-2]
++(9) r174 = sxt(r200)
++(10) m[r181] = r200 ; a[i] = t1
++(11) r201 = r200 + r186 ; t2 = t1 + a[i-1]
++(12) r186 = sxt(r201)
++(13) m[r181+4] = r201 ; a[i+1] = t2
++(14) r202 = r180 + 2 ; i += 2
++(14.1) r180 = sxt(r202)
++(15) r203 = 100 - r202 ; used to calc loop remainder
++(16) r185 = zxt(r203) ; used to calc loop remainder
++(17) r181 = r181 + 8 ; address induction var
++(18) ccr204 = cmp(r202,#98) ; set CC
++(19) BNE ccr204,L1 ; branch
++
++In the pseudo-code, you see several sign extension candidates: (2),(4),
++(9), (12), (14.1), (16).
++
++ALGORITHM:
++To eliminate the extra sign ext you have to look at (1) the definitions
++of the source of the sign extensions and/or (2) look at the uses of the target
++of the sign extensions. In either case, if doing a global elimination
++pass, you'll need def-use chain information.
++
++The algorithms are recursive. Using the use/def and def/use chains
++we attempt to find ultimately whether the extension is relevant
++or not.
++
++
++Example 1.
++Extensions (2) and (4) are not put in the candidate list because
++they are combined into a load/ext pair that is ultimately generated
++as sign extending loads.
++
++Take the sign extension at (9), r174 = sxt(r200).
++Def analysis shows that r200 is defined by 2 registers, thus no
++further def analysis recursion can occur.
++Use analysis. Find all the uses of r174. There is 1 use at (8) r200 = r174 + r186.
++The extension does not affect the add operation results. Continuing, we look at
++the uses of r200 to see if the results of operations on r200 need the sign extended bits.
++We see 2 uses of r200 at (10) and (11). (10) is a 32-bit store of r200,
++so the sign extended bits are irrelevant. (11), however, is an unknown,
++so we must look that the uses of this result, r201. A similar sequence
++occurs for r201 when it defines r186. Looking at the uses of r186 at
++(8) and (11), we have already visited those statements so they have
++been covered already. So it appears that the sxt to r174 at (9) ultimately
++dead-ends to a store instruction that doesn't case about the sign extended
++bits. The sxt at (9) can be removed.
++
++The remaining extensions are processed similarly.
++
++PROGRAM STRUCTURE:
++
++extension elimination -- main entry point
++ find extensions -- identify extension candidates
++ extension duplication -- insert extension at strategic points to
++ enable removal of extensions at more frequently
++ executed points.
++ find extensions -- recreate extension candidate list
++ sort extensions -- sort extension candidate list by loop depth
++ for each ext in list -- process each extension candidate
++ eliminate one extension
++ replace marked candidates with copy -- optimize the extension
++
++PSEUDOCODE:
++
++Create working list of sign extensions, sxt_list
++
++For each insn, insn_sxt, in sxt_list
++ ext_needed = true
++ For all insns, insn_def, that DEFINE and REACH the SOURCE_REG(insn_sxt)
++ ext_needed = analyze_def(insn_def, insn_sxt)
++ if (ext_needed)
++ break;
++ end_loop
++ if (ext_needed)
++ For all insns, insn_use, that USE and are REACHED by the DEST_REG(insn_sxt)
++ ext_needed = analyze_use(insn_use, insn_sxt)
++ if (ext_needed)
++ break;
++ end_loop
++
++ if (!ext_needed)
++ mark_for_replace_with_copy(I)
++end_loop
++
++For each insn, insn_sxt, in sxt_list
++ if (insn_sxt is marked for replacement)
++ replace_insn_with_copy(insn_sxt)
++end_loop
++
++--------------------------
++function: analyze_def(def)
++---------------------------
++return true if extension is needed, false otherwise.
++
++destination_operand = defined operand of source
++source_operand = source operand of def
++
++if (have_seen_this_insn_already (def))
++ return true;
++
++set_seen_this_insn_flag (def)
++
++analysis_result = analyze_result_def (def)
++switch (analysis_result)
++ case source_operand_is_extended:
++ return false
++ case stop_recursion:
++ return true
++ case continue_recursion:
++ break;
++
++ext_needed = true;
++
++For all insns, insn_def, that USE and REACHED by the register of destination_operand
++ ext_needed = analyze_def(insn_def))
++ if (ext_needed)
++ break;
++end_loop
++
++return ext_needed
++
++--------------------------
++function: analyze_use(use)
++---------------------------
++return true if extension is needed, false otherwise.
++
++destination_operand = destination operand of use
++source_operand = source operand of use
++
++if (have_seen_this_insn_already (use))
++ return false;
++
++set_seen_this_insn_flag (use)
++
++analysis_result = analyze_result_use (use)
++switch (analysis_result)
++ case low_bits_not_affected_by_use:
++ return false
++ case low_bits_affected_by_use:
++ return true
++ case look_at_uses_of_destination_operand
++ break;
++
++ext_needed = true;
++For all insns, insn_use, that USE the register of destination_operand
++ ext_needed = analyze_use(insn_use))
++ if (ext_needed)
++ break;
++end_loop
++
++return ext_needed
++
++REFERENCES:
++
++"Effective Sign Extension Elimination", Kawahito, Komatsu, Nakatani.
++IBM Tokyo Researc Laboratory.
++
++"New sign/zero extension elimination pass", deVries.
++http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01529.html
++*/
++
++/*
++Iteration 4: pre-ZERO_EXTEND version, duplicates sign_extend at uses
++Iteration 5: begin supporting ZERO_EXTEND, crashes on Coremark.
++Iteration 6: revert to 4, support SI:HI sign_extensions.
++Iteration 7: Add support for zero extend. This version deletes
++ "inserted" duplicate extensions when redundant and propagates
++ the copied value. This propagate fails in other_tests/test2.sh.
++ I am reverting back to replacing the "inserted" extension to a copy.
++ Copy propagation should always be able to eliminate this copy.
++ Coremark was stable, however.
++Iteration 8: Revert to change extensions to copy, regardless of whether
++ the extension was duplicated or not.
++ Refactor setting of dest,src in analyze_ext_use, analyze_ext_def, now
++ handled with a single function.
++Iteration 9:
++ Inserted redundant extensions at function return points.
++ Sorted the order that extensions are processed by loop depth.
++ Additional cases in upper_bits_do_not_affect_dest
++Iteration 10:
++ Fixes for test failures. A major problem was uncovered where
++ the "visited" flag was not properly cleared. This meant that
++ each time a new extension was processed, it appeared that some
++ extensions were visited already and there were not. The result
++ was false removals. This fix significantly affects the benchmark.
++ Another change was to comment out the duplicate_exts_at_uses. This
++ seemed to have little effect now that the visited flag issue is
++ fixed.
++Iteration 11:
++ Cleanup warnings during build.
++Iteration 12:
++ QImode support started.
++Iteration 13:
++ Redesign and refactor analyze_ext_use, analyze_ext_def
++Iteration 14:
++ Continue redesign and refactor of analyze_ext_use, analyze_ext_def
++ Debugging paper_example.c
++Iteration 15:
++ cond_c fix
++Iteration 16: (not tested)
++ Refactor check_compare code
++ Refactor action decision in PARALLEL
++ Allow pass-thru on insns that are marked for replace copy
++ instead of stopping recursion if we see a marked insn.
++ Examining lshiftrt.c program (signed and unsigned).
++Iteration 17:
++ Refactor mostly complete. Passed all local testing including
++ nas and perfect. Best coremark results so far.
++Iteration 18:
++ Oops. analyze_ext_def was disabled. Enabling it improves
++ Coremark. Passed coremark, perfect.
++Iteration 19:
++ Local tests are passing. Tested with glibc.
++ Added statistics.
++ Fixed elimination from CALL output in operand_is_extended.
++ This impacted Coremark went from 6300 to 6170. But is necessary.
++ More safety for used regs in analyze_ext_def.
++ More safety for the types of extensions.
++Iteration 20:
++ Fixes for various tests.
++Iteration 21:
++ pr43017 -funroll_loops fix.
++Iteration 22:
++ Fixes for AND immediate in operand_is_extended.
++ Cosmetic cleanup.
++Iteration 23:
++ Fixes for consumer-2,spec2k,spec2k6. Handle
++ SUBREG_PROMOTED_VAR_P flags on operands whose
++ dependent extension has been eliminated.
++Iteration 24:
++ Fixed problem in native build during bootstrapping.
++ Extelim was considering debug_insns and should have
++ ignored them. This resulted in a compare fail between
++ stage2 and stage3.
++Iteration 25:
++ - Post-release 4.6.1 development
++ - Full duplication of extensions at uses turned on.
++ - Recursion into original extension no longer kills optimization (analyze_ext_def only)
++ - Allow some duplication into the same block if it enables insn selection
++ - Allow CCmode and CCUNSmode into mode_supported_p
++Iteration 26:
++ - Solve ICEs due to null df-ref.
++Iteration 27:
++ - Fixed issue with duplication of extension at a self-assign.
++ - Some fixes for copying flags during duplication
++ - Some fixes for counting register uses.
++Iteration 28:
++ - Fixed issue with duplication of extension when use has multiple
++ reaching definitions.
++Iteration 29:
++ - Release candidate for Q42011 release iteration.
++Iteration 30:
++ - Turn off extension duplication - minimally effective
++
++*/
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "rtl.h"
++#include "tree.h"
++#include "tm_p.h"
++#include "flags.h"
++#include "regs.h"
++#include "hard-reg-set.h"
++#include "basic-block.h"
++#include "insn-config.h"
++#include "function.h"
++#include "expr.h"
++#include "insn-attr.h"
++#include "recog.h"
++#include "toplev.h"
++#include "target.h"
++#include "timevar.h"
++#include "optabs.h"
++#include "insn-codes.h"
++#include "rtlhooks-def.h"
++#include "output.h"
++#include "params.h"
++#include "timevar.h"
++#include "tree-pass.h"
++#include "cgraph.h"
++#include "df.h"
++#include "vec.h"
++
++/* Feature flags */
++/* Duplicate extensions at each immediate use */
++#define EXTELIM_DUPLICATE_EXTS_AT_USES 0
++/* Dump DF information also in dump */
++#define EXTELIM_DF_DUMP 0
++
++
++/* Typedefs */
++typedef unsigned int insn_flag_t; /* Insn flags type */
++typedef int extelim_uid_t; /* UID type */
++DEF_VEC_I (insn_flag_t); /* Define vector type and allocation type */
++DEF_VEC_ALLOC_I (insn_flag_t, heap);
++
++typedef struct GTY (()) ext_record
++{
++ rtx ext; /* The extension insn */
++ VEC (rtx, heap) * ext_uses; /* List of use records for this extension. For some
++ some extensions, we will duplicate the extension
++ at these use points. */
++ VEC (rtx, heap) * ext_updates;/* List of rtx that need to be updated if the extension
++ is to be eliminated. For example, SUBREG_PROMOTED flags
++ on SUBREG uses defined by this extension should
++ be reset since the extension is eliminated. The PROMOTED
++ flag is no longer valid. */
++} *ext_record_t;
++
++typedef struct regspec_cb_data
++{
++ unsigned int regno;
++ rtx exp;
++} regspec_cb_data_t;
++
++/* Static variables */
++DEF_VEC_P (ext_record_t);
++DEF_VEC_ALLOC_P (ext_record_t, heap);
++VEC (ext_record_t, heap) * extensions; /* Vector holding all extension records */
++VEC (insn_flag_t, heap) * insn_flags; /* Vector holding flags for all insns */
++VEC (rtx, heap) * returns; /* Vector holding return insns for this function */
++
++ static extelim_uid_t max_uid; /* Max UID insn value for insn_flags allocation */
++ static ext_record_t current_ext_record; /* Current extension record being processed */
++
++/* Statistics */
++ static int num_cand; /* Number of extensions detected */
++ static int num_cand_ignored; /* Number of extensions ignored */
++ static int num_cand_transformed; /* Number of extensions transformed to copy */
++
++/* Basic information about the extension being processed */
++ enum machine_mode ext_to_mode; /* Mode extended to */
++ enum machine_mode ext_from_mode; /* Mode extended from */
++ enum rtx_code ext_code; /* Sign or zero extend */
++
++/* Insn use analysis possible results */
++ enum insn_use_results
++ {
++ EXTELIM_ANALYSIS_RESULT_LOWBITS_NOT_AFFECTED,
++ EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED,
++ EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION
++ };
++
++/* Insn def analysis possible results */
++ enum insn_def_results
++ {
++ EXTELIM_ANALYSIS_RESULT_DEF_EXTENDED,
++ EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION,
++ EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION
++ };
++
++/* Insn flags for this pass */
++#define EXTELIM_NONE 0
++#define EXTELIM_SEEN (1<<0) /* Mark insn as visited during DF traversal */
++#define EXTELIM_REPLACE_COPY (1<<1) /* Mark ext insn as replace with copy */
++#define EXTELIM_INSERTED (1<<2) /* Mark ext insn as algorithmically inserted */
++#define EXTELIM_INSERTED_FOR (1<<3) /* Mark use insn for which ext has been inserted */
++
++
++/* Query the insn flag */
++
++ static bool insn_flag_p (insn_flag_t set_p, extelim_uid_t uid)
++{
++ insn_flag_t flags;
++
++ if (((flags = VEC_index (insn_flag_t, insn_flags, uid)) & set_p) == set_p)
++ return true;
++
++ return false;
++}
++
++/* Set the insn flags */
++
++static void
++insn_flag_set (insn_flag_t flags, extelim_uid_t uid)
++{
++ insn_flag_t set;
++ set = VEC_index (insn_flag_t, insn_flags, uid);
++ set |= flags;
++ VEC_replace (insn_flag_t, insn_flags, uid, set);
++}
++
++/* Clear insn flags */
++
++static void
++insn_flag_clear (insn_flag_t flags, extelim_uid_t uid)
++{
++ insn_flag_t clear;
++ clear = VEC_index (insn_flag_t, insn_flags, uid);
++ clear &= ~flags;
++ VEC_replace (insn_flag_t, insn_flags, uid, clear);
++}
++
++/* Set static variable max_uid to the largest
++ insn uid found in the module plus 1. This will be the
++ size of the vector for insn flags. */
++
++static void
++set_max_uid (void)
++{
++ basic_block bb;
++ rtx insn;
++ extelim_uid_t lmax_uid = 0;
++
++ FOR_EACH_BB (bb) FOR_BB_INSNS (bb, insn)
++ {
++ if (INSN_P (insn))
++ {
++ if (INSN_UID (insn) > lmax_uid)
++ lmax_uid = INSN_UID (insn);
++ }
++ }
++ max_uid = lmax_uid + 1;
++}
++
++/* Re-initializes the requested insn flags to their reset state */
++
++static void
++reinit_insn_flags (insn_flag_t flags_to_be_reset)
++{
++ extelim_uid_t i;
++
++ /* Account for new insns */
++ set_max_uid ();
++
++ for (i = 0; i < max_uid; i++)
++ {
++ insn_flag_clear (flags_to_be_reset, i);
++ }
++}
++
++/* Init the vector for insn flags. One
++ vector element per insn is created.
++ The flags are init'd to EXTELIM_NONE. */
++
++static void
++init_flags_vector (void)
++{
++ extelim_uid_t i;
++ /* Get the maximum uid value. We'll use this
++ information to set up a vector of max_uid
++ length. Each element of the vector will hold
++ the pass-specific flags for each insn. */
++ max_uid = 0;
++ set_max_uid ();
++
++ /* Allocate the vector of insn flags */
++ insn_flags = VEC_alloc (insn_flag_t, heap, max_uid);
++
++ /* Initialize the insn flags vector */
++ for (i = 0; i < max_uid; i++)
++ {
++ VEC_quick_insert (insn_flag_t, insn_flags, i, EXTELIM_NONE);
++ }
++}
++
++/* Initialize this pass */
++
++static void
++init_pass (void)
++{
++ /* Init insn flags vector */
++ init_flags_vector ();
++
++ /* This pass requires def-use chain information */
++ df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
++ df_analyze ();
++}
++
++static void
++free_extensions (void)
++{
++ ext_record_t ext_record;
++ unsigned i;
++
++ FOR_EACH_VEC_ELT (ext_record_t, extensions, i, ext_record)
++ {
++ if (!VEC_empty (rtx, ext_record->ext_uses))
++ VEC_free (rtx, heap, ext_record->ext_uses);
++
++ if (!VEC_empty (rtx, ext_record->ext_updates))
++ VEC_free (rtx, heap, ext_record->ext_updates);
++ }
++ VEC_free (ext_record_t, heap, extensions);
++}
++
++/* Clean up this pass */
++
++static void
++finish_pass (void)
++{
++ free_extensions ();
++ VEC_free (insn_flag_t, heap, insn_flags);
++ VEC_free (rtx, heap, returns);
++}
++
++static void
++update_uid_vectors (extelim_uid_t uid)
++{
++ VEC_safe_grow_cleared (insn_flag_t, heap, insn_flags, uid + 1);
++}
++
++/* Emit a insn before a given insn, update vector lengths
++ of those vectors that are indexed by uid. Return uid
++ of the inserted insn. */
++
++static extelim_uid_t
++extelim_emit_before (rtx new_insn, rtx before_insn)
++{
++ rtx seq;
++ extelim_uid_t new_uid;
++
++ start_sequence ();
++ emit_insn (new_insn);
++ seq = get_insns ();
++ end_sequence ();
++ new_insn = emit_insn_before (seq, before_insn);
++
++ /* Expand the flags vector to hold the new insn and set the
++ inserted flag on the insn. */
++ new_uid = INSN_UID (new_insn);
++ update_uid_vectors (new_uid);
++ return new_uid;
++}
++
++/* Utility function to find the REG exp
++ given an rtx */
++
++static rtx
++register_exp (rtx exp)
++{
++ if (REG_P (exp))
++ {
++ return exp;
++ }
++ else if (GET_CODE (exp) == SUBREG)
++ {
++ return SUBREG_REG (exp);
++ }
++ else
++ return NULL;
++}
++
++/* Check whether this is a sign extension. */
++
++static bool
++extension_p (rtx insn, rtx * dest, rtx * inner, int *preserved_size)
++{
++ rtx src, op0;
++
++ /* Detect set of reg. */
++ if (GET_CODE (PATTERN (insn)) != SET)
++ return false;
++
++ src = SET_SRC (PATTERN (insn));
++ *dest = SET_DEST (PATTERN (insn));
++
++ if (!REG_P (*dest))
++ return false;
++
++ if (GET_CODE (src) == SIGN_EXTEND || GET_CODE (src) == ZERO_EXTEND)
++ {
++ op0 = XEXP (src, 0);
++
++ /* Determine amount of least significant bits preserved by operation. */
++ if (GET_CODE (src) == AND)
++ *preserved_size = ctz_hwi (~UINTVAL (XEXP (src, 1)));
++ else
++ *preserved_size = GET_MODE_BITSIZE (GET_MODE (op0));
++
++ if (GET_CODE (op0) == SUBREG)
++ {
++ if (subreg_lsb (op0) != 0)
++ return false;
++
++ *inner = SUBREG_REG (op0);
++ return true;
++ }
++ else if (REG_P (op0))
++ {
++ *inner = op0;
++ return true;
++ }
++ }
++
++ return false;
++}
++
++/* Return true if this is the last use of a
++ register, false otherwise. */
++
++static bool
++reg_is_dead_p (rtx insn, rtx reg_expr)
++{
++ rtx link;
++ gcc_assert (REG_P (reg_expr));
++
++ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
++ {
++ if (REG_NOTE_KIND (link) == REG_DEAD && REG_P (XEXP (link, 0)))
++ {
++ if (REGNO (XEXP (link, 0)) == REGNO (reg_expr))
++ return true;
++ }
++ }
++ return false;
++}
++
++/* Return true if we don't want to place this
++ extension in the candidate extensions list because of the
++ previous insn. Return false otherwise. */
++
++static bool
++ignore_extension_prev_p (rtx ext_insn, rtx prev_insn)
++{
++ rtx prev_dest, prev_src, prev = PATTERN (prev_insn);
++ rtx ext_src, ext = PATTERN (ext_insn);
++
++ /* It's OK to allow extension with no accompanying prev real insn */
++ if (!NONDEBUG_INSN_P (prev_insn) || NOTE_P (prev_insn))
++ return false;
++
++ if (GET_CODE (prev) != SET)
++ return false;
++
++ if (GET_CODE (ext) != SET)
++ return false;
++
++ prev_dest = SET_DEST (prev);
++ prev_src = SET_SRC (prev);
++
++ /* Source register of sign extension */
++ ext_src = XEXP (SET_SRC (ext), 0);
++
++ /* Check previous insns */
++
++ /* Previous insn is a load whose dest is the
++ extension's source and the dest reg is
++ dead */
++ if (MEM_P (prev_src) && (prev_dest = register_exp (prev_dest)))
++ {
++ if ((ext_src = register_exp (ext_src)))
++ {
++ if ((REGNO (prev_dest) == REGNO (ext_src))
++ && reg_is_dead_p (ext_insn, ext_src))
++ return true;
++ }
++ }
++ return false;
++}
++
++/* Return true if we don't want to place this
++ extension in the candidate extensions list because of the
++ next insn. Return false otherwise. */
++
++static bool
++ignore_extension_next_p (rtx ext_insn, rtx next_insn)
++{
++ rtx next = PATTERN (next_insn);
++ rtx ext_src, ext = PATTERN (ext_insn);
++
++ if (GET_CODE (ext) != SET)
++ return false;
++
++ /* Check next insns */
++ if (!NONDEBUG_INSN_P (next_insn) || NOTE_P (next_insn))
++ return false;
++
++ if (GET_CODE (next) != SET)
++ return false;
++
++ /* zero-extend followed by left shift by 1 -- this sequence will be
++ detected by the insn selection. */
++ if (GET_CODE (SET_SRC (ext)) == ZERO_EXTEND)
++ {
++ if (GET_CODE (SET_SRC (next)) == ASHIFT
++ && CONST_INT_P (XEXP (SET_SRC (next), 1))
++ && UINTVAL (XEXP (SET_SRC (next), 1)) == 0x1)
++ return true;
++ }
++
++ return false;
++}
++
++/* Find extensions and store them in the extensions vector. */
++
++static bool
++find_extensions (void)
++{
++ basic_block bb;
++ rtx insn, dest, inner;
++ int preserved_size;
++ ext_record_t extrec;
++
++ /* For all insns, call note_use for each use in insn. */
++ FOR_EACH_BB (bb)
++ {
++ FOR_BB_INSNS (bb, insn)
++ {
++ if (!NONDEBUG_INSN_P (insn))
++ continue;
++
++ if (!extension_p (insn, &dest, &inner, &preserved_size))
++ {
++ continue;
++ }
++
++ /* We do not consider extensions that follow a load for
++ this target, as the code selector optimizes the sequence
++ to a load with sign extend or load with zero extend. */
++ if (PREV_INSN (insn)
++ && ignore_extension_prev_p (insn, PREV_INSN (insn)))
++ {
++ if (dump_file)
++ fprintf (dump_file, "extension at uid=%d ignored\n",
++ INSN_UID (insn));
++ num_cand_ignored++;
++ continue;
++ }
++ /* We don't consider certain sequences that are picked up by
++ insn selection. */
++ if (NEXT_INSN (insn)
++ && ignore_extension_next_p (insn, NEXT_INSN (insn)))
++ {
++ if (dump_file)
++ fprintf (dump_file, "extension at uid=%d ignored\n",
++ INSN_UID (insn));
++ num_cand_ignored++;
++ continue;
++ }
++
++ /* Only looking at sign extensions to DImode, SImode, or HImode */
++ if (GET_MODE_BITSIZE (SImode) != preserved_size
++ && GET_MODE_BITSIZE (HImode) != preserved_size
++ && GET_MODE_BITSIZE (QImode) != preserved_size)
++ continue;
++
++ extrec = (ext_record_t) xmalloc (sizeof (struct ext_record));
++ extrec->ext = insn;
++ extrec->ext_uses = NULL;
++ extrec->ext_updates = NULL;
++ VEC_safe_push (ext_record_t, heap, extensions, extrec);
++ num_cand++;
++ }
++ }
++
++ if (dump_file)
++ {
++ if (!VEC_empty (ext_record_t, extensions))
++ fprintf (dump_file, "\n");
++ else
++ fprintf (dump_file, "no extensions found.\n");
++ }
++
++ return !VEC_empty (ext_record_t, extensions);
++}
++
++/* Return true if the rtx mode is a supported mode for
++ this optimization, false otherwise. */
++
++static bool
++mode_supported_p (rtx exp)
++{
++ if (GET_MODE (exp) != QImode
++ && GET_MODE (exp) != HImode
++ && GET_MODE (exp) != SImode
++ && GET_MODE (exp) != DImode
++ && GET_MODE (exp) != CCmode
++ && GET_MODE (exp) != CCUNSmode)
++ return false;
++
++ return true;
++}
++
++/* Return true if the rtx is a function return expr, false otherwise */
++
++static bool
++return_val_p (rtx dest)
++{
++ if ((REG_P (dest) || GET_CODE (dest) == PARALLEL) &&
++ REG_FUNCTION_VALUE_P (dest))
++ {
++ return true;
++ }
++ return false;
++}
++
++
++/* A 'for_each_rtx' callback returning 1 if the rtx is a
++ REG or SUBREG rtx. The first matching rtx found stops the
++ rtx traversal. */
++
++static int
++reg_or_subreg_rtx (rtx * x, void *data)
++{
++ regspec_cb_data_t *ldata = (regspec_cb_data_t *) data;
++
++ if (REG_P (*x))
++ {
++ ldata->exp = *x;
++ return 1;
++ }
++
++ if (GET_CODE (*x) == SUBREG)
++ {
++ ldata->exp = SUBREG_REG (*x);
++ return 1;
++ }
++
++ return 0;
++}
++
++/* A 'for_each_rtx' callback returning 1 if the rtx is a
++ REG or SUBREG rtx whose register number is that passed
++ in the data parameter. Data parameter's rtx value is
++ set to the matching rtx if found. */
++
++static int
++reg_or_subreg_rtx_regno (rtx * x, void *data)
++{
++ regspec_cb_data_t *ldata = (regspec_cb_data_t *) data;
++
++ if (REG_P (*x) && (REGNO (*x) == ldata->regno))
++ {
++ ldata->exp = *x;
++ return 1;
++ }
++ if (GET_CODE (*x) == SUBREG && (REGNO (SUBREG_REG (*x)) == ldata->regno))
++ {
++ ldata->exp = SUBREG_REG (*x);
++ return 1;
++ }
++ return 0;
++}
++
++/* Callback that counts the number of register operands
++ in an expression. Return 0 to allow all rtxs to be
++ traversed. */
++
++static int
++count_reg_operands (rtx * x, void *data)
++{
++ regspec_cb_data_t *ldata = (regspec_cb_data_t *) data;
++
++ if (register_exp (*x) != NULL)
++ {
++ ldata->regno++;
++ }
++ return 0;
++}
++
++/* Count the number of register operands in an expression.
++ We use the regspec_cb_data_t regno field as the number
++ of register operands we found in an expression. */
++
++static int
++num_reg_operands (rtx x)
++{
++ int rv;
++ regspec_cb_data_t data;
++ data.regno = 0;
++ data.exp = NULL_RTX;
++
++ if ((rv = for_each_rtx (&x, count_reg_operands, (void *) &data)) == 0)
++ return (data.regno); /* contains the count */
++ else
++ return 0;
++}
++
++/* Find the SUBREG or REG rtx corresponding to regno in the given rtx.
++ Return NULL_RTX if the regno rtx is not found. */
++
++static rtx
++find_regspec_regno (unsigned int regno, rtx x)
++{
++ int rv;
++ regspec_cb_data_t data;
++ data.regno = regno;
++ data.exp = NULL_RTX;
++
++ if ((rv = for_each_rtx (&x, reg_or_subreg_rtx_regno, (void *) &data)) != 0)
++ return (data.exp);
++ else
++ return NULL_RTX;
++}
++
++/* Find a REG or SUBREG rtx, starting at expr x.
++ Return NULL_RTX if no REG or SUBREG rtx is found.
++ If found, the rtx returned is a REG (not SUBREG) */
++
++static rtx
++find_regspec (rtx x)
++{
++ int rv;
++ regspec_cb_data_t data;
++ data.regno = -1; /* not used */
++ data.exp = NULL_RTX;
++
++ if ((rv = for_each_rtx (&x, reg_or_subreg_rtx, (void *) &data)) != 0)
++ return (data.exp);
++ else
++ return NULL_RTX;
++}
++
++/* Return true if the expression defines single register, regno. */
++
++static bool
++expr_defines_regno_p (rtx insn, unsigned int regno)
++{
++ rtx reg;
++ if (GET_CODE (insn) == SET)
++ {
++ reg = SET_DEST (insn);
++ if (find_regspec_regno (regno, reg) != NULL_RTX)
++ return true;
++ }
++ return false;
++}
++
++/* Return true if the insn defines a single register, regno.
++ Return false otherwise */
++
++static bool
++defines_regno_p (rtx insn_insn, unsigned int regno, int indent)
++{
++ extelim_uid_t uid = INSN_UID (insn_insn);
++ df_ref *p_def;
++
++ /* Get the operands defined */
++ p_def = DF_INSN_UID_DEFS (uid);
++
++ if (!p_def)
++ return false;
++
++ if (*(p_def + 1) != NULL)
++ {
++ if (dump_file)
++ fprintf (dump_file, "%*suid=%d defines multiple registers\n",
++ indent, " ", uid);
++ return false;
++ }
++
++ if (DF_REF_REGNO (*p_def) != regno)
++ {
++ if (dump_file)
++ fprintf (dump_file, "%*suid=%d defines does not define %d\n",
++ indent, " ", uid, regno);
++ return false;
++ }
++
++ return true;
++}
++
++/* The operand is already extended and the extension is compatible with
++ the originating extension with respect to type and size.
++ E.g. zero_extend:HI meets and AND r,#0xffff. Another example
++ is LSHIFT:SI left or right and zero_extend:SI, because the
++ instruction selected is rlwinm and clears the upper 32 bits.
++ Other examples in the code. Return true if a compatible extension
++ is found, false otherwise. */
++
++static bool
++operand_is_extended (rtx dest, rtx srcexp, int indent)
++{
++ /* Output of a CALL is already extended.
++ To ensure that the return value is not modified by the extend,
++ the extend from mode size must be at least the size of the CALL output.
++ Example - this is redundant since output of CALL is extended.
++ X:SI = CALL ...
++ Y:DI = sign_extend:DI (X:SI) */
++ if (GET_CODE (srcexp) == CALL
++ && (GET_MODE_BITSIZE (ext_from_mode)) >=
++ GET_MODE_BITSIZE (GET_MODE (dest)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...is extended already (CALL insn output)\n", indent,
++ " ");
++ return true;
++ }
++
++ /* Output is load immediate or load constant */
++ if (CONST_INT_P (srcexp))
++ {
++ bool is_extended;
++ if (ext_from_mode == QImode && (UINTVAL (srcexp) <= 0xff))
++ is_extended = true;
++ else if (ext_from_mode == HImode && (UINTVAL (srcexp) <= 0xffff))
++ is_extended = true;
++ else if (ext_from_mode == SImode && (UINTVAL (srcexp) <= 0xffffffff))
++ is_extended = true;
++ else
++ is_extended = false;
++
++ if (is_extended)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s... is extended already (CONST_INT load)\n", indent,
++ " ");
++ return true;
++ }
++ }
++
++ /* Sign extension of the same type as the originating extension.
++ Here the candidate defines the register used in the originating extension.
++ The originating extension will be replaced by a copy if it is found to be
++ redundant with respect to the candidate extension.
++ The candidate (this extension dest,src) must write the at least the same bits as the
++ originating extension in order to be redundant. So, we follow these rules:
++
++ cand_to_mode == machine mode of the destination for this candidate extension
++ cand_from_mode == machine mode of the source for this candidate extension
++ ext_to_mode == machine mode of the originating extension output
++ ext_from_mode == machine mode of the originating extension input
++
++ SIZE(cand_to_mode) >= SIZE(extend_to_mode) && SIZE(cand_from_mode) <= SIZE(extend_from_mode)
++
++ Example 1:
++ Candidate (HI->SI extension)
++ DI SI HI QI 0
++ | |<---| | |
++
++ Originating (SI->DI)
++ DI SI HI QI 0
++ |<-------| | | |
++
++ Not redundant, candidate does not cover the original bits:
++ SIZE(cand_to_mode)[SI] !>= SIZE(extend_to_mode)[DI]
++
++ Example 2:
++ Candidate (QI->DI extension)
++ DI SI HI QI 0
++ |<-------|----|--| |
++
++ Originating (HI->SI)
++ DI SI HI QI 0
++ | |<---| | |
++
++ Redundant, candidate covers the original bits:
++ SIZE(cand_to_mode) [DI] >= SIZE(extend_to_mode) [SI]
++ AND
++ SIZE(cand_from_mode) [QI] <= SIZE(extend_from_mode) [HI]
++ */
++ if (GET_CODE (srcexp) == ext_code)
++ {
++ enum machine_mode cand_from_mode = GET_MODE (XEXP (srcexp, 0));
++ enum machine_mode cand_to_mode = GET_MODE (dest);
++ if ((GET_MODE_BITSIZE (cand_to_mode) >= GET_MODE_BITSIZE (ext_to_mode))
++ && (GET_MODE_BITSIZE (cand_from_mode) <=
++ GET_MODE_BITSIZE (ext_from_mode)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...is already extended (redundant extension)\n",
++ indent, " ");
++ return true;
++ }
++ }
++
++ /* Encountered an insn with the same effect as extension, e.g.
++ AND (regspec) (const_int). E.g. AND (reg:SI) (0x7fff) is equivalent
++ to ZERO_EXTEND:DI (reg:HI) or SIGN_EXTEND:DI (reg:HI). The code selection
++ for AND zero extends the entire register, so we don't have to
++ check that srcexp extends to at least ext_to_mode size. */
++ if ((GET_CODE (srcexp) == AND) && CONST_INT_P (XEXP (srcexp, 1)))
++ {
++ if (ext_from_mode == QImode && (UINTVAL (XEXP (srcexp, 1)) <= 0x7f))
++ return true;
++ else if (ext_from_mode == HImode
++ && (UINTVAL (XEXP (srcexp, 1)) <= 0x7fff))
++ return true;
++ else if (ext_from_mode == SImode
++ && (UINTVAL (XEXP (srcexp, 1)) <= 0x7fffffff))
++ return true;
++ }
++
++ return false;
++}
++
++/* Determine if the operation allows us to continue the propagation.
++ We kill the propagation for all operations except copy. This
++ ensures that the extended operand that we may find eventually
++ is not modified by insns in the def-use chain. It's harsh,
++ but it's safest eliminate all but the most benign (copy) operations
++ in the propagation chain. */
++
++static bool
++continue_def_propagation (rtx dest, rtx srcexp, rtx src_operand, int indent)
++{
++ /* Only continue if its a copy -- that is, the srcexp is a register expression */
++ if ( register_exp (srcexp) )
++ return true;
++
++ return false;
++}
++
++/* Helper for insn_def_analysis_result.
++ The register operand, src is set here. Recall we
++ can only handle one register operand in the src expression.
++ We one of 3 states:
++ 1) Determine the operand is extended, ...DEF_EXTENDED returned.
++ 2) Determine the propagation can continue, ...DEF_CONTINUE_RECURSION returned.
++ 3) Otherwise, ...DEF_STOP_RECURSION is returned. */
++static enum insn_def_results
++insn_def_analysis_result_1 (rtx insn, bool treat_as_copy,
++ unsigned int regno_def ATTRIBUTE_UNUSED,
++ rtx * src, int indent)
++{
++ rtx dest, srcexp;
++ int num_operands;
++
++ /* Insn has to be an expression we can analyze */
++ if (GET_CODE (insn) != SET)
++ {
++ if (dump_file)
++ fprintf (dump_file, "%*s...is not a SET expression\n", indent, " ");
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++ dest = SET_DEST (insn);
++ srcexp = SET_SRC (insn);
++
++ /* Dest must be a reg, not expression */
++ if (!REG_P (dest))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...dest is not a simple register\n", indent, " ");
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++
++ /* First check whether the operand is extended already. If so,
++ we can leave immediately successfully. */
++ if (operand_is_extended (dest, srcexp, indent) && !treat_as_copy)
++ return (EXTELIM_ANALYSIS_RESULT_DEF_EXTENDED);
++
++
++ /* Failing to determine that the operand is already extended,
++ we have to validate that we have register operands to propagate. */
++ num_operands = num_reg_operands (srcexp);
++
++ /* At least one register operand required for propagation. */
++ if (num_operands == 0)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...no register operands in RHS\n", indent, " ");
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++
++ /* Only one register operand is allowed in the RHS since we can't
++ can't propagate more than one register. */
++ if (num_operands > 1)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...found multiple register operands in RHS\n", indent,
++ " ");
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++
++ /* Find the used operand in the src expression */
++ *src = find_regspec (srcexp);
++ if (*src == NULL_RTX || !mode_supported_p (*src))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...src operand reg=%d cannot be found or is unsupported mode\n",
++ indent, " ", regno_def);
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++
++ /* This is an extension, but it is previously marked to be transformed to a copy.
++ We just treat it as a copy even though it hasn't been transformed yet. So
++ continue the propagation. */
++ if (treat_as_copy)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s is treated as a copy (marked for replace)\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (srcexp)));
++ return (EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION);
++ }
++
++ /* Validate that it's ok to continue propagation with this operand. */
++ if (continue_def_propagation (dest, srcexp, *src, indent))
++ return (EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION);
++
++ /* Else we default to halting the search for a redundant extension */
++ return (EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION);
++}
++
++/* Determine if the insn extends it's destination register in
++ a manner such that the original extension is redundant. */
++
++static enum insn_def_results
++insn_def_analysis_result (rtx insn_insn, unsigned int regno_def, rtx * src,
++ int indent)
++{
++ bool treat_as_copy = false;
++
++ /* Insn must only define one output */
++ if (!defines_regno_p (insn_insn, regno_def, indent))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...defines more than 1 output\n", indent, " ");
++ return EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++ }
++
++ /* We want to treat this extension as a copy and continue propagation.
++ Otherwise, it would be detected again as redundant. */
++ if (insn_flag_p (EXTELIM_REPLACE_COPY, INSN_UID (insn_insn)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*suse at uid=%d is marked to transform to copy\n", indent,
++ " ", INSN_UID (insn_insn));
++ treat_as_copy = true;
++ }
++
++ /* Do the analysis */
++ return (insn_def_analysis_result_1
++ (PATTERN (insn_insn), treat_as_copy, regno_def, src, indent));
++}
++
++/* Analyze each of the expressions in a PARALLEL expression. As each of
++ the expressions may yield a different state, select the most conservative
++ state to return. */
++
++static enum insn_def_results
++insn_def_analysis_2 (rtx insn_def, unsigned int regno_def, rtx * src,
++ int indent)
++{
++ int i;
++ rtx insn = PATTERN (insn_def);
++ enum insn_def_results action;
++ enum insn_def_results return_action =
++ EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION;
++
++ gcc_assert (GET_CODE (insn) == PARALLEL);
++
++ for (i = XVECLEN (insn, 0) - 1; i >= 0; i--)
++ {
++ rtx body = XVECEXP (insn, 0, i);
++ /* Only act on the expressions that define regno_def */
++ if (!expr_defines_regno_p (body, regno_def))
++ continue;
++ /* Determine the next action */
++ action = insn_def_analysis_result_1 (body, false /* treat_as_copy */ ,
++ regno_def, src, indent);
++ /* The result of this expression stops the recursion, i.e. no
++ longer reasonable to continue looking at further recursion. */
++ if (action == EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION)
++ return action;
++ /* Only return EXTENDED if there are no other different actions
++ in the series. Otherwise, CONTINUE_RECURSION is returned. */
++ if (action == EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION)
++ return_action = action;
++ else if (return_action ==
++ EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION)
++ return_action = EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION;
++ else
++ return_action = action;
++ }
++ return (return_action);
++}
++
++/* Helper 1 for insn_def_analysis */
++
++static enum insn_def_results
++insn_def_analysis_1 (rtx insn_def, unsigned int regno_def, rtx * src,
++ int indent)
++{
++ rtx def = PATTERN (insn_def);
++ enum insn_def_results action;
++
++ switch (GET_CODE (def))
++ {
++ case PARALLEL:
++ action = insn_def_analysis_2 (insn_def, regno_def, src, indent);
++ break;
++ default:
++ action = insn_def_analysis_result (insn_def, regno_def, src, indent);
++ break;
++ }
++ return action;
++}
++
++/* We look at the definition of a register that is either the
++ sign or zero extend source register or a definition that that
++ has been propagated to here via analyze_ext_def. The objective
++ is to determine, by looking at the operation and operands, whether
++ the register is sign/zero extended by virtue of the operation and/or
++ operands. If so, the original extension is redundant.
++ The function returns one of 3 possible states after analyzing the
++ insn:
++ 1. EXTELIM_ANALYSIS_RESULT_DEF_EXTENDED - we determined that the
++ insn does indeed extend the original source extension register.
++ analyze_ext_def returns FALSE, therefore, ending the recursion
++ and propagation.
++ 2. EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION - we determined that
++ the insn does not meet the criteria to continue the recursive search.
++ Some conditions causing this may be multiple operands defining this
++ register (we only propagate on a single input operand) or the insn
++ defines more than one output or the operation does not allow
++ a previous extension to propagate, e.g. an arithmetic shift on
++ a SI value clears the upper bits using rlwinm. MUL, DIV, MOD
++ stop recursion because the result is longer than the input size,
++ thus impacting the possible previous extension.
++ 3. EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION - we found an
++ operation with one register operand and the operation will not
++ affect a previous extension if one exists. ADD, SUB are examples.
++ We continue looking up the chain at the definition of the operand
++ for an extended result.
++ If we run into a previous extension marked for replacement during
++ recursion, we treat it as a copy (CONTINUE_RECURSION since the
++ extension is preserved by the copy). */
++
++static enum insn_def_results
++insn_def_analysis (rtx insn_def, unsigned int regno_def, rtx * src,
++ int indent)
++{
++ return (insn_def_analysis_1 (insn_def, regno_def, src, indent));
++}
++
++/* Analyze the insn defining the source of the sign extension.
++ If it can be determined that the definition is already
++ sign extended, return false. Otherwise, return true if
++ extension is needed. */
++
++static bool
++analyze_ext_def (rtx insn_def, unsigned int regno_def, int indent)
++{
++ extelim_uid_t uid;
++ rtx def = PATTERN (insn_def);
++ rtx src;
++ df_ref df_def, *p_use;
++ bool ext_needed, indent_once;
++ struct df_link *link;
++ enum insn_def_results analysis_result;
++
++ gcc_assert (def != NULL);
++
++ uid = INSN_UID (insn_def);
++
++ /* If we seen the originating extension again, return false (ext not needed) */
++ if (current_ext_record->ext == insn_def)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sdef at uid=%d is original extension\n", indent, " ", uid);
++ return false;
++ }
++
++ /* The recursion has to definitively end with an operand being
++ extended (and compatible with the originating extension). If
++ we see the insn again, this could return a faulty positive (false),
++ so we return true here instead of false. See pr43017 (-funroll-loops)
++ as an example. */
++ if (insn_flag_p (EXTELIM_SEEN, uid))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sdef at uid=%d is visited already\n", indent, " ", uid);
++ return true;
++ }
++
++ /* Mark this insn as seen */
++ insn_flag_set (EXTELIM_SEEN, uid);
++
++ analysis_result = insn_def_analysis (insn_def, regno_def, &src, indent);
++ switch (analysis_result)
++ {
++ /* We know conclusively that the register defined in this expression
++ is already extended. */
++ case EXTELIM_ANALYSIS_RESULT_DEF_EXTENDED:
++ if (dump_file)
++ fprintf (dump_file, "%*sdef at uid=%d is extended\n", indent, " ",
++ uid);
++ return false;
++ break;
++ /* We know conclusively that we cannot continue the recursion. Perhaps
++ the expression defines multiple registers, etc. */
++ case EXTELIM_ANALYSIS_RESULT_DEF_STOP_RECURSION:
++ if (dump_file)
++ fprintf (dump_file, "%*sdef at uid=%d cannot be propagated\n", indent,
++ " ", uid);
++ return true;
++ break;
++ /* Continue to look at the operands of this expression. They may be extended
++ already. */
++ case EXTELIM_ANALYSIS_RESULT_DEF_CONTINUE_RECURSION:
++ break;
++ default:
++ gcc_unreachable ();
++ }
++
++ /* This is the operand for which we want to find definitions. There should
++ only be one operand as we have previously checked for operations with only
++ one register operand as the src previously. */
++ p_use = DF_INSN_UID_USES (uid);
++ gcc_assert (p_use != NULL);
++
++ /* Make sure that this use is the one returned in src. Otherwise we simply
++ stop the propagation. Note the DF_INSN_UID_USES works at the insn
++ level, so a PARALLEL pattern may return many uses, hence the need
++ to validate the correct use here. */
++ if ((*p_use == NULL) || (DF_REF_REGNO (*p_use) != REGNO (src)))
++ return true;
++
++ ext_needed = true;
++ indent_once = true;
++ for (link = DF_REF_CHAIN (*p_use); link; link = link->next)
++ {
++ rtx insn_def;
++ df_def = link->ref;
++ if (!df_def)
++ continue;
++ /* Link must be to a definition of the use */
++ if (!DF_REF_REG_DEF_P (df_def))
++ continue;
++ /* Ignore ARTIFICIAL defs */
++ if (DF_REF_IS_ARTIFICIAL (df_def))
++ continue;
++ insn_def = DF_REF_INSN (df_def);
++ /* Don't consider debug_insns */
++ if (!NONDEBUG_INSN_P (insn_def))
++ continue;
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sdef of reg=%d at uid=%d\n", indent, " ",
++ DF_REF_REGNO (df_def), INSN_UID (insn_def));
++ /* Set indent for dump formatting */
++ if (indent_once)
++ {
++ ++indent;
++ indent_once = false;
++ }
++ ext_needed = analyze_ext_def (insn_def, DF_REF_REGNO (df_def), indent);
++ if (ext_needed)
++ break;
++ }
++
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sext %s needed\n", indent, " ", ext_needed ? "" : "not");
++
++ return ext_needed;
++}
++
++/* Determine whether the expression needs to be saved for this extension.
++ The expression will be updated in some way if the extension is ultimately
++ eliminated. */
++
++static bool
++exp_needs_update_p (rtx exp)
++{
++ if (GET_CODE (exp) == SUBREG
++ && (SUBREG_PROMOTED_VAR_P (exp)))
++ {
++ return true;
++ }
++ return false;
++}
++
++/* Some expressions may need to be updated if the originating extension
++ is eliminated. For example, SUBREG_PROMOTED flags on uses are no longer
++ valid if the extension is eliminated. Save the expression here. */
++
++static void
++save_ext_update (ext_record_t extrec, rtx exp)
++{
++ /* Save this expression to be updated if the extension is eliminated. */
++ VEC_safe_push (rtx, heap, extrec->ext_updates, exp);
++}
++
++/* Check a compare operation to determine whether the operands
++ of the compare use the upper bits of the extension. Return
++ true if the upper bits are not relevant in the compare, false
++ otherwise. */
++
++static bool
++check_compare (rtx dest, rtx src)
++{
++ /* Detect
++ (set (reg:CC r0) (compare:CC (REGSPEC) (REGSPEC)))
++ or
++ (set (reg:CC r0) (compare:CC (REGSPEC) (CONST)))
++ where REGSPEC is (reg:mm r) or (subreg:mm (reg:MM r) n)
++ CONST is a constant integer.
++ The mode size of compare ops must be less than the
++ mode of the original extension for the upper bits to
++ be irrelevant.
++ An exception is made for mode sizes less than a word size.
++ For our targets, there is no 'cmph' insn, so we bail out
++ if we see a comparison of sizes less than a word (SI). */
++ if (REG_P (dest)
++ && (GET_MODE (dest) == CCmode || GET_MODE (dest) == CCUNSmode)
++ && GET_CODE (src) == COMPARE
++ && (GET_MODE (src) == CCmode || GET_MODE (src) == CCUNSmode))
++ {
++ rtx compare_op0 = XEXP (src, 0);
++ rtx compare_op1 = XEXP (src, 1);
++
++ /* Check the first operand, op0, size. */
++ if ((REG_P (compare_op0) || GET_CODE (compare_op0) == SUBREG)
++ && (GET_MODE_BITSIZE (GET_MODE (compare_op0)) <=
++ GET_MODE_BITSIZE (ext_from_mode)))
++ {
++ /* Half word compares and smaller are performed as word compares, so upper bits are used. */
++ if (GET_MODE_BITSIZE (GET_MODE (compare_op0)) < SImode)
++ return false;
++
++ /* Now check the other operand, op1. */
++ if ((REG_P (compare_op1) || GET_CODE (compare_op1) == SUBREG)
++ && (GET_MODE_BITSIZE (GET_MODE (compare_op1)) <=
++ GET_MODE_BITSIZE (ext_from_mode)))
++ return true;
++
++ /* Compare to constant, we know op0 already meets size constraints. */
++ if (CONST_INT_P (compare_op1))
++ return true;
++ }
++ }
++ return false;
++}
++
++/* Determine condition a, whether the upper bits are relevant to the operation.
++ Return false if we prove the upper bits are not relevant in the operation,
++ true otherwise. */
++
++static bool
++operation_uses_upper_bits (rtx dest, rtx src, unsigned int regno_use,
++ int indent ATTRIBUTE_UNUSED)
++{
++ rtx regspec_src = find_regspec_regno (regno_use, src);
++
++ if (check_compare (dest, src))
++ return false;
++
++ /* Store of regno to mem, size stored is the same or smaller than the extended from size */
++ if (MEM_P (dest)
++ && (GET_MODE_BITSIZE (GET_MODE (dest)) <=
++ GET_MODE_BITSIZE (ext_from_mode))
++ /* Ensure the used register is being stored and not used in another capacity, say, as a pointer. */
++ && (regspec_src))
++ return false;
++
++ /* Operation operand size is the same or smaller than the extended from size */
++ if (regspec_src)
++ {
++ if (GET_MODE_BITSIZE (GET_MODE (regspec_src)) <=
++ GET_MODE_BITSIZE (ext_from_mode))
++ return false;
++ }
++
++ /* Default to the safest result */
++ return true;
++}
++
++/* Determine if this insn also extends to the size or greater of the original extension.
++ Sign extend can propagate to zero extend and vice-versa because the upper bits
++ haven't affected the low bits up to now throughout the propagation. */
++
++static bool
++operation_extends_to_upper_bits_size (rtx src, int indent ATTRIBUTE_UNUSED)
++{
++ /* Sign extension of the same type as the originating extension.
++ Here the candidate uses the register defined by the originating extension.
++ If the candidate is found to be redundant, the originating extension is
++ replaced with a copy.
++
++ We follow these rules:
++
++ dest_mode == machine mode of the destination for this candidate extension
++ (it's the same mode as the src, e,g, reg:DI = sign_extend:DI ...)
++ src_mode == machine mode of the source for this candidate extension
++ (the mode of the used register, SI in this case, e.g. reg:DI = sign_extend:DI (subreg:SI (reg:DI))
++ ext_to_mode == machine mode of the originating extension output
++ ext_from_mode == machine mode of the originating extension input
++
++ SIZE(cand_from_mode) >= SIZE(extend_from_mode) && SIZE(cand_to_mode) <= SIZE(extend_to_mode)
++
++ Example 1:
++ Originating (SI->DI)
++ DI SI HI QI 0
++ |<-------| | | |
++
++ Candidate (HI->SI extension)
++ DI SI HI QI 0
++ | |<---| | |
++
++ Not redundant, candidate does not cover the original bits:
++ SIZE(dest_mode)[SI] !<= SIZE(extend_to_mode)[DI]
++
++ Example 2:
++ Originating (HI->SI)
++ DI SI HI QI 0
++ | |<---| | |
++
++ Candidate (QI->DI extension)
++ DI SI HI QI 0
++ |<-------|----|--| |
++
++ Redundant, candidate covers the original bits:
++ SIZE(cand_to_mode) [DI] >= SIZE(extend_to_mode) [SI]
++ AND
++ SIZE(cand_from_mode) [QI] <= SIZE(extend_from_mode) [HI] */
++ if (GET_CODE (src) == ext_code)
++ {
++ /* Extend is redundant if we don't overwrite the source of the
++ previous extension and extends to at least the extent of the original. */
++ enum machine_mode cand_from_mode = GET_MODE (XEXP (src, 0));
++ enum machine_mode cand_to_mode = GET_MODE (src);
++ if (GET_MODE_BITSIZE (cand_from_mode) >=
++ GET_MODE_BITSIZE (ext_from_mode)
++ && (GET_MODE_BITSIZE (cand_to_mode) <=
++ GET_MODE_BITSIZE (ext_to_mode)))
++ return true;
++ }
++
++ /* Encountered an insn with the same effect as extension, e.g.
++ AND (regspec) (const_int). E.g. AND (reg:SI) (0xffff) is equivalent
++ to ZERO_EXTEND:DI (reg:HI) */
++ if ((GET_CODE (src) == AND) && CONST_INT_P (XEXP (src, 1)))
++ {
++ /* Extends to at least the original extension size */
++ if (GET_MODE_BITSIZE (GET_MODE (src)) >= GET_MODE_BITSIZE (ext_to_mode))
++ {
++ if (ext_from_mode == QImode && (UINTVAL (XEXP (src, 1)) <= 0xff))
++ return true;
++ else if (ext_from_mode == HImode
++ && (UINTVAL (XEXP (src, 1)) <= 0xffff))
++ return true;
++ else if (ext_from_mode == SImode
++ && (UINTVAL (XEXP (src, 1)) <= 0xffffffff))
++ return true;
++ else
++ return false;
++ }
++ }
++ return false;
++}
++
++/* Determine whether the operation's upper bits subtly or overtly affects the low bits. */
++
++static bool
++operation_implicitly_affects_lowbits (rtx dest, rtx src,
++ unsigned int regno_use, int indent)
++{
++ rtx regspec = find_regspec_regno (regno_use, src);
++
++ /* First, a return expression must be assumed to affect the lowbits as the return value
++ must be extended properly. */
++ if (return_val_p (dest))
++ {
++ if (dump_file)
++ {
++ fprintf (dump_file, "%*sDestination is a return value\n", indent,
++ " ");
++ }
++ return true;
++ }
++
++ /* These operations implicitly affect the lowbits, except where noted. */
++ switch (GET_CODE (src))
++ {
++ case MULT:
++ case DIV:
++ case UDIV:
++ case UMOD:
++ case MOD:
++ /* Normally, yes, these operations return true (affects low bits). But when the
++ the operand size is less than or equal to the "low bits" size AND the operation size
++ is the same as the operand size, the operation is performed only on the "low bits"
++ and the "upper bits" do not contribute to the output. */
++ if (regspec
++ && (GET_MODE_BITSIZE (GET_MODE (regspec)) <=
++ GET_MODE_BITSIZE (ext_from_mode))
++ && GET_MODE_BITSIZE (GET_MODE (src)) ==
++ GET_MODE_BITSIZE (GET_MODE (regspec)))
++ return false;
++ return true;
++
++ break;
++ /* Shift rights normally affect the low bits. There can be special cases where this
++ is not true, such a the operand size is smaller than the extended from size, e.g.
++ set (reg:SI Y) (zero_extend:SI (subreg:HI (reg:SI X)))
++ set (reg:QI Z) (lshiftrt (subreg:QI (reg:SI Y))
++ The shift of the QI data is not affected by the extension of HI data unless the
++ shift is large enough to encroach into the QI bits. This seems rare and I do not
++ check for it. */
++ case LSHIFTRT:
++ case ASHIFTRT:
++ return true;
++ break;
++ /* Other operations are known not to impact the low bits */
++ default:
++ return false;
++ }
++
++}
++
++/* The operation directly defines a propagatable output. Several
++ operations do not define such output. E.g. MEM (loads) do not
++ define an output based on the operation. USE is another example,
++ as it isn't a real operation. */
++
++static bool
++operation_directly_defines_an_output (rtx dest, rtx src,
++ int indent ATTRIBUTE_UNUSED)
++{
++ switch (GET_CODE (src))
++ {
++ case REG:
++ case SUBREG:
++ case PLUS:
++ case MINUS:
++ case NEG:
++ case MULT:
++ case DIV:
++ case MOD:
++ case UDIV:
++ case UMOD:
++ case AND:
++ case IOR:
++ case XOR:
++ case NOT:
++ case ASHIFT:
++ case ROTATE:
++ case ASHIFTRT:
++ case LSHIFTRT:
++ case ROTATERT:
++ case SIGN_EXTEND:
++ case ZERO_EXTEND:
++ case TRUNCATE:
++ return true;
++ break;
++ /* OK to propagate if the output of IF_THEN_ELSE is a register */
++ case IF_THEN_ELSE:
++ if (REG_P (dest))
++ return true;
++ break;
++ /* All others are assumed not to generate a normal output */
++ default:
++ break;
++ }
++ return false;
++}
++
++/* Helper for insn_use_analysis_result */
++
++static enum insn_use_results
++insn_use_analysis_result_1 (rtx insn, bool treat_as_copy,
++ unsigned int regno_use, rtx * dest, int indent)
++{
++ rtx src;
++ bool cond_a, cond_b, cond_c, cond_d;
++
++ if (GET_CODE (insn) != SET)
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++
++ *dest = SET_DEST (insn);
++ src = SET_SRC (insn);
++
++ /* Bail out on inline assembly also */
++ if (GET_CODE (src) == ASM_INPUT || GET_CODE (src) == ASM_OPERANDS)
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++
++ /* Bail out on non supported types */
++ if (!mode_supported_p (*dest))
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++
++ /* First, we determine cond_c (is a redundant extension) because it gates the
++ other conditions. */
++ if ((cond_c = operation_extends_to_upper_bits_size (src, indent)))
++ {
++ if (treat_as_copy)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s is treated as a copy (marked for replace)\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (src)));
++ return EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION;
++ }
++
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s is a redundant extension\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (src)));
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_NOT_AFFECTED;
++ }
++
++ cond_a = operation_uses_upper_bits (*dest, src, regno_use, indent);
++
++ cond_b =
++ operation_implicitly_affects_lowbits (*dest, src, regno_use, indent);
++
++ cond_d = operation_directly_defines_an_output (*dest, src, indent);
++
++ /* Operation implicitly affects low bits */
++ if (cond_b)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s implicitly affects low bits\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (src)));
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++ }
++
++ /* Neither cond_a nor cond_b affects the low bits */
++ if (!cond_a)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s does not use upper bits\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (src)));
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_NOT_AFFECTED;
++ }
++
++ /* To continue recursion, the operation must define a
++ meaningful output. */
++ if (!cond_d)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*s...%s does not define a propagatable output\n",
++ indent, " ", GET_RTX_NAME (GET_CODE (src)));
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++ }
++
++ /* This leaves cond_a, meaning we need to continue down the chain
++ to see if the low bits are ultimately affected by the upper bits. */
++ return EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION;
++}
++
++/* Determine the action based on the insn conditions. The truth table is
++ simplified using if statements. Insns previously marked for replace by copy
++ are identified, these will be essentially be treated as copies now and not
++ be detected as redundant for this use. */
++static enum insn_use_results
++insn_use_analysis_result (rtx insn_insn, unsigned int regno_use, rtx * dest,
++ int indent)
++{
++ bool treat_as_copy = false;
++ if (insn_flag_p (EXTELIM_REPLACE_COPY, INSN_UID (insn_insn)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*suse at uid=%d is marked to transform to copy\n", indent,
++ " ", INSN_UID (insn_insn));
++ treat_as_copy = true;
++ }
++ return (insn_use_analysis_result_1
++ (PATTERN (insn_insn), treat_as_copy, regno_use, dest, indent));
++}
++
++/* We have to analyze each expression action in a PARALLEL series.
++ Return the appropriate action for a series of expressions in a PARALLEL insn.
++ LOWBITS_AFFECTED stops the loop. This leaves only CONTINUE_RECURSION
++ or LOWBITS_NOT_AFFECTED. LOWBITS_NOT_AFFECTED is only returned
++ if there are no other different actions in the series (no CONTINUE_RECURSION
++ states). For each CONTINUE_RECURSION action we encounter, the destination
++ registers must be identical since we can only propagate one use (one definition
++ of dest) should CONTINUE_RECURSION be returned. */
++
++static enum insn_use_results
++analyze_action (enum insn_use_results cur_action,
++ enum insn_use_results prev_action,
++ rtx * dest, rtx * prev_dest)
++{
++ enum insn_use_results return_action;
++
++ if (cur_action == EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED)
++ return cur_action;
++
++ if (cur_action == EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION)
++ return_action = cur_action;
++ else if (prev_action == EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION)
++ return_action = EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION;
++ else
++ return_action = cur_action;
++
++ if (return_action == EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION)
++ {
++ if (*prev_dest)
++ {
++ /* All bets off if the series defines multiple outputs */
++ if (*prev_dest != *dest)
++ return_action = EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++ }
++ }
++ /* Set prev_dest */
++ *prev_dest = *dest;
++
++ return return_action;
++}
++
++/* Helper 2 for insn_use_analysis. Return the appropriate action
++ for a series of expressions in a PARALLEL insn. */
++
++static enum insn_use_results
++insn_use_analysis_2 (rtx insn_use, unsigned int regno_use, rtx * dest,
++ int indent)
++{
++ int i;
++ rtx insn = PATTERN (insn_use);
++ rtx prev_dest = NULL_RTX;
++ enum insn_use_results action;
++ enum insn_use_results return_action =
++ EXTELIM_ANALYSIS_RESULT_LOWBITS_NOT_AFFECTED;
++
++ gcc_assert (GET_CODE (insn) == PARALLEL);
++
++ /* We make a quick decision about call_insns here. Since the use reached
++ a call, we assume it's an outgoing parameter and thus must be extended
++ as per the ABI. */
++ if (CALL_P (insn_use))
++ {
++ if (dump_file)
++ fprintf (dump_file, "%*s...is a call parameter\n", indent, " ");
++ return EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED;
++ }
++
++ for (i = XVECLEN (insn, 0) - 1; i >= 0; i--)
++ {
++ rtx body = XVECEXP (insn, 0, i);
++ /* Only act on the expressions containing a use of regno_use. */
++ if (regno_use_in (regno_use, body) == NULL_RTX)
++ continue;
++
++ /* Determine the next action */
++ action = insn_use_analysis_result_1 (body, false /* treat as copy */ ,
++ regno_use, dest, indent);
++
++ /* Here we make a decision on the return action based on the previous actions.
++ This is done to accomodate different actions from different elements in the
++ PARALLEL series of expressions. */
++ return_action =
++ analyze_action (action, return_action, dest, &prev_dest);
++
++ /* The result of this expression stops the recursion, i.e. "low bits"
++ are affected by the operation. */
++ if (return_action == EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED)
++ break;
++ }
++ return (return_action);
++}
++
++/* Helper 1 for insn_use_analysis */
++
++static enum insn_use_results
++insn_use_analysis_1 (rtx insn_use, unsigned int regno_use, rtx * dest,
++ int indent)
++{
++ rtx use = PATTERN (insn_use);
++ enum insn_use_results action;
++
++ switch (GET_CODE (use))
++ {
++ case PARALLEL:
++ action = insn_use_analysis_2 (insn_use, regno_use, dest, indent);
++ break;
++ default:
++ action = insn_use_analysis_result (insn_use, regno_use, dest, indent);
++ break;
++ }
++
++ return action;
++}
++
++/* Analyze the insn and determine the next course of action in the
++ use analysis loop.
++ There are several conditions to consider:
++
++ 1. The "extended from" mode. This is an enum machine_mode value
++ that determines what is the size extended. It is derived from the
++ source of the original extension. It is the "low bits" value.
++ It is these range of bits that cannot be affected by the operation's
++ "upper bits" in order to determine whether the extend is useful or not.
++ Examples:
++ (1) set (reg:DI Y (zero_extend:DI (subreg:QI (reg:DI X))) ==> low bits = QI
++ (2) set (reg:SI Y (sign_extend:SI (reg:HI X) ==> low bits = HI
++
++ 2. The "extend to" mode. This is the size extended to in the original
++ extension. It is the "upper bits" value. The entire extended to size may
++ be used subsequently or it may be subreg'd to a smaller or larger sizes
++ later in the propagation.
++ For example (1) above, "upper bits" is DI, and (2) "upper bits" is SI.
++
++ 3. The code, ext_code, of the original extension, either ZERO_EXTEND or SIGN_EXTEND.
++
++ 4. Operation code. For an insn, the actual operation code corresponding to
++ a machine instruction. For certain codes, we know that the "low bits" of the
++ result are modified by the insn because of the values in the "upper bits" of the
++ input operand. We say the operation implicitly uses the "upper bits" to modify the
++ "low bits". For other codes, the "upper bits" do not affect the output result
++ in the "low bits".
++
++ If the operation does implicitly use the "upper bits" to modify
++ the "low bits", it is instantly a deal killer. The original extension must be
++ preserved.
++
++ If the operation does not implicitly use "upper bits" to modify the "low bits",
++ then the action to take depends on the operation operand size relative to
++ "low bits" size.
++
++ We only want to deal with codes that map to real instructions,
++ like ADD, SUB, MULT, LSHIFTRT, etc. Codes such as PARALLEL, etc. do not map to
++ instruction and must be dissected to extract the real instructions.
++
++ Furthermode, for recursion to continue, the operation and operand must define
++ an output related to the input operand (the use register). This doesn't happen
++ for operations such as "mem" where the output is indirectly related to the
++ input operand.
++
++ 5. Operation mode. The operation mode of the operation code. This sometimes impacts
++ the effect of the operation. For example MULT:SI and MULT:DI map to two different
++ machine instructions and both may have operands of SI mode. However, the MULT:SI
++ results will be oblivious to the upper bits of the DI register whereas, SI part of
++ MULT:DI result will be affected by the upper bits of the DI register.
++
++ Several conditions determine the action to take based on the various inputs.
++
++ The truth table inputs are A, B, and C. The truth table output is the action to take.
++
++ A. True if the used operand mode size is greater than the extended_from ("low bits") mode size.
++ B. True if the operation implicitly uses upper bits to define the low bits
++ C. True if the operation also extends the output to upper bits size
++ D. True if the operation and input operand directly define an output operand.
++
++ Condition A. means the upper bits are in use in the operation. The extend _may_ be needed,
++ all things being equal, so the action would be to continue recursion to the use of the
++ defined operand, i.e. return CONTINUE_RECURSION.
++
++ Condition B. means the "low bits" are modified by the extended portion of the register
++ by virtue of the operation. For example, logical shift right, where the extended
++ portion is shifted into the "low bits". Another example, multiply, where the machine
++ uses the extended portion implicitly to calculate the results, some of which are
++ reflected in the "low bits" of the result. The extension is definitely needed in these
++ cases for this use, so return LOWBITS_AFFECTED. Recursion is stopped and analysis of
++ this extension is halted.
++
++ Condition C. means the operation and it's operands perform the same extension as
++ the originating extension. The operation must extend to the same size _or higher_ of
++ the original extension. In this case, the original extension is truly redundant and
++ we return LOWBITS_NOT_AFFECTED for this use.
++
++ Condtion D. means the operation and operand directly define an output operand. For most
++ arithmetic and unary operations this is true. For mem and other internal operations,
++ e.g. USE, this is false.
++
++ Condition Action Comments
++ ==================================================================
++ A. B. C. D.
++ ------------------------------------------------------------------
++ X X true true LOW_BITS_NOT_AFFECTED extend is redundant
++ ------------------------------------------------------------------
++ false false false X LOW_BITS_NOT_AFFECTED used operand is smaller than "low bits"
++ ------------------------------------------------------------------
++ false true false true LOW_BITS_AFFECTED "low bits" modified implicitly by operation
++ ------------------------------------------------------------------
++ true false false true CONTINUE_RECURSION "low bits" _may_ be impacted by next uses
++ ------------------------------------------------------------------
++ true true false true LOW_BITS_AFFECTED "low bits" modified implicitly by operation */
++
++static enum insn_use_results
++insn_use_analysis (rtx insn_use, unsigned int regno_use, rtx * dest,
++ int indent)
++{
++ return (insn_use_analysis_1 (insn_use, regno_use, dest, indent));
++}
++
++/* Analyze the operation and operands of this use of a sign extension
++ target register. If the target register's upper bits do not
++ affect the result of the operation, then the sign extension is
++ useless. Returns true if the extension is needed, false
++ otherwise. */
++
++static bool
++analyze_ext_use (rtx insn_use, unsigned int regno_use, int indent)
++{
++ bool ext_needed, indent_once;
++ unsigned int dest_target_regno;
++ extelim_uid_t uid;
++ rtx use = PATTERN (insn_use), dest;
++ df_ref df_use, *p_def;
++ struct df_link *link;
++ enum insn_use_results analysis_result;
++
++ gcc_assert (use != NULL);
++
++ uid = INSN_UID (insn_use);
++
++ if (insn_flag_p (EXTELIM_SEEN, uid))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*suse at uid=%d is visited already\n", indent, " ", uid);
++ return false;
++ }
++
++ /* Mark this insn as seen */
++ insn_flag_set (EXTELIM_SEEN, uid);
++
++ analysis_result = insn_use_analysis (insn_use, regno_use, &dest, indent);
++ switch (analysis_result)
++ {
++ /* We know conclusively that the "upper bits" of the extended
++ entity do not impact the "low bits" of the output of the operation. */
++ case EXTELIM_ANALYSIS_RESULT_LOWBITS_NOT_AFFECTED:
++ if (dump_file)
++ fprintf (dump_file, "%*suse at uid=%d is not affected\n", indent, " ",
++ uid);
++ return false;
++ break;
++ /* We know conclusively that the "upper bits" of the extended
++ entity _do_ impact the "low bits" of the output of the operation. */
++ case EXTELIM_ANALYSIS_RESULT_LOWBITS_AFFECTED:
++ if (dump_file)
++ fprintf (dump_file, "%*suse at uid=%d is affected\n", indent, " ",
++ uid);
++ return true;
++ break;
++ /* Continue to look at the uses of the result to determine the impact
++ of the "upper bits" */
++ case EXTELIM_ANALYSIS_RESULT_CONTINUE_RECURSION:
++ break;
++ default:
++ gcc_unreachable ();
++ }
++
++ /* We reach here because the action taken is CONTINUE_RECURSION.
++ Continue to look at the uses of the destination register recursively.
++ If the propagation ultimately ends where the upper bits are not significant
++ to the final output, then the extension can be removed. */
++ if (!REG_P (dest))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sdest of uid=%d (SET) is not a register\n", indent, " ",
++ uid);
++ return true;
++ }
++
++ dest_target_regno = REGNO (dest);
++
++ /* What this insn defines */
++ p_def = DF_INSN_UID_DEFS (uid);
++
++ /* Ref must be valid and there must be only one definition and it must be the
++ destination */
++ if ((*p_def == NULL) || (*(p_def + 1) != NULL))
++ return true;
++
++ gcc_assert (DF_REF_REGNO (*p_def) == dest_target_regno);
++
++ ext_needed = true;
++ indent_once = true;
++ for (link = DF_REF_CHAIN (*p_def); link; link = link->next)
++ {
++ rtx insn_use, use_exp;
++ df_use = link->ref;
++ if (!df_use)
++ continue;
++ /* Link must be a USE of the DEF */
++ if (!DF_REF_REG_USE_P (df_use))
++ continue;
++ /* Ignore ARTIFICIAL USES */
++ if (DF_REF_IS_ARTIFICIAL (df_use))
++ continue;
++ insn_use = DF_REF_INSN (df_use);
++ /* Don't consider debug_insns */
++ if (!NONDEBUG_INSN_P (insn_use))
++ continue;
++ use_exp = DF_REF_REG (df_use);
++
++ if (exp_needs_update_p (use_exp))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "%*ssaved reg=%d expression for update\n", indent, " ", DF_REF_REGNO (df_use));
++ save_ext_update (current_ext_record, use_exp);
++ }
++
++ if (dump_file)
++ fprintf (dump_file,
++ "%*suse at uid=%d of reg=%d\n", indent, " ",
++ INSN_UID (insn_use), DF_REF_REGNO (df_use));
++ /* Set indent for dump formatting */
++ if (indent_once)
++ {
++ ++indent;
++ indent_once = false;
++ }
++ ext_needed = analyze_ext_use (insn_use, DF_REF_REGNO (df_use), indent);
++ if (ext_needed)
++ break;
++ }
++
++ if (dump_file)
++ fprintf (dump_file,
++ "%*sext %s needed\n", indent, " ", ext_needed ? "" : "not");
++
++ return ext_needed;
++}
++
++/* Set a flag on an insn indicating that it is
++ marked for replacement by a copy insn or for
++ deletion. */
++
++static void
++mark_replace_with_copy (rtx ext)
++{
++ extelim_uid_t uid = INSN_UID (ext);
++ insn_flag_set (EXTELIM_REPLACE_COPY, uid);
++}
++
++/* Get the mode that we are sign/zero extending from */
++
++static enum machine_mode
++get_ext_from_mode (rtx src)
++{
++ rtx regexp;
++ gcc_assert (GET_CODE (src) == ZERO_EXTEND || GET_CODE (src) == SIGN_EXTEND);
++
++ /* The SUBREG or REG mode of the extend operand */
++ regexp = XEXP (src, 0);
++ return (GET_MODE (regexp));
++}
++
++/* Perform the action on the expression. Return true
++ if any action performed, false otherwise. */
++
++static bool
++process_ext_update (rtx exp)
++{
++ /* Reset SUBREG_PROMOTED state to false */
++ if (GET_CODE (exp) == SUBREG
++ && SUBREG_PROMOTED_VAR_P (exp))
++ {
++ SUBREG_PROMOTED_VAR_P (exp) = 0;
++ return true;
++ }
++
++ return false;
++}
++
++/* Process the current extension record, looking at all the
++ the expressions that need to be updated because this
++ extension will be replaced by a copy. */
++
++static void
++process_ext_updates (ext_record_t extrec)
++{
++ unsigned i;
++ rtx exp;
++ bool updated=false;
++
++
++ FOR_EACH_VEC_ELT (rtx, extrec->ext_updates, i, exp)
++ {
++ updated |= process_ext_update (exp);
++ }
++
++ if (dump_file && updated)
++ fprintf (dump_file, " updates processed for extension at uid=%d\n",
++ INSN_UID (extrec->ext));
++}
++
++/* Try to eliminate the sign extension by examining the
++ definitions of the extension source and the uses
++ of the extension destination. */
++
++static void
++eliminate_one_extend (rtx ext)
++{
++ rtx src, dest, regexp;
++ df_ref df_use, df_def, *ext_use, *ext_def;
++ unsigned int ext_dest_regno, ext_src_regno, def_use_count = 1;
++ bool ext_needed = true;
++ extelim_uid_t uid = INSN_UID (ext);
++ struct df_link *link;
++ const char *inserted =
++ insn_flag_p (EXTELIM_INSERTED, uid) ? "inserted" : "";
++
++ /* Reset desired per insn flags for each extension analyzed */
++ reinit_insn_flags (EXTELIM_SEEN);
++
++ gcc_assert (GET_CODE (PATTERN (ext)) == SET);
++ src = SET_SRC (PATTERN (ext));
++ dest = SET_DEST (PATTERN (ext));
++
++ /* Save the basic information about the extension in a file global */
++ ext_to_mode = GET_MODE (dest);
++ ext_from_mode = get_ext_from_mode (src);
++ ext_code = GET_CODE (src);
++
++ /* Also mark this original extension as "SEEN" so we don't recurse into it. */
++ insn_flag_set (EXTELIM_SEEN, INSN_UID (ext));
++
++ /* Find the target of the extension */
++ if (!REG_P (dest))
++ return;
++ ext_dest_regno = REGNO (dest);
++
++ /* Find the source of the extension: set (REG:MODE (sign_extend (REG|SUBREG:MODE ... */
++ if ((regexp = register_exp (XEXP (src, 0))) == NULL)
++ return;
++ ext_src_regno = REGNO (regexp);
++
++ /* Iterate through the reaching definitions of the source of the extension
++ recursively. If the source if already sign extended, mark the
++ extension for replacement with a copy or deletion (deletion if it was
++ inserted in the duplication pass). */
++ ext_use = DF_INSN_UID_USES (uid);
++ /* There is only one use in a sign/zero extension insn and it must be the
++ source register */
++ gcc_assert (*(ext_use + 1) == NULL);
++ gcc_assert (DF_REF_REGNO (*ext_use) == ext_src_regno);
++
++ /* Now look at all the reaching definitions of this use */
++ for (link = DF_REF_CHAIN (*ext_use); link; link = link->next)
++ {
++ rtx insn_def;
++ df_def = link->ref;
++ if (!df_def)
++ continue;
++ /* Link must be to a definition of the use */
++ if (!DF_REF_REG_DEF_P (df_def))
++ continue;
++ /* Ignore ARTIFICIAL defs */
++ if (DF_REF_IS_ARTIFICIAL (df_def))
++ continue;
++ insn_def = DF_REF_INSN (df_def);
++ /* Don't consider debug_insns */
++ if (!NONDEBUG_INSN_P (insn_def))
++ continue;
++ if (dump_file)
++ fprintf (dump_file,
++ " analyze def #%d of reg=%d at uid=%u\n",
++ def_use_count, DF_REF_REGNO (*ext_use), INSN_UID (insn_def));
++ ext_needed = analyze_ext_def (insn_def, DF_REF_REGNO (*ext_use), 2);
++ if (ext_needed)
++ break;
++ def_use_count++;
++ }
++
++ /* Try the def-use chains if the extension wasn't marked by the
++ previous pass. */
++ if (ext_needed)
++ {
++ /* Defs of the sign extension */
++ ext_def = DF_INSN_UID_DEFS (uid);
++ /* There is only one def in a sign extension insn and it must be the
++ destination */
++ gcc_assert (*(ext_def + 1) == NULL);
++ gcc_assert (DF_REF_REGNO (*ext_def) == ext_dest_regno);
++
++ /* Counter for debug dump */
++ def_use_count = 1;
++ /* Reset desired per insn flags for each extension analyzed */
++ reinit_insn_flags (EXTELIM_SEEN);
++ /* Also mark this original extension as "SEEN" so we don't recurse into it. */
++ insn_flag_set (EXTELIM_SEEN, INSN_UID (ext));
++
++ /* Iterate over the reached uses of extension destination register recursively.
++ If the destination register's upper bits are ultimately not
++ relevant, the extension can be marked for replacement with a
++ copy. */
++ for (link = DF_REF_CHAIN (*ext_def); link; link = link->next)
++ {
++ rtx insn_use, use_exp;
++ df_use = link->ref;
++ if (!df_use)
++ continue;
++ /* Link must be a USE of the DEF */
++ if (!DF_REF_REG_USE_P (df_use))
++ continue;
++ /* Ignore ARTIFICIAL USES */
++ if (DF_REF_IS_ARTIFICIAL (df_use))
++ continue;
++ insn_use = DF_REF_INSN (df_use);
++ /* Don't consider debug_insns */
++ if (!NONDEBUG_INSN_P (insn_use))
++ continue;
++ use_exp = DF_REF_REG (df_use);
++
++ if (exp_needs_update_p (use_exp))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " saved reg=%d expression for update\n", DF_REF_REGNO (df_use));
++ save_ext_update (current_ext_record, use_exp);
++ }
++
++ if (dump_file)
++ fprintf (dump_file,
++ " analyze use #%d at uid=%u of reg=%d\n",
++ def_use_count, INSN_UID (insn_use),
++ DF_REF_REGNO (*ext_def));
++ ext_needed = analyze_ext_use (insn_use, DF_REF_REGNO (*ext_def), 2);
++ if (ext_needed)
++ break;
++ def_use_count++;
++ }
++ }
++
++ /* The extension is not needed. The rtl for the extension is marked
++ for replace by copy. */
++ if (!ext_needed)
++ {
++ process_ext_updates (current_ext_record);
++
++ if (dump_file)
++ fprintf (dump_file,
++ ":) mark %s extension insn uid=%d for copy replacement\n",
++ inserted, INSN_UID (ext));
++ mark_replace_with_copy (ext);
++ num_cand_transformed++;
++ }
++ else
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ ":( %s extension insn uid=%d is needed\n", inserted,
++ INSN_UID (ext));
++ }
++}
++
++/* Replace the sign extension with a copy instruction
++
++ example 1:
++ from:
++ dest src
++ (set (reg:DI destreg) (sign_extend:DI (reg:SI srcreg)))
++ to:
++ (clobber (reg:DI destreg))
++ (set (subreg:SI (reg:DI destreg) 4) (reg:SI srcreg))
++
++ or
++
++ example 2:
++ from:
++ dest src
++ (set (reg:DI destreg) (sign_extend:DI (subreg:SI (reg:DI srcreg) 4)))
++ to:
++ (clobber (reg:DI destreg))
++ (set (subreg:SI (reg:DI destreg) 4) (subreg:SI (reg:DI srcreg) 4))
++
++ or
++
++ example 3:
++ from:
++ dest src
++ (set (reg:SI destreg) (sign_extend:SI (subreg:HI (reg:SI srcreg) 2)))
++ to:
++ (clobber (reg:SI destreg))
++ (set (subreg:HI (reg:SI destreg) 2) (subreg:HI (reg:SI srcreg) 2)) */
++
++static void
++replace_with_copy (rtx ext)
++{
++ rtx extension = PATTERN (ext);
++ rtx ext_op, src, dest, insns, cp_dest, cp_src;
++ enum machine_mode inner_mode;
++ gcc_assert (GET_CODE (extension) == SET);
++
++ dest = SET_DEST (extension);
++ src = SET_SRC (extension);
++
++ /* The sign extension operand */
++ ext_op = XEXP (src, 0);
++ /* Get the inner mode */
++ inner_mode = GET_MODE (ext_op);
++ gcc_assert (inner_mode == SImode || inner_mode == HImode
++ || inner_mode == QImode);
++
++ /* Make dest a SUBREG:mm */
++ cp_dest = gen_lowpart_SUBREG (inner_mode, dest);
++
++ /* Copy src is the sign extension target register */
++ cp_src = ext_op;
++
++ /* ??? clobber is needed for rtl consistency, don't know why */
++ start_sequence ();
++ emit_clobber (dest);
++ emit_move_insn (cp_dest, cp_src);
++ insns = get_insns ();
++ end_sequence ();
++ emit_insn_before (insns, ext);
++
++ delete_insn (ext);
++}
++
++/* Iterate through extensions, replace those extensions
++ that are marked as so with a copy insn. */
++
++static void
++replace_ext_with_copy (void)
++{
++ ext_record_t extrec;
++ unsigned i;
++
++ FOR_EACH_VEC_ELT (ext_record_t, extensions, i, extrec)
++ {
++ const char *inserted = insn_flag_p (EXTELIM_INSERTED,
++ INSN_UID (extrec->
++ ext)) ? "inserted" : "";
++ if (insn_flag_p (EXTELIM_REPLACE_COPY, INSN_UID (extrec->ext)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " replace %s extension uid=%d with a copy\n", inserted,
++ INSN_UID (extrec->ext));
++ replace_with_copy (extrec->ext);
++ }
++ }
++}
++
++
++/* Copy the RTX flags from old to new */
++
++static void
++copy_flags (rtx oldrtx, rtx newrtx)
++{
++ if (RTX_FLAG (oldrtx, in_struct))
++ RTX_FLAG (newrtx, in_struct) = true;
++
++ if (RTX_FLAG (oldrtx, volatil))
++ RTX_FLAG (newrtx, volatil) = true;
++
++ if (RTX_FLAG (oldrtx, unchanging))
++ RTX_FLAG (newrtx, unchanging) = true;
++
++ if (RTX_FLAG (oldrtx, frame_related))
++ RTX_FLAG (newrtx, frame_related) = true;
++
++ if (RTX_FLAG (oldrtx, jump))
++ RTX_FLAG (newrtx, jump) = true;
++
++ if (RTX_FLAG (oldrtx, call))
++ RTX_FLAG (newrtx, call) = true;
++
++ if (RTX_FLAG (oldrtx, return_val))
++ RTX_FLAG (newrtx, return_val) = true;
++}
++
++/* Iterate through the insn notes looking for 'kind'. If
++ found replace the register rtx with the new rtx. */
++
++static void
++update_notes (enum reg_note kind, rtx insn, rtx reg, rtx new_reg)
++{
++ rtx link;
++ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
++ if (REG_NOTE_KIND (link) == kind)
++ {
++ rtx op0 = XEXP (link, 0);
++ if (kind == REG_DEAD)
++ if (REG_P (op0) && op0 == reg)
++ XEXP (link, 0) = new_reg;
++ }
++}
++
++
++
++#if EXTELIM_DUPLICATE_EXTS_AT_USES
++/* Insert a duplicate sign extension at the use point.
++ Add a flag indicating this extension is algorithmically
++ added. Since the "inserted" extensions have the form
++ regX = sign_extend (subreg:mm (reg:MM regX), offset),
++ they can simply be deleted if they are redundant since we
++ are at a reaching use of the original definition. We also
++ mark the use insn where the insert occurs so we don't insert
++ the same extension from another def at this use. */
++
++static void
++insert_duplicate_ext_at_use (rtx ext_insn, rtx use_insn)
++{
++ rtx ext = PATTERN (ext_insn), ext_src, ext_dest;
++ rtx new_ext_src_inner, new_ext_src_outer, new_ext_part;
++ rtx new_ext_dest, new_ext_insn;
++ extelim_uid_t new_uid;
++ df_ref *p_df_uses;
++ unsigned int ext_dest_regno;
++ enum machine_mode inner_mode;
++ bool sign_extend_p =
++ GET_CODE (SET_SRC (PATTERN (ext_insn))) == SIGN_EXTEND ? true : false;
++
++ /* This new extension must be of the form:
++ set (reg:MM X (sign_extend:MM (subreg:mm (reg:MM X))))
++ where mm is smaller than MM. */
++ ext_dest = SET_DEST (ext);
++ ext_src = SET_SRC (ext);
++
++ gcc_assert (REG_P (register_exp (ext_dest)));
++
++ /* A copy of the extend destination register to a new virtual register */
++ new_ext_dest = gen_reg_rtx (GET_MODE (ext_dest));
++ /* A copy of the extend source (same reg as dest), REG_P */
++ new_ext_src_inner = copy_rtx (ext_dest);
++ /* Get inner mode, either mm for SUBREG:mm (REG:MM) or MM for (REG:MM) */
++ if (GET_CODE (XEXP (ext_src, 0)) == SUBREG)
++ inner_mode = GET_MODE (XEXP (ext_src, 0));
++ else if (REG_P (XEXP (ext_src, 0)))
++ inner_mode = GET_MODE (XEXP (ext_src, 0));
++ else
++ /* Can't determine sign_extend operand */
++ gcc_unreachable ();
++
++ /* Make a subreg rtx */
++ new_ext_src_outer = gen_lowpart_SUBREG (inner_mode, new_ext_src_inner);
++ /* Make a sign/zero extend insn */
++ new_ext_part = sign_extend_p
++ ? gen_rtx_SIGN_EXTEND (GET_MODE (ext_dest), new_ext_src_outer)
++ : gen_rtx_ZERO_EXTEND (GET_MODE (ext_dest), new_ext_src_outer);
++ /* (set (new:MM (sign_extend:MM (subreg:mm (reg:MM ext_dest))))) */
++ new_ext_insn = gen_rtx_SET (VOIDmode, new_ext_dest, new_ext_part);
++
++ /* Now update the use */
++ /* Operands used by this the use_insn */
++ ext_dest_regno = REGNO (register_exp (ext_dest));
++ for (p_df_uses = DF_INSN_UID_USES (INSN_UID (use_insn)); *p_df_uses;
++ p_df_uses++)
++ {
++ if (DF_REF_REGNO (*p_df_uses) == ext_dest_regno)
++ {
++ rtx use_reg = DF_REF_REG (*p_df_uses);
++
++ /* Replace the register use in use_insn with the new register. If the use
++ is a subreg pattern, replace the innermost reg. */
++ replace_rtx (PATTERN (use_insn), register_exp (use_reg),
++ new_ext_dest);
++ /* Update flags on new dest reg */
++ copy_flags (register_exp (use_reg), new_ext_dest);
++ /* Update any notes associated with use reg and use_insn */
++ update_notes (REG_DEAD, use_insn, register_exp (use_reg), new_ext_dest);
++ /* DF info must be updated since existing insn is changed */
++ df_insn_rescan (use_insn);
++ }
++ }
++
++ new_uid = extelim_emit_before (new_ext_insn, use_insn);
++ insn_flag_set (EXTELIM_INSERTED, new_uid);
++}
++
++/* Allow the duplication of the extension even if the extension
++ and the duplication use are in the same block. */
++
++static bool
++allow_same_block_duplication_p (rtx ext_insn, rtx use_insn)
++{
++ rtx ext = PATTERN (ext_insn);
++ rtx use = PATTERN (use_insn);
++
++ if (GET_CODE (SET_SRC (use)) == ASHIFT && GET_CODE (SET_SRC (ext)) == ZERO_EXTEND)
++ return true;
++ return false;
++}
++
++/* Determine if the extension should be duplicated at this use point.
++ Return true if yes, false otherwise. */
++
++static bool
++save_ext_use_p (ext_record_t extrec, rtx use_insn)
++{
++ rtx ext_insn, ext, ext_dest, use = PATTERN (use_insn), use_src;
++ df_ref df_use;
++
++ ext_insn = extrec->ext;
++ ext = PATTERN (ext_insn);
++ ext_dest = SET_DEST (ext);
++
++ if (GET_CODE (use) != SET)
++ {
++ if (dump_file)
++ fprintf (dump_file, " no -- use is not a SET code\n");
++ return false;
++ }
++
++ /* Check for obviousness */
++ /* 1. The use is only reached by the a single definition of the extension.
++ Otherwise, it wouldn't be legal to insert a duplicate extension
++ as other defs reaching this use may not need it. Certainly not all
++ other defs may reach here, but this is the conservative approximation.
++ Found in nof/muldf3.c */
++ df_use = df_find_use (use_insn, ext_dest);
++ if ( df_use && DF_REF_CHAIN (df_use)->next)
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " no -- there are multiple definitions of reg=%d reaching this use\n",
++ (REGNO (register_exp (ext_dest))));
++ return false;
++ }
++
++ /* 2. The extension and use are in the same block. Since
++ this is a reached use, it's obvious we don't need another
++ extension. The exception is this -- we are trying to set
++ up a specific extension,insn pattern that will be recognized
++ by the insn selector. This pattern will also be ignored when
++ the next extension candidate list is created in the next pass. */
++ if (INSN_P (ext_insn) && INSN_P (use_insn))
++ {
++ if (BLOCK_FOR_INSN (ext_insn) == BLOCK_FOR_INSN (use_insn))
++ {
++ if (allow_same_block_duplication_p (ext_insn, use_insn))
++ ;
++ else
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " no -- ext and use are in the same block\n");
++ return false;
++ }
++ }
++ }
++
++ /* 3. The use is a sign extension of the extension destination reg */
++ use_src = SET_SRC (use);
++ if (GET_CODE (use_src) == SIGN_EXTEND
++ && REG_P (register_exp (XEXP (use_src, 0)))
++ && REG_P (register_exp (ext_dest)))
++ if (GET_MODE (use_src) == GET_MODE (ext_dest)
++ && REGNO (register_exp (XEXP (use_src, 0))) ==
++ REGNO (register_exp (ext_dest)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " no -- the use is a sign extension of reg=%d\n",
++ REGNO (register_exp (XEXP (use_src, 0))));
++ return false;
++ }
++
++ /* 4. The use already has an extension inserted and one of the use's operands
++ is a register matching the reaching definition. So don't reinsert the same
++ extension. */
++ if (insn_flag_p (EXTELIM_INSERTED_FOR, INSN_UID (use_insn)))
++ {
++ df_ref *p_df_uses;
++ /* Operands used by this the use_insn */
++ for (p_df_uses = DF_INSN_UID_USES (INSN_UID (use_insn)); *p_df_uses;
++ p_df_uses++)
++ {
++ if (REG_P (register_exp (ext_dest)) &&
++ DF_REF_REGNO (*p_df_uses) == REGNO (register_exp (ext_dest)))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " no -- this use is marked for sign extension insertion already\n");
++ return false;
++ }
++ }
++ }
++
++ /* 5. There is also a definition of the ext dest register at this use (as can occur in self assignment). */
++ if (register_exp (SET_DEST (use)) && REG_P (ext_dest)
++ && REGNO (register_exp (SET_DEST (use))) == REGNO (ext_dest))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ " no -- this use also assigns the used register\n");
++ return false;
++ }
++
++
++ if (dump_file)
++ fprintf (dump_file, " yes\n");
++ return true;
++}
++
++/* Save the use insn in the extension records list of
++ uses. At the next phase, we will duplicate the extension
++ at these use points. */
++
++static void
++save_ext_use (ext_record_t extrec, rtx use_insn)
++{
++ /* Mark the use insn, it will have a duplicate inserted */
++ insn_flag_set (EXTELIM_INSERTED_FOR, INSN_UID (use_insn));
++ /* Save use to the list of uses to be duplicated for this extension. */
++ VEC_safe_push (rtx, heap, extrec->ext_uses, use_insn);
++}
++
++
++/* Save the qualified use of an extension to a list */
++
++static void
++gather_ext_uses_info (ext_record_t extrec)
++{
++ rtx ext;
++ df_ref *ext_def, df_use;
++ unsigned int def_use_count = 1;
++ extelim_uid_t uid;
++ struct df_link *link;
++
++ gcc_assert (extrec != NULL);
++ ext = extrec->ext;
++ uid = INSN_UID (ext);
++
++ /* Insn level defs of the sign extension */
++ ext_def = DF_INSN_UID_DEFS (uid);
++ /* There is only one def in a sign extension insn */
++ gcc_assert (*(ext_def + 1) == NULL);
++
++ /* Iterate over the reached uses of extension destination register.
++ Duplicate the extension at the use point. */
++ for (link = DF_REF_CHAIN (*ext_def); link; link = link->next)
++ {
++ rtx insn_use;
++ df_use = link->ref;
++ if (!df_use)
++ continue;
++ /* Link must be a USE of the DEF */
++ if (!DF_REF_REG_USE_P (df_use))
++ continue;
++ /* Ignore ARTIFICIAL USES */
++ if (DF_REF_IS_ARTIFICIAL (df_use))
++ continue;
++ insn_use = DF_REF_INSN (df_use);
++
++ /* Don't consider debug_insns */
++ if (!NONDEBUG_INSN_P (insn_use))
++ continue;
++
++ if (dump_file)
++ fprintf (dump_file,
++ " use #%d duplicate ext of reg=%d at uid=%u?\n",
++ def_use_count, DF_REF_REGNO (*ext_def), INSN_UID (insn_use));
++ if (save_ext_use_p (extrec, insn_use))
++ save_ext_use (extrec, insn_use);
++ def_use_count++;
++ }
++}
++
++/* At each use point of the sign extension, unless the
++ use is obviously already sign extended, insert a
++ sign extension insn before the use. We do this in two
++ passes to avoid confusing the dataflow information. */
++
++static void
++duplicate_exts_at_uses (void)
++{
++ unsigned i, j;
++ ext_record_t extrec;
++ rtx use_insn;
++
++ /* Get the uses where the extensions will be duplicated */
++ FOR_EACH_VEC_ELT (ext_record_t, extensions, i, extrec)
++ {
++ if (dump_file)
++ fprintf (dump_file, "gathering extension uid=%u use information\n",
++ INSN_UID (extrec->ext));
++ gather_ext_uses_info (extrec);
++ }
++
++ /* Now duplicate the extensions at the appropriate use points */
++ FOR_EACH_VEC_ELT (ext_record_t, extensions, i, extrec)
++ {
++ if (dump_file)
++ fprintf (dump_file, "extension uid=%u\n", INSN_UID (extrec->ext));
++
++ FOR_EACH_VEC_ELT (rtx, extrec->ext_uses, j, use_insn)
++ {
++ if (dump_file)
++ fprintf (dump_file, " duplicated at use uid=%u\n",
++ INSN_UID (use_insn));
++ insert_duplicate_ext_at_use (extrec->ext, use_insn);
++ }
++ }
++}
++#endif /* EXTELIM_DUPLICATE_EXTS_AT_USES */
++
++/* Determine if an instruction is a return insn */
++
++static rtx
++return_p (rtx rtn_insn)
++{
++ rtx rtn = PATTERN (rtn_insn), dest;
++ int i;
++
++ if (GET_CODE (rtn) != SET)
++ return false;
++
++ dest = SET_DEST (rtn);
++
++ /* Is a return value? */
++ if ((REG_P (dest) || GET_CODE (dest) == PARALLEL) &&
++ REG_FUNCTION_VALUE_P (dest))
++ {
++ /* Simple SET, return the insn */
++ if (REG_P (dest))
++ return rtn_insn;
++ /* PARALLEL, find the embedded rtx */
++ if (GET_CODE (dest) == PARALLEL)
++ for (i = XVECLEN (rtn_insn, 0) - 1; i >= 0; i--)
++ {
++ rtx body = XVECEXP (rtn_insn, 0, i);
++ if (GET_CODE (body) == SET)
++ {
++ dest = SET_DEST (body);
++ if (REG_FUNCTION_VALUE_P (dest))
++ return body;
++ }
++ }
++ }
++ /* Not a return */
++ return NULL;
++}
++
++/* Find all return RTLs in the function and save them in
++ a list. */
++
++static bool
++find_returns (void)
++{
++ basic_block bb;
++ rtx insn, rtn_insn;
++ bool found = false;
++
++ /* For all insns */
++ FOR_EACH_BB (bb)
++ {
++ FOR_BB_INSNS (bb, insn)
++ {
++ if (!NONDEBUG_INSN_P (insn))
++ continue;
++
++ if ((rtn_insn = return_p (insn)) == NULL)
++ {
++ continue;
++ }
++ if (dump_file)
++ fprintf (dump_file, " found return at uid=%u\n", INSN_UID (rtn_insn));
++
++ VEC_safe_push (rtx, heap, returns, rtn_insn);
++ found = true;
++ }
++ }
++
++ return (found);
++}
++
++/* Get the signedness and machine mode of the function */
++
++static bool
++get_return_info (bool * signed_p, enum machine_mode *return_mode)
++{
++ tree rtninfo;
++
++ if ((rtninfo = DECL_RESULT (current_function_decl)) != NULL)
++ {
++ *signed_p = !TYPE_UNSIGNED (TREE_TYPE (rtninfo));
++ *return_mode = DECL_MODE (rtninfo);
++ return true;
++ }
++ return false;
++}
++
++/* If the dest mode of the return is larger than
++ the function return mode, we can subreg the return
++ insn to the return mode and extend to the destination.
++ E.g. unsigned, return mode: HImode
++ set (reg/i:DI Y) (reg:DI X)
++ becomes
++ set (reg:DI new) (zero_extend:DI (subreg:HI (reg:DI X)))
++ set (reg/i:DI Y) (reg:DI new) */
++
++static void
++make_ext_at_rtn (rtx rtn_insn, bool fun_signed_p, enum machine_mode fun_mode)
++{
++ rtx rtn = PATTERN (rtn_insn);
++ rtx dest, src, new_ext_dest, new_ext_src, new_ext_outer, new_ext_part,
++ new_ext_insn;
++ extelim_uid_t new_uid;
++ gcc_assert (GET_CODE (rtn) == SET);
++
++ dest = SET_DEST (rtn);
++ src = SET_SRC (rtn);
++
++ /* Deal with scalar rtn values only */
++ if (fun_mode != DImode
++ && fun_mode != SImode && fun_mode != HImode && fun_mode != QImode)
++ {
++ if (dump_file)
++ fprintf (dump_file, "failed-- not scalar return mode\n");
++ return;
++ }
++
++ /* Dest and src have to have the same mode. This should always be
++ true for well formed rtl, but we check anyway. */
++ if (GET_MODE (dest) != GET_MODE (src))
++ {
++ if (dump_file)
++ fprintf (dump_file, "failed-- dest and src modes differ\n");
++ return;
++ }
++
++ /* Also check that we are dealing with simple regs here. */
++ if (!REG_P (dest) || !REG_P (src))
++ {
++ if (dump_file)
++ fprintf (dump_file, "failed-- dest or src is not REG_P\n");
++ return;
++ }
++
++ /* The return reg mode should never be smaller than fun return mode. If the
++ same size, however, we can't subreg either, so return */
++ if (GET_MODE_BITSIZE (GET_MODE (dest)) <= GET_MODE_BITSIZE (fun_mode))
++ {
++ if (dump_file)
++ fprintf (dump_file,
++ "failed-- dest size mode is smaller or equal to function mode size\n");
++ return;
++ }
++
++ /* From here we should be able to build a subreg since the function return mode
++ size is smaller than the return register mode size */
++ new_ext_dest = gen_reg_rtx (GET_MODE (src)); /* set (reg:MM new) */
++ new_ext_src = copy_rtx (src); /* copy of X, copyX */
++ new_ext_outer = gen_lowpart_SUBREG (fun_mode, new_ext_src); /* subreg:mm (reg:MM copyX) */
++ new_ext_part = fun_signed_p /* extend:MM (subreg:mm (reg:MM copyX)) */
++ ? gen_rtx_SIGN_EXTEND (GET_MODE (src), new_ext_outer)
++ : gen_rtx_ZERO_EXTEND (GET_MODE (src), new_ext_outer);
++ /* Put it together */
++ new_ext_insn = gen_rtx_SET (VOIDmode, new_ext_dest, new_ext_part);
++
++ /* Modify src of return insn to use new pseudo */
++ replace_rtx (PATTERN (rtn_insn), src, new_ext_dest);
++ /* Update flags on new dest reg */
++ copy_flags (src, new_ext_dest);
++ /* Update any notes associated with replaced register */
++ update_notes (REG_DEAD, rtn_insn, src, new_ext_dest);
++ /* Rescan the modified insn */
++ df_insn_rescan (rtn_insn);
++ /* Insert the new insn */
++ new_uid = extelim_emit_before (new_ext_insn, rtn_insn);
++
++ if (dump_file)
++ fprintf (dump_file, "success\n");
++}
++
++/* Insert extensions at return points. Scan the RTL
++ for the return statements. Determine if the RTL
++ can be modified to insert an extension. Modify the
++ return to insert the extension. */
++
++static void
++insert_ext_at_returns (void)
++{
++ bool signed_p;
++ enum machine_mode return_mode;
++ rtx rtn_insn;
++ int i;
++
++ /* Generate list of return rtls for the function */
++ if (dump_file)
++ fprintf (dump_file, "gathering return insns...\n");
++
++ if (!find_returns ())
++ return;
++
++ if (!get_return_info (&signed_p, &return_mode))
++ return;
++
++ /* For each return instruction, generate a sign/zero extend
++ if the current return size is larger than the function
++ return mode. */
++ FOR_EACH_VEC_ELT (rtx, returns, i, rtn_insn)
++ {
++ if (dump_file)
++ fprintf (dump_file, " making extension at return uid=%u...",
++ INSN_UID (rtn_insn));
++ make_ext_at_rtn (rtn_insn, signed_p, return_mode);
++ }
++}
++
++/* Compare two extension records by loop depth.
++ Used by VEC_qsort to sort the order in which extensions
++ are processed. */
++
++static int
++ext_record_compare (const void *p_er1, const void *p_er2)
++{
++ const ext_record_t er1 = *(const ext_record_t *) p_er1;
++ const ext_record_t er2 = *(const ext_record_t *) p_er2;
++ basic_block bb1, bb2;
++ rtx ext1, ext2;
++
++ if (er1 == er2)
++ return 0;
++
++ ext1 = er1->ext;
++ ext2 = er2->ext;
++
++ bb1 = BLOCK_FOR_INSN (ext1);
++ bb2 = BLOCK_FOR_INSN (ext2);
++
++ /* Sort high to low */
++ return (bb2->loop_depth - bb1->loop_depth);
++}
++
++/* The main interface to this optimization. */
++
++static void
++extension_elimination (void)
++{
++ ext_record_t ext;
++ unsigned i;
++
++ init_pass ();
++
++ /* Find initial sign extension candidates */
++ if (!find_extensions ())
++ {
++ finish_pass ();
++ return;
++ }
++
++ /* Insert sign extension at return points in
++ the function. */
++ insert_ext_at_returns ();
++
++ /* Duplicate the sign extensions at their use
++ points unless the use is already obviously sign
++ extended or extension is already added. */
++#if EXTELIM_DUPLICATE_EXTS_AT_USES
++ duplicate_exts_at_uses ();
++#endif
++
++ /* Update DF information since now have new insns. */
++ df_finish_pass (true);
++ df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
++ df_analyze ();
++
++#if EXTELIM_DF_DUMP
++ if (dump_file)
++ df_dump (dump_file);
++#endif
++
++ /* Init statistics */
++ num_cand = 0;
++ num_cand_ignored = 0;
++ num_cand_transformed = 0;
++
++ /* Free old extensions list, generate new one that includes
++ the new extensions. */
++ free_extensions ();
++
++ if (!find_extensions ())
++ {
++ finish_pass ();
++ return;
++ }
++
++ if (dump_file)
++ {
++ fprintf (dump_file, "\nRTL After Extension Duplication\n");
++ print_rtl (dump_file, get_insns ());
++ }
++
++ if (dump_file)
++ fprintf (dump_file, "Begin extension elimination analysis\n");
++
++ /* Sort the extensions by loop depth. We want to try to eliminate
++ those in innermost loops (highest loop depth) first. */
++ VEC_qsort (ext_record_t, extensions, ext_record_compare);
++
++ /* Iterate through extension worklist */
++ FOR_EACH_VEC_ELT (ext_record_t, extensions, i, ext)
++ {
++ rtx ext_insn = ext->ext;
++ rtx ext_src = SET_SRC (PATTERN (ext_insn));
++ const char *ext_name =
++ GET_CODE (ext_src) == SIGN_EXTEND ? "sign" : "zero";
++ const char *inserted =
++ insn_flag_p (EXTELIM_INSERTED, INSN_UID (ext_insn)) ? "inserted" : "";
++ extelim_uid_t uid = INSN_UID (ext_insn);
++
++ if (dump_file)
++ fprintf (dump_file,
++ "<analyzing %s %s extension uid=%u> (loop_depth=%d)\n",
++ inserted, ext_name, uid,
++ BLOCK_FOR_INSN (ext_insn)->loop_depth);
++
++ current_ext_record = ext;
++ eliminate_one_extend (ext->ext);
++ }
++
++ if (dump_file)
++ fprintf (dump_file, "Begin extension elimination transformations\n");
++
++ replace_ext_with_copy ();
++
++ if (dump_file)
++ fprintf (dump_file, "\nRTL After Extension Elimination\n");
++
++ finish_pass ();
++
++ /* Print statistics */
++ if (dump_file)
++ {
++ fprintf (dump_file,
++ "Number of extensions ignored: %d (of %d candidiates)\nDETECTION EFFECTIVENESS: %f%%\n",
++ num_cand_ignored, num_cand,
++ ((float) (num_cand - num_cand_ignored) / (float) num_cand) *
++ 100);
++ fprintf (dump_file,
++ "Number of extensions converted to copy: %d (of %d candidiates)\nCONVERSION EFFECTIVENESS: %f%%\n",
++ num_cand_transformed, num_cand,
++ ((float) num_cand_transformed / (float) num_cand) * 100);
++ }
++}
++
++/* Remove redundant extensions. */
++
++static unsigned int
++rest_of_handle_extelim (void)
++{
++ extension_elimination ();
++ return 0;
++}
++
++/* Run extelim pass when flag_extelim is set at optimization level > 0. */
++
++static bool
++gate_handle_extelim (void)
++{
++ return (optimize > 0 && flag_extelim);
++}
++
++struct rtl_opt_pass pass_rtl_extelim = {
++ {
++ RTL_PASS,
++ "extelim", /* name */
++ gate_handle_extelim, /* gate */
++ rest_of_handle_extelim, /* execute */
++ NULL, /* sub */
++ NULL, /* next */
++ 0, /* static_pass_number */
++ TV_EXTELIM, /* tv_id */
++ 0, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ TODO_ggc_collect | TODO_dump_func | TODO_df_finish | TODO_verify_rtl_sharing, /* todo_flags_finish */
++ }
++};
--- /dev/null
+diff -Naur gcc-4.6.2/gcc/config/rs6000/sysv4.h gcc-4.6.2-MTWX51204-dwarf-vector-reg/gcc/config/rs6000/sysv4.h
+--- gcc-4.6.2/gcc/config/rs6000/sysv4.h 2011-03-07 01:50:23.000000000 -0600
++++ gcc-4.6.2-MTWX51204-dwarf-vector-reg/gcc/config/rs6000/sysv4.h 2011-12-16 09:44:18.469039002 -0600
+@@ -1035,5 +1035,3 @@
+
+ /* This target uses the sysv4.opt file. */
+ #define TARGET_USES_SYSV4_OPT 1
+-
+-#undef DBX_REGISTER_NUMBER
--- /dev/null
+--- gcc-4_6-branch/gcc/config/host-linux.c.orig 2012-03-08 02:18:57.282190580 -0600
++++ gcc-4_6-branch/gcc/config/host-linux.c 2012-03-08 02:19:30.930158694 -0600
+@@ -17,6 +17,8 @@
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
++#include <bits/posix1_lim.h>
++
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
--- /dev/null
+gcc.fix_build-with-cxx
+
+On native builds, when linking cc1 with static libraries (ppl cloog,
+gmp, mpfr), there is c++ code brought in by libppl. Normally cc1 is
+linked through "gcc", but in this case it should be linked with "g++".
+
+To work around this, gcc is configured with --enable-build-with-cxx,
+which compiles and links the entire compiler with g++. Since g++ is
+more rigorous about the use of the "const" keyword, there is a couple
+of places that we get syntax errors. This patch fixes them.
+
+--- gcc-4.6.0/gcc/config/rs6000/rs6000.c-orig 2011-05-09 10:35:55.627190744 -0500
++++ gcc-4.6.0/gcc/config/rs6000/rs6000.c 2011-05-09 10:39:09.232814653 -0500
+@@ -22502,11 +22502,12 @@
+ rs6000_xcoff_strip_dollar (const char *name)
+ {
+ char *strip, *p;
++ const char *q;
+ int len;
+
+- p = strchr (name, '$');
++ q = strchr (name, '$');
+
+- if (p == 0 || p == name)
++ if (q == 0 || q == name)
+ return name;
+
+ len = strlen (name);
+--- gcc-4.6.0/gcc/objc/objc-next-runtime-abi-02.c-orig 2011-05-11 13:46:44.559065173 -0500
++++ gcc-4.6.0/gcc/objc/objc-next-runtime-abi-02.c 2011-05-11 13:48:34.956939829 -0500
+@@ -1878,7 +1878,7 @@
+ static const char *
+ newabi_append_ro (const char *name)
+ {
+- char *dollar;
++ const char *dollar;
+ char *p;
+ static char string[BUFSIZE];
+ dollar = strchr (name, '$');
--- /dev/null
+gcc.fix_cloogstatic2
+
+When only static libraries are available (so we can build cc1 without
+depending on extras libraries), we get a bunch of undefined symbols
+that are defined in libpwl. This patch explicitly adds libpwl to the
+linker command.
+
+--- gcc-trunk/configure.orig 2011-03-10 12:48:29.433528020 -0600
++++ gcc-trunk/configure 2011-03-10 12:52:11.342145967 -0600
+@@ -5770,7 +5770,7 @@
+ LDFLAGS="$saved_LDFLAGS"
+ fi
+
+- ppllibs="$ppllibs -lppl_c -lppl $pwllib -lgmpxx"
++ ppllibs="$ppllibs -lppl_c -lppl -lpwl $pwllib -lgmpxx"
+
+ if test "$enable_ppl_version_check" != no; then
+ saved_CFLAGS="$CFLAGS"
--- /dev/null
+For altivec targets, 32 bits, the spec2k-gap bmk does not build. The
+reason is that at some point the vectorizer creates an CONST_VECTOR
+rtl, where the elements are SYMBOL_REFs.
+
+Gcc ICE on simplify_immed_subreg, where it checks that CONST_VECTORS
+can be only made of CONST_INT, CONST_DOUBLE, or CONST_FIXED.
+
+I really don't understand what that function does, but since the
+vectorizer will bailout later anyway, I think it is safe to treat
+SYMBOL_REFs as CONST_INT. (NOT for FSF submission, as I really don't
+have a clue)
+
+This problem does not exists on gcc-4.5
+
+This problem does not exists on 64 bits, since there is no altivec
+type that can support 64bit elements.
+
+Here is a simplified test case:
+
+typedef void f_t (void);
+extern f_t f;
+extern f_t *A[12];
+extern f_t *B[12];
+void bad_vector ()
+{
+ int i;
+
+ for (i = 0; i < 12; i++ ) {
+ A[i] = f;
+ B[i] = f;
+ }
+}
+
+--- gcc-4.6.2/gcc/simplify-rtx.c~ 2011-12-28 12:28:01.700039002 -0600
++++ gcc-4.6.2/gcc/simplify-rtx.c 2011-12-28 12:38:22.287039002 -0600
+@@ -5001,6 +5001,7 @@
+ switch (GET_CODE (el))
+ {
+ case CONST_INT:
++ case SYMBOL_REF:
+ for (i = 0;
+ i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
+ i += value_bit)
--- /dev/null
+--- gcc-4_6-branch/gcc/limitx.h.orig 2012-03-08 01:11:23.024440826 -0600
++++ gcc-4_6-branch/gcc/limitx.h 2012-03-08 01:13:44.372515706 -0600
+@@ -30,6 +30,7 @@
+ #define _GCC_LIMITS_H_
+
+ #ifndef _LIBC_LIMITS_H_
+-/* Use "..." so that we find syslimits.h only in this same directory. */
+-#include "syslimits.h"
++#define _GCC_NEXT_LIMITS_H /* tell gcc's limits.h to recurse */
++#include_next <limits.h>
++#undef _GCC_NEXT_LIMITS_H
+ #endif
--- /dev/null
+diff -Naur gcc-4.6.2/gcc/config/rs6000/rs6000.c gcc-4.6.2-loop_invariant/gcc/config/rs6000/rs6000.c
+--- gcc-4.6.2/gcc/config/rs6000/rs6000.c 2011-11-24 00:03:49.709144001 -0600
++++ gcc-4.6.2-loop_invariant/gcc/config/rs6000/rs6000.c 2011-12-12 23:49:27.901487730 -0600
+@@ -2723,7 +2723,7 @@
+ calculation works better for RTL loop invariant motion on targets
+ with enough (>= 32) registers. It is an expensive optimization.
+ So it is on only for peak performance. */
+- if (optimize >= 3 && global_init_p)
++ if (optimize >= 3 && global_init_p && !global_options_set.x_flag_ira_loop_pressure)
+ flag_ira_loop_pressure = 1;
+
+ /* Set the pointer size. */
--- /dev/null
+gcc.fix_longversionstring
+
+Freescale version string is really long, and it can overflow a
+buffer. This patch extends the size of the buffer.
+
+--- gcc-4.6.0/gcc/dwarf2out.c-orig 2011-03-18 11:22:01.000000000 -0500
++++ gcc-4.6.0/gcc/dwarf2out.c 2011-05-06 10:24:24.114277925 -0500
+@@ -20005,7 +20005,7 @@
+ gen_compile_unit_die (const char *filename)
+ {
+ dw_die_ref die;
+- char producer[250];
++ char producer[2500];
+ const char *language_string = lang_hooks.name;
+ int language;
+
--- /dev/null
+--- gcc-4.6.0/gcc/configure~ 2011-02-28 09:36:37.000000000 -0600
++++ gcc-4.6.0/gcc/configure 2011-06-28 10:07:22.430630818 -0500
+@@ -10898,7 +10898,7 @@
+ saved_CFLAGS="${CFLAGS}"
+ CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
+ LDFLAGS="${LDFLAGS_FOR_BUILD}" \
+- ${realsrcdir}/configure \
++ ${realsrcdir}/configure --with-gnu-ld --with-gnu-as --enable-targets=all \
+ --enable-languages=${enable_languages-all} \
+ --target=$target_alias --host=$build_alias --build=$build_alias
+ CFLAGS="${saved_CFLAGS}"
--- /dev/null
+gcc.ld_unaligned-460
+
+Optimization:
+Allows a "ld" of an address that is world aligned. There is a penalty
+performance, but it still beats a pair of "lwz".
+
+Index: gcc-4.4-e500mc64-20090322/gcc/config/rs6000/rs6000.c
+===================================================================
+--- gcc-4.4-e500mc64-20090322/gcc/config/rs6000/rs6000.c (revision 137727)
++++ gcc-4.4-e500mc64-20090322/gcc/config/rs6000/rs6000.c (working copy)
+@@ -10640,7 +10667,9 @@
+ else if (bytes >= 8 && TARGET_POWERPC64
+ /* 64-bit loads and stores require word-aligned
+ displacements. */
+- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
++ && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500))
+ {
+ clear_bytes = 8;
+ mode = DImode;
+@@ -10775,7 +10808,9 @@
+ else if (bytes >= 8 && TARGET_POWERPC64
+ /* 64-bit loads and stores require word-aligned
+ displacements. */
+- && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
++ && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)
++ || rs6000_cpu == PROCESSOR_PPCE5500
++ || rs6000_cpu == PROCESSOR_PPCE6500))
+ {
+ move_bytes = 8;
+ mode = DImode;
--- /dev/null
+
+ This patch implements option -fbypass-load-on-store
+
+ A load on store collision causes the load to to be replayed if the store has not completed.
+ Under -fbypass-load-on-store, GCC will attempt to avoid a load on store collision by trying
+ to space the load away from the store by scheduling upto 14 instructions in between, to
+ prevent the load from executing too early.
+
+ -fbypass-load-on-store is enabled under -fschedule-insns
+
+ Cores supported: e5500, e6500, e500mc
+
+ Ref: Load-on-Store Collision Avoidance by Software Stall of Load. James Yang. May 18, 2010
+
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/common.opt fsl-gcc-4.6.2-new-bypass/gcc/common.opt
+--- fsl-gcc-4.6.2-sans-bypass/gcc/common.opt 2011-11-29 11:10:18.967872292 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/common.opt 2011-11-29 14:02:46.765994436 -0600
+@@ -840,6 +840,10 @@
+ Common Report Var(flag_btr_bb_exclusive) Optimization
+ Restrict target load migration not to re-use registers in any basic block
+
++fbypass-load-on-store
++Common Report Var(flag_bypass_load_on_store) Optimization
++Bypass load on store collision
++
+ fcall-saved-
+ Common Joined RejectNegative Var(common_deferred_options) Defer
+ -fcall-saved-<register> Mark <register> as being preserved across functions
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e500mc64.md fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e500mc64.md
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e500mc64.md 2011-11-29 11:11:38.454868780 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e500mc64.md 2011-11-29 17:10:39.849869060 -0600
+@@ -189,3 +189,5 @@
+ (and (eq_attr "type" "ddiv")
+ (eq_attr "cpu" "ppce500mc64"))
+ "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*34")
++
++(define_bypass 15 "e500mc64_store" "e500mc64_load" "rs6000_bypass_load_on_store_collision_p")
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e500mc.md fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e500mc.md
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e500mc.md 2011-11-29 11:11:38.479869032 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e500mc.md 2011-11-29 17:10:27.810997020 -0600
+@@ -198,3 +198,5 @@
+ (and (eq_attr "type" "ddiv")
+ (eq_attr "cpu" "ppce500mc"))
+ "e500mc_decode,e500mc_issue+e500mc_fpu,e500mc_fpu*65")
++
++(define_bypass 15 "e500mc_store" "e500mc_load" "rs6000_bypass_load_on_store_collision_p")
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e5500.md fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e5500.md
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e5500.md 2011-11-29 11:11:38.321744639 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e5500.md 2011-11-29 17:10:47.255997293 -0600
+@@ -174,3 +174,5 @@
+ (and (eq_attr "type" "cr_logical,delayed_cr")
+ (eq_attr "cpu" "ppce5500"))
+ "e5500_decode,e5500_bu")
++
++(define_bypass 15 "e5500_store" "e5500_load" "rs6000_bypass_load_on_store_collision_p")
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e6500.md fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e6500.md
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/e6500.md 2011-11-29 11:11:37.831996567 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/e6500.md 2011-11-29 17:11:00.902869709 -0600
+@@ -211,3 +211,5 @@
+ (and (eq_attr "type" "vecperm")
+ (eq_attr "cpu" "ppce6500"))
+ "e6500_decode,e6500_vecperm")
++
++(define_bypass 15 "e6500_store" "e6500_load" "rs6000_bypass_load_on_store_collision_p")
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/rs6000.c fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/rs6000.c
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/rs6000.c 2011-11-29 11:11:38.393748363 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/rs6000.c 2011-11-29 17:10:15.740745470 -0600
+@@ -28719,3 +28719,20 @@
+
+
+ #include "gt-rs6000.h"
++
++bool
++rs6000_bypass_load_on_store_collision_p (rtx out_insn, rtx in_insn)
++{
++ /* The out_insn is a store and the in_insn is a load */
++ if (flag_bypass_load_on_store &&
++ (GET_CODE (PATTERN (out_insn)) == SET &&
++ GET_CODE (SET_DEST (PATTERN (out_insn))) == MEM &&
++ GET_CODE (SET_SRC (PATTERN (out_insn))) == REG) &&
++ (GET_CODE (PATTERN (in_insn)) == SET &&
++ GET_CODE (SET_DEST (PATTERN (in_insn))) == REG &&
++ GET_CODE (SET_SRC (PATTERN (in_insn))) == MEM))
++ return rtx_equal_p (SET_DEST (PATTERN (out_insn)),
++ SET_SRC (PATTERN (in_insn)));
++ else
++ return false;
++}
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/rs6000-protos.h fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/rs6000-protos.h
+--- fsl-gcc-4.6.2-sans-bypass/gcc/config/rs6000/rs6000-protos.h 2011-11-29 11:11:37.783996630 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/config/rs6000/rs6000-protos.h 2011-11-29 17:42:51.443119385 -0600
+@@ -174,6 +174,8 @@
+
+ extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
+
++extern bool rs6000_bypass_load_on_store_collision_p (rtx out_insn, rtx in_insn);
++
+ /* Declare functions in rs6000-c.c */
+
+ extern void rs6000_pragma_longcall (struct cpp_reader *);
+diff -ruN fsl-gcc-4.6.2-sans-bypass/gcc/testsuite/gcc.target/powerpc/bypass-load-on-store.c fsl-gcc-4.6.2-new-bypass/gcc/testsuite/gcc.target/powerpc/bypass-load-on-store.c
+--- fsl-gcc-4.6.2-sans-bypass/gcc/testsuite/gcc.target/powerpc/bypass-load-on-store.c 1969-12-31 18:00:00.000000000 -0600
++++ fsl-gcc-4.6.2-new-bypass/gcc/testsuite/gcc.target/powerpc/bypass-load-on-store.c 2011-11-30 16:36:55.168869498 -0600
+@@ -0,0 +1,34 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-options "-O0 -fschedule-insns -fbypass-load-on-store -fdump-rtl-sched1 -fsched-verbose=2" } */
++
++void nescaf(void)
++{
++ long a, b, c, d,
++ e, f, g, h,
++ i, j, k, l,
++ m, n, o, p,
++ q, r, s, t,
++
++ z, w;
++
++ a = 41; b = 79; c = 20; d = 11;
++ e = 13; f = 43; g = 13; h = 21;
++ i = 12; j = 45; k = 55; l = 90;
++ m = 23; n = 61; o = 89; p = 53;
++ q = 83; r = 52; s = 76; t = 99;
++
++ /* Now, we have a store followed by a load. The assignments to a-t are
++ * all independent of the store-load computation below. The question is:
++ * Under -fschedule-insns -fbypass-load-on-store, are 14 of the above
++ * instructions moved between the store-load?
++ */
++ z = 121;
++ w = z;
++}
++
++/* Note: There is going to be exactly one insn that will be assigned cost 15.
++ * Since its insn-number will likely change, we do not include the insn
++ * number in the scan - just the part of the dump that'll be invariant.
++ */
++/* { dg-final { scan-rtl-dump "into queue with cost=15" "sched1" { target powerpc*-*-* } } } */
++/* { dg-final { cleanup-rtl-dump "sched1" } } */
--- /dev/null
+gcc.local_unaligned_altivec
+
+Optimization:
+On Altivec targets, make all char arrays 128 bits aligned (instead of
+32 bits aligned)
+
+--- gcc-4.5.0/gcc/config/rs6000/rs6000.h-orig 2010-10-20 10:23:52.000000000 -0500
++++ gcc-4.5.0/gcc/config/rs6000/rs6000.h 2010-10-20 10:39:14.000000000 -0500
+@@ -768,7 +768,8 @@
+ ? 64 \
+ : (TREE_CODE (TYPE) == ARRAY_TYPE \
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
+- && (ALIGN) < BITS_PER_WORD) ? BITS_PER_WORD : (ALIGN)))
++ && (ALIGN) < (TARGET_ALTIVEC ? 128 : BITS_PER_WORD)) \
++ ? (TARGET_ALTIVEC ? 128 : BITS_PER_WORD) : (ALIGN)))
+
+ /* Nonzero if move instructions will actually fail to work
+ when given unaligned data. */
--- /dev/null
+Implements a GIMPLE pass to optimize array access by factoring
+out expressions that calculate address offset from
+multiple array access. Controls with flag -fopt-array-offset
+
+diff -ruN XLMe500mc/gcc/common.opt XLMe5500/gcc/common.opt
+--- XLMe500mc/gcc/common.opt 2011-10-18 14:49:23.026644000 -0500
++++ XLMe5500/gcc/common.opt 2011-10-05 12:39:26.242644101 -0500
+@@ -1992,6 +1992,10 @@
+ Common Report Var(flag_tree_vrp) Init(0) Optimization
+ Perform Value Range Propagation on trees
+
++fopt-array-offset
++Common Report Var(flag_opt_array_offset)
++Expand array offset address calculations
++
+ funit-at-a-time
+ Common Report Var(flag_unit_at_a_time) Init(1) Optimization
+ Compile whole compilation unit at a time
+diff -ruN XLMe500mc/gcc/Makefile.in XLMe5500/gcc/Makefile.in
+--- XLMe500mc/gcc/Makefile.in 2011-10-18 14:49:23.028644000 -0500
++++ XLMe5500/gcc/Makefile.in 2011-10-05 12:08:28.104643898 -0500
+@@ -1306,6 +1306,7 @@
+ omp-low.o \
+ optabs.o \
+ options.o \
++ opt-array-offset.o \
+ opts-common.o \
+ opts-global.o \
+ opts.o \
+@@ -2629,7 +2630,10 @@
+ $(FLAGS_H) $(CGRAPH_H) $(PLUGIN_H) \
+ $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
+ $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H) $(REGSET_H)
+-
++opt-array-offset.o : opt-array-offset.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
++ $(TM_H) $(FLAGS_H) $(TREE_H) $(TREE_FLOW_H) $(TIMEVAR_H) \
++ $(TREE_PASS_H) alloc-pool.h $(BASIC_BLOCK_H) $(TARGET_H) \
++ $(DIAGNOSTIC_H) gimple-pretty-print.h tree-pretty-print.h
+ widen-types.o : widen-types.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
+ $(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \
+ $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
+diff -ruN XLMe500mc/gcc/opt-array-offset.c XLMe5500/gcc/opt-array-offset.c
+--- XLMe500mc/gcc/opt-array-offset.c 1969-12-31 18:00:00.000000000 -0600
++++ XLMe5500/gcc/opt-array-offset.c 2011-11-01 15:24:21.746039000 -0500
+@@ -0,0 +1,283 @@
++/* Optimizing array element access
++ Copyright (C) 2011
++ Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it
++under the terms of the GNU General Public License as published by the
++Free Software Foundation; either version 3, or (at your option) any
++later version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT
++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++
++/* This is a GIMPLE pass over basic block which coverts the stmts:
++
++ a = b +/- c1;
++ c = a * c2;
++
++ to:
++
++ a = b * c2;
++ c = a +/- c1 * c2;
++
++ in effect expanding the multiplication across addition/substraction.
++
++ Motivating example:
++ Consider the following simple integer array access:
++
++ a[i] = c;
++ a[i + 1] = c;
++
++ The following GIMPLE equivalent will be generated:
++
++ off_1 = i * 4;
++ a_i = a + off_1;
++ *a_i = c;
++
++ off_1 = i + 1;
++ off_2 = off_1 * 4;
++ a_i1 = a + off_2;
++ *a_i1 = c;
++
++ Notice that a_i1 could simply be a_i + 4. But the calcuation of i+1
++ is preventing CSE to perform. This pass will essentially convert the
++ second expr into:
++
++ off_1 = i * 4;
++ off_2 = off_1 + 4;
++ a_i1 = a + off_2;
++ ....
++
++ Thus allowing the previous index i calculation to be reuse. off_1 + 4
++ would also be combined into a_i if offset addressing mode is available.
++ This also have side effect of avoiding redundant sign extension on
++ i+1 for LP64 model where native integer size is different from pointer size.
++
++ The algorithm iterates through all the basic blocks looking for
++ the above pattern. Care is taken to make sure off_1 only
++ has the single use otherwise the transformation cannot be perform.
++*/
++
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "flags.h"
++#include "tree.h"
++#include "tree-flow.h"
++#include "timevar.h"
++#include "tree-pass.h"
++#include "alloc-pool.h"
++#include "basic-block.h"
++#include "target.h"
++#include "gimple-pretty-print.h"
++#include "tree-pretty-print.h"
++
++
++/*
++ We are looking for:
++ a = b +/- c1
++ c = a * c2 (stmt incoming)
++ d = &arr + c
++*/
++static bool
++is_candidate (gimple stmt)
++{
++ tree mul_result = gimple_get_lhs (stmt);
++ tree rhs1, rhs2;
++ gimple rhs1_stmt, use_stmt;
++ use_operand_p use_p;
++ imm_use_iterator imm_iter;
++
++ /* check for a * c2 */
++ if (gimple_assign_rhs_code (stmt) != MULT_EXPR)
++ return false;
++
++ rhs1 = gimple_assign_rhs1 (stmt);
++ rhs2 = gimple_assign_rhs2 (stmt);
++
++ if (TREE_CODE (rhs2) != INTEGER_CST)
++ return false;
++
++ /* check for b + c1 */
++ if (TREE_CODE (rhs1) == SSA_NAME)
++ {
++ rhs1_stmt = SSA_NAME_DEF_STMT (rhs1);
++ if (is_gimple_assign (rhs1_stmt))
++ {
++ tree rhs1_2;
++ tree plusminus_result;
++
++ if (gimple_assign_rhs_code (rhs1_stmt) != PLUS_EXPR
++ && gimple_assign_rhs_code (rhs1_stmt) != MINUS_EXPR)
++ return false;
++
++ rhs1_2 = gimple_assign_rhs2 (rhs1_stmt);
++ if (TREE_CODE (rhs1_2) != INTEGER_CST)
++ return false;
++
++ /* make sure there are no other uses of a
++ e.g. if a is used as an indcution variable
++ we cannot modified it
++ */
++ plusminus_result = gimple_get_lhs (rhs1_stmt);
++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, plusminus_result)
++ {
++ use_stmt = USE_STMT (use_p);
++
++ /* ignore PHI node */
++ if (is_gimple_assign (use_stmt) &&
++ (gimple_assign_rhs_code (use_stmt) == GIMPLE_PHI))
++ continue;
++ if (use_stmt != stmt)
++ return false;
++ }
++
++#if 0
++ if (gimple_bb(rhs1_stmt) != gimple_bb(stmt))
++ return false;
++#endif
++ }
++ else
++ return false;
++ }
++ else
++ return false;
++
++ /* now look for uses of c that is a pointer use */
++ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, mul_result)
++ {
++ enum tree_code use_code;
++
++ use_stmt = USE_STMT (use_p);
++
++ if (is_gimple_debug (use_stmt))
++ continue;
++
++ if (gimple_bb (use_stmt) != gimple_bb (stmt))
++ return false;
++
++ if (!is_gimple_assign (use_stmt))
++ return false;
++
++ use_code = gimple_assign_rhs_code (use_stmt);
++ if (use_code != POINTER_PLUS_EXPR)
++ return false;
++ }
++
++ if (dump_file)
++ {
++ fprintf (dump_file, "Found candidate:\n");
++ print_gimple_stmt (dump_file, rhs1_stmt, 0, TDF_SLIM);
++ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
++ print_gimple_stmt (dump_file, use_stmt, 0, TDF_SLIM);
++ }
++
++ return true;
++}
++
++/* Do the actual transformation:
++ a = b + c1 ==> a = b * c2
++ c = a * c2 ==> c = a + c1*c2
++*/
++static bool
++expand_plusminus_mult (gimple stmt)
++{
++ tree c1, c2, mul_result;
++ gimple rhs1_stmt;
++
++ /* get c2 */
++ c2 = gimple_assign_rhs2 (stmt);
++
++ /* get c1 */
++ rhs1_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
++ c1 = gimple_assign_rhs2 (rhs1_stmt);
++
++ /* form c1 * c2 */
++ mul_result = double_int_to_tree (TREE_TYPE(c2), double_int_mul
++ (tree_to_double_int (c1), tree_to_double_int (c2)));
++
++ /* a = b + c1 ==> a = b * c2 */
++ gimple_assign_set_rhs2 (rhs1_stmt, c2);
++ gimple_assign_set_rhs_code (rhs1_stmt, MULT_EXPR);
++ update_stmt (rhs1_stmt);
++
++ /* c = a * c2 ==> c = a + c1*c2 */
++ gimple_assign_set_rhs2 (stmt, mul_result);
++ /* MINUS_EXPR has already been embedded into c1*c2 */
++ gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
++ update_stmt (stmt);
++
++ return true;
++}
++
++
++static unsigned int
++execute_opt_array_offset (void)
++{
++ basic_block bb;
++ tree fndecl;
++
++ FOR_EACH_BB (bb)
++ {
++ gimple_stmt_iterator gsi;
++
++ for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next(&gsi))
++ {
++ gimple stmt = gsi_stmt (gsi);
++ tree lhs,rhs1,rhs2,rhs3;
++ enum tree_code code;
++
++ /* only interested in assign statement */
++ if (is_gimple_assign (stmt))
++ {
++ /* find stmts calculating array offset */
++ if (is_candidate (stmt))
++ /* convert stmt */
++ expand_plusminus_mult(stmt);
++
++ }
++ }
++ }
++
++ return 0;
++}
++
++static bool
++gate_opt_array_offset (void)
++{
++ return flag_opt_array_offset && optimize;
++}
++
++struct gimple_opt_pass pass_opt_array_offset =
++{
++ {
++ GIMPLE_PASS,
++ "opt_array_offset", /* name */
++ gate_opt_array_offset, /* gate */
++ execute_opt_array_offset, /* execute */
++ NULL, /* sub */
++ NULL, /* next */
++ 0, /* static_pass_number */
++ TV_NONE, /* tv_id */
++ PROP_ssa, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ TODO_verify_ssa
++ | TODO_verify_stmts
++ | TODO_update_ssa
++ | TODO_dump_func /* todo_flags_finish */
++ }
++};
++
+diff -ruN XLMe500mc/gcc/passes.c XLMe5500/gcc/passes.c
+--- XLMe500mc/gcc/passes.c 2011-10-18 14:49:23.029644000 -0500
++++ XLMe5500/gcc/passes.c 2011-10-05 11:19:01.168644127 -0500
+@@ -937,6 +937,7 @@
+ NEXT_PASS (pass_phiopt);
+ NEXT_PASS (pass_fold_builtins);
+ NEXT_PASS (pass_optimize_widening_mul);
++ NEXT_PASS (pass_opt_array_offset);
+ NEXT_PASS (pass_tail_calls);
+ NEXT_PASS (pass_rename_ssa_copies);
+ NEXT_PASS (pass_uncprop);
+diff -ruN XLMe500mc/gcc/tree-pass.h XLMe5500/gcc/tree-pass.h
+--- XLMe500mc/gcc/tree-pass.h 2011-10-18 14:49:23.029644000 -0500
++++ XLMe5500/gcc/tree-pass.h 2011-10-05 11:19:59.665643705 -0500
+@@ -421,6 +421,7 @@
+ extern struct gimple_opt_pass pass_cse_sincos;
+ extern struct gimple_opt_pass pass_optimize_bswap;
+ extern struct gimple_opt_pass pass_optimize_widening_mul;
++extern struct gimple_opt_pass pass_opt_array_offset;
+ extern struct gimple_opt_pass pass_warn_function_return;
+ extern struct gimple_opt_pass pass_warn_function_noreturn;
+ extern struct gimple_opt_pass pass_cselim;
--- /dev/null
+--- gcc-4_6-branch/gcc/extelim.c.orig 2012-03-05 21:42:53.984215949 -0600
++++ gcc-4_6-branch/gcc/extelim.c 2012-03-05 21:43:27.884394659 -0600
+@@ -922,8 +922,7 @@
+ && GET_MODE (exp) != HImode
+ && GET_MODE (exp) != SImode
+ && GET_MODE (exp) != DImode
+- && GET_MODE (exp) != CCmode
+- && GET_MODE (exp) != CCUNSmode)
++ && GET_MODE (exp) != CCmode)
+ return false;
+
+ return true;
+@@ -1653,9 +1652,9 @@
+ For our targets, there is no 'cmph' insn, so we bail out
+ if we see a comparison of sizes less than a word (SI). */
+ if (REG_P (dest)
+- && (GET_MODE (dest) == CCmode || GET_MODE (dest) == CCUNSmode)
++ && (GET_MODE (dest) == CCmode)
+ && GET_CODE (src) == COMPARE
+- && (GET_MODE (src) == CCmode || GET_MODE (src) == CCUNSmode))
++ && (GET_MODE (src) == CCmode))
+ {
+ rtx compare_op0 = XEXP (src, 0);
+ rtx compare_op1 = XEXP (src, 1);
--- /dev/null
+diff -urN gcc-4.6.0/gcc/testsuite/gfortran.dg/cray_pointers_8.f90 gcc-4.6.0-fixed/gcc/testsuite/gfortran.dg/cray_pointers_8.f90
+--- gcc-4.6.0/gcc/testsuite/gfortran.dg/cray_pointers_8.f90 2009-02-13 15:12:34.000000000 -0600
++++ gcc-4.6.0-fixed/gcc/testsuite/gfortran.dg/cray_pointers_8.f90 1969-12-31 18:00:00.000000000 -0600
+@@ -1,63 +0,0 @@
+-! { dg-do run }
+-! { dg-options "-fcray-pointer" }
+-!
+-! Test the fix for PR36528 in which the Cray pointer was not passed
+-! correctly to 'euler' so that an undefined reference to fcn was
+-! generated by the linker.
+-!
+-! Reported by Tobias Burnus <burnus@gcc.gnu.org>
+-! from http://groups.google.com/group/comp.lang.fortran/msg/86b65bad78e6af78
+-!
+-real function p1(x)
+- real, intent(in) :: x
+- p1 = x
+-end
+-
+-real function euler(xp,xk,dx,f)
+- real, intent(in) :: xp, xk, dx
+- interface
+- real function f(x)
+- real, intent(in) :: x
+- end function
+- end interface
+- real x, y
+- y = 0.0
+- x = xp
+- do while (x .le. xk)
+- y = y + f(x)*dx
+- x = x + dx
+- end do
+- euler = y
+-end
+-program main
+- interface
+- real function p1 (x)
+- real, intent(in) :: x
+- end function
+- real function fcn (x)
+- real, intent(in) :: x
+- end function
+- real function euler (xp,xk,dx,f)
+- real, intent(in) :: xp, xk ,dx
+- interface
+- real function f(x)
+- real, intent(in) :: x
+- end function
+- end interface
+- end function
+- end interface
+- real x, xp, xk, dx, y, z
+- pointer (pfcn, fcn)
+- pfcn = loc(p1)
+- xp = 0.0
+- xk = 1.0
+- dx = 0.0005
+- y = 0.0
+- x = xp
+- do while (x .le. xk)
+- y = y + fcn(x)*dx
+- x = x + dx
+- end do
+- z = euler(0.0,1.0,0.0005,fcn)
+- if (abs (y - z) .gt. 1e-6) call abort
+-end
--- /dev/null
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_data_map_rand.cc 2011-05-11 20:03:39.000000000 -0500
+@@ -46,17 +46,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_no_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_no_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_no_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/hash_no_data_map_rand.cc 2011-05-11 20:04:00.000000000 -0500
+@@ -46,17 +46,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_data_map_rand.cc 2011-05-11 20:02:23.000000000 -0500
+@@ -47,7 +47,7 @@
+ using namespace __gnu_pbds::test;
+ typedef lu_map_tl_t map_tl_t;
+
+- return rand_regression_test(50, 10,
++ return rand_regression_test(2, 5,
+ "lu_data_map_rand_regression_test",
+ map_tl_t());
+ }
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_no_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_no_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_no_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/list_update_no_data_map_rand.cc 2011-05-11 20:02:23.000000000 -0500
+@@ -47,7 +47,7 @@
+ using namespace __gnu_pbds::test;
+ typedef lu_set_tl_t map_tl_t;
+
+- return rand_regression_test(50, 10,
++ return rand_regression_test(2, 5,
+ "lu_no_data_map_rand_regression_test",
+ map_tl_t());
+ }
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queue_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queue_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queue_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/priority_queue_rand.cc 2011-05-11 20:02:23.000000000 -0500
+@@ -45,10 +45,10 @@
+ #include <regression/common_type.hpp>
+
+ #ifndef ITERATIONS
+-#define ITERATIONS 5000
++#define ITERATIONS 2
+ #endif
+ #ifndef KEYS
+-#define KEYS 10000
++#define KEYS 5
+ #endif
+ int
+ main(int argc, char* a_p_argv[])
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_data_map_rand.cc 2011-05-11 20:04:21.000000000 -0500
+@@ -46,17 +46,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_no_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_no_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_no_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/tree_no_data_map_rand.cc 2011-05-11 20:04:41.000000000 -0500
+@@ -47,17 +47,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_data_map_rand.cc 2011-05-11 20:05:34.000000000 -0500
+@@ -46,17 +46,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
+diff -u gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_no_data_map_rand.cc gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_no_data_map_rand.cc
+--- gcc-4.6.0-orig/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_no_data_map_rand.cc 2011-05-11 20:01:58.000000000 -0500
++++ gcc-4.6.0/libstdc++-v3/testsuite/ext/pb_ds/regression/trie_no_data_map_rand.cc 2011-05-11 20:05:50.000000000 -0500
+@@ -46,17 +46,17 @@
+
+ #ifndef ITERATIONS
+ # ifdef _GLIBCXX_DEBUG
+-# define ITERATIONS 100
++# define ITERATIONS 2
+ # else
+-# define ITERATIONS 5000
++# define ITERATIONS 2
+ #endif
+ #endif
+
+ #ifndef KEYS
+ # ifdef _GLIBCXX_DEBUG
+-# define KEYS 200
++# define KEYS 5
+ # else
+-# define KEYS 10000
++# define KEYS 5
+ # endif
+ #endif
+
--- /dev/null
+diff -ruN gcc-4.6.0-orig/gcc/common.opt gcc-4.6.0-new/gcc/common.opt
+--- gcc-4.6.0-orig/gcc/common.opt 2011-03-05 18:38:13.000000000 -0600
++++ gcc-4.6.0-new/gcc/common.opt 2011-08-25 13:16:36.408937475 -0500
+@@ -1797,6 +1797,10 @@
+ Common Report Var(flag_strict_overflow)
+ Treat signed overflow as undefined
+
++fwiden-types
++Common Report Var(flag_widen_types)
++Widen signed integral variables (local, whose address has not been taken, non-volatile and having precision less than that of long) to long (retaining original qualifiers)
++
+ fsyntax-only
+ Common Report Var(flag_syntax_only)
+ Check for syntax errors, then stop
+diff -ruN gcc-4.6.0-orig/gcc/Makefile.in gcc-4.6.0-new/gcc/Makefile.in
+--- gcc-4.6.0-orig/gcc/Makefile.in 2011-01-25 22:19:58.000000000 -0600
++++ gcc-4.6.0-new/gcc/Makefile.in 2011-08-25 13:16:36.411937390 -0500
+@@ -1245,6 +1245,7 @@
+ gimple-fold.o \
+ gimple-low.o \
+ gimple-pretty-print.o \
++ widen-types.o \
+ gimplify.o \
+ godump.o \
+ graph.o \
+@@ -2628,6 +2629,12 @@
+ $(TREE_INLINE_H) tree-mudflap.h $(GGC_H) graph.h $(CGRAPH_H) \
+ $(TREE_PASS_H) $(CFGLOOP_H) $(EXCEPT_H) $(REGSET_H)
+
++widen-types.o : widen-types.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
++ $(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \
++ $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
++ coretypes.h $(EXCEPT_H) $(FLAGS_H) $(RTL_H) $(FUNCTION_H) $(EXPR_H) output.h \
++ $(GGC_H) gt-gimplify.h $(HASHTAB_H) $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(OPTABS_H) \
++ $(SPLAY_TREE_H) $(VEC_H) tree-iterator.h tree-pass.h tree-pretty-print.h
+ gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(GIMPLE_H) \
+ $(DIAGNOSTIC_H) $(GIMPLE_H) $(TREE_INLINE_H) langhooks.h \
+ $(LANGHOOKS_DEF_H) $(TREE_FLOW_H) $(CGRAPH_H) $(TIMEVAR_H) $(TM_H) \
+@@ -3733,6 +3740,7 @@
+ $(srcdir)/tree-cfg.c \
+ $(srcdir)/tree-dfa.c \
+ $(srcdir)/tree-iterator.c $(srcdir)/gimplify.c \
++ $(srcdir)/widen-types.c \
+ $(srcdir)/tree-chrec.h \
+ $(srcdir)/tree-scalar-evolution.c \
+ $(srcdir)/tree-ssa-operands.h \
+diff -ruN gcc-4.6.0-orig/gcc/passes.c gcc-4.6.0-new/gcc/passes.c
+--- gcc-4.6.0-orig/gcc/passes.c 2011-02-17 10:18:24.000000000 -0600
++++ gcc-4.6.0-new/gcc/passes.c 2011-08-25 13:16:36.413937342 -0500
+@@ -719,6 +719,7 @@
+ backend might produce already lowered functions that are not processed
+ by these passes. */
+ p = &all_lowering_passes;
++ NEXT_PASS (pass_widen_types_stmts);
+ NEXT_PASS (pass_warn_unused_result);
+ NEXT_PASS (pass_diagnose_omp_blocks);
+ NEXT_PASS (pass_mudflap_1);
+@@ -741,6 +742,7 @@
+ NEXT_PASS (pass_fixup_cfg);
+ NEXT_PASS (pass_init_datastructures);
+ NEXT_PASS (pass_expand_omp);
++ NEXT_PASS (pass_widen_types_bbs);
+
+ NEXT_PASS (pass_referenced_vars);
+ NEXT_PASS (pass_build_ssa);
+diff -ruN gcc-4.6.0-orig/gcc/tree-pass.h gcc-4.6.0-new/gcc/tree-pass.h
+--- gcc-4.6.0-orig/gcc/tree-pass.h 2011-02-01 09:12:26.000000000 -0600
++++ gcc-4.6.0-new/gcc/tree-pass.h 2011-08-25 13:16:36.406937543 -0500
+@@ -349,6 +349,7 @@
+
+ extern void tree_lowering_passes (tree decl);
+
++extern struct gimple_opt_pass pass_widen_types_stmts;
+ extern struct gimple_opt_pass pass_mudflap_1;
+ extern struct gimple_opt_pass pass_mudflap_2;
+ extern struct gimple_opt_pass pass_lower_cf;
+@@ -409,6 +410,7 @@
+ extern struct gimple_opt_pass pass_lower_omp;
+ extern struct gimple_opt_pass pass_diagnose_omp_blocks;
+ extern struct gimple_opt_pass pass_expand_omp;
++extern struct gimple_opt_pass pass_widen_types_bbs;
+ extern struct gimple_opt_pass pass_expand_omp_ssa;
+ extern struct gimple_opt_pass pass_object_sizes;
+ extern struct gimple_opt_pass pass_fold_builtins;
+diff -ruN gcc-4.6.0-orig/gcc/widen-types.c gcc-4.6.0-new/gcc/widen-types.c
+--- gcc-4.6.0-orig/gcc/widen-types.c 1969-12-31 18:00:00.000000000 -0600
++++ gcc-4.6.0-new/gcc/widen-types.c 2011-08-25 17:27:31.372937392 -0500
+@@ -0,0 +1,1446 @@
++/*
++ Type Widening:
++
++ Locals and temporaries having signed integral types, whose address has
++ not been taken, are not volatile qualified, and having type precision
++ less than that of type long are widened to type long (with any other
++ qualifiers retained).
++
++ Copyright (C) 2011
++ Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "tree.h"
++#include "tm_p.h"
++#include "gimple.h"
++#include "basic-block.h"
++#include "tree-iterator.h"
++#include "tree-inline.h"
++#include "langhooks.h"
++#include "tree-pretty-print.h"
++#include "gimple-pretty-print.h"
++#include "langhooks.h"
++#include "tree-flow.h"
++#include "cgraph.h"
++#include "timevar.h"
++#include "hashtab.h"
++#include "flags.h"
++#include "function.h"
++#include "output.h"
++#include "ggc.h"
++#include "tree-dump.h"
++#include "tree-pass.h"
++#include "diagnostic-core.h"
++#include "target.h"
++#include "pointer-set.h"
++#include "splay-tree.h"
++#include "vec.h"
++#include "gimple.h"
++#include "tree-pass.h"
++
++#include "langhooks-def.h"
++#include "expr.h"
++
++#include "except.h"
++#include "value-prof.h"
++#include "pointer-set.h"
++
++/* define TW_FINALIZE_STMTS to 1, if you want to run the widening
++ * pass just after gimplification - over the sequence of statements.
++ */
++#define TW_FINALIZE_STMTS 1
++
++#define TW_DEBUG 0
++#if TW_DEBUG
++
++#define TWDBG_STMT(stmt) fprintf (stderr, "%s: ", __FUNCTION__); \
++ debug_gimple_stmt (stmt);
++
++#define TWDBG_TREE(tree) \
++{ \
++ fprintf (stderr, "%s:\n", #tree); \
++ debug_tree (tree); \
++ fprintf (stderr, "\n"); \
++}
++
++#define TWDBG_MSG(fmt) \
++fprintf (stderr, "%s: ", __FUNCTION__); \
++fprintf (stderr, fmt)
++
++#define TWDBG_MSG1(fmt, msg) \
++fprintf (stderr, "%s: ", __FUNCTION__); \
++fprintf (stderr, fmt, msg)
++
++#else
++#define TWDBG_STMT(stmt)
++#define TWDBG_TREE(tree)
++#define TWDBG_MSG(fmt)
++#define TWDBG_MSG1(fmt, msg)
++#endif
++
++#if TW_DEBUG
++static void tw_dump_candidate_list (void);
++static bool tw_debug_candidate (const void *t, void **candidacy, void *data);
++#endif
++static void tw_init (void);
++static void tw_reset (void);
++static long tw_candidate (tree node);
++static long tw_candidate_const (tree node);
++static long *tw_log_candidate (tree node);
++static long tw_candidacy_valid (tree node);
++static void tw_candidacy (tree node, long value);
++static long tw_in_candidate_list (tree node);
++static tree tw_widen_constant (tree node);
++static tree tw_widen_variable (tree node);
++#ifdef TW_FINALIZE_STMTS
++static long tw_fn_has_openmp (gimple_seq stmts);
++#endif
++static void tw_log_parms (tree fndecl);
++#ifdef TW_FINALIZE_STMTS
++static void tw_log_vars (gimple_seq stmts);
++#endif
++static void tw_log_local_decls (void);
++#ifdef TW_FINALIZE_STMTS
++static unsigned int tw_finalize_stmts (void);
++#endif
++static unsigned int tw_finalize_bbs (void);
++static long tw_gimple_in_seq (gimple_seq stmts, long widen);
++static long tw_gimple_in_bb (basic_block bb, long widen);
++static long tw_switch (gimple stmt, long widen);
++static long tw_gimple_stmt (gimple stmt, long widen);
++static long tw_gimple_assign (gimple stmt, long widen);
++static long tw_gimple_assign_single (gimple stmt, long widen);
++static long tw_gimple_assign_unary (gimple stmt, long widen);
++static long tw_gimple_assign_binary (gimple stmt, long widen);
++static long tw_gimple_assign_ternary (gimple stmt, long widen);
++static bool is_formatted_IO_fn (tree decl);
++static long tw_gimple_call (gimple stmt, long widen);
++static long tw_gimple_comparison (gimple stmt, long widen);
++static long tw_gimple_switch (gimple stmt, long widen);
++static long tw_gimple_return (gimple stmt, long widen);
++static long tw_gimple_asm (gimple stmt, long widen);
++static long tw_gimple_debug (gimple stmt, long widen);
++
++static struct pointer_map_t *tw_candidate_list;
++
++#if TW_DEBUG
++static void
++tw_dump_candidate_list (void)
++{
++ TWDBG_MSG ("Dumping candidate list:\n");
++ pointer_map_traverse (tw_candidate_list, tw_debug_candidate, NULL);
++ TWDBG_MSG ("Done dumping candidate list\n");
++}
++
++static
++bool tw_debug_candidate (const void *t, void **candidacy, void *data)
++{
++ debug_tree (t);
++ fprintf(stderr, "candidacy: %ld\n data (ignore): %p", *((long *) candidacy), data);
++ return true;
++}
++#endif
++
++static void
++tw_init (void)
++{
++ gcc_assert (tw_candidate_list == NULL);
++ tw_candidate_list = pointer_map_create ();
++}
++
++static void
++tw_reset (void)
++{
++ if (tw_candidate_list)
++ {
++ pointer_map_destroy (tw_candidate_list);
++ tw_candidate_list = NULL;
++ }
++}
++
++/* gcc.dg/torture/pr43879_[12].c
++ * Initialized statics should not be widened:
++ *
++ * void bar(int c)
++ * {
++ * static int x = 1; // if widened, x gets initialized to (2^32)
++ * if (c != x) __builtin_abort();
++ * x--;
++ * }
++ *
++ * int main()
++ * {
++ * int c = 1;
++ * bar (1);
++ * return 0;
++ * }
++ *
++ * Likely, the initial value is laid out/translated to RTL way before
++ * the rest of the code is translated to GIMPLE; so when we widen the
++ * type, it's already too late.
++ */
++
++/* tw_candidate() has no way to tell if it was passed a local variable
++ * (or not) - so make sure it is passed local variables or parameters only.
++ */
++static long
++tw_candidate (tree node)
++{
++ long rv = 0;
++
++ if (!node || TREE_TYPE (node) == error_mark_node)
++ return 0;
++
++ if (node && TREE_TYPE (node) != error_mark_node &&
++ ((TREE_CODE (node) == VAR_DECL &&
++ /* See note: Initialized statics should not be widened. */
++ (!TREE_STATIC (node) || !DECL_INITIAL (node))) ||
++ TREE_CODE (node) == PARM_DECL ||
++ TREE_CODE (node) == DEBUG_EXPR_DECL) &&
++ !TYPE_VOLATILE (TREE_TYPE (node)) &&
++ !TREE_ADDRESSABLE (node) &&
++ !POINTER_TYPE_P (TREE_TYPE (node)) &&
++ INTEGRAL_TYPE_P (TREE_TYPE (node)) &&
++ !TYPE_UNSIGNED (TREE_TYPE (node)) &&
++ (TYPE_PRECISION (TREE_TYPE (node)) < TYPE_PRECISION (long_integer_type_node)))
++ rv = 1;
++ return rv;
++}
++
++static long
++tw_candidate_const (tree node)
++{
++ long rv = 0;
++
++ if (node && TREE_TYPE (node) != error_mark_node &&
++ INTEGRAL_TYPE_P (TREE_TYPE (node)) &&
++ TREE_CONSTANT (node) &&
++ (TYPE_PRECISION (TREE_TYPE (node)) < TYPE_PRECISION (long_integer_type_node)))
++ rv = 1;
++ return rv;
++}
++
++static long *
++tw_log_candidate (tree node)
++{
++ long *pval = NULL;
++
++ if (tw_candidate_list && node && TREE_TYPE (node) != error_mark_node)
++ {
++ pval = (long *) pointer_map_contains (tw_candidate_list, node);
++ if (!pval)
++ {
++ pval = (long *) pointer_map_insert (tw_candidate_list, node);
++ *pval = 1;
++ TWDBG_MSG ("Logged variable:\n");
++ TWDBG_TREE (node);
++ }
++ }
++ return pval;
++}
++
++static long
++tw_candidacy_valid (tree node)
++{
++ long rval = 0;
++ long *pval = NULL;
++
++ if (tw_candidate_list && node && TREE_TYPE (node) != error_mark_node)
++ pval = (long *) pointer_map_contains (tw_candidate_list, node);
++ if (pval)
++ rval = *pval ? 1 : 0;
++ return rval;
++}
++
++static void
++tw_candidacy (tree node, long value)
++{
++ long *pval;
++
++ if (tw_candidate_list && node)
++ {
++ pval = (long *) pointer_map_contains (tw_candidate_list, node);
++ if (pval)
++ {
++ *pval = value;
++#if TW_DEBUG
++ fprintf (stderr, "Setting candidacy of node:\n");
++ TWDBG_TREE (node);
++ fprintf (stderr, "to: %ld\n", value);
++#endif
++ }
++ }
++}
++
++static long
++tw_in_candidate_list (tree node)
++{
++ long *pval;
++ long rval = 0;
++
++ if (tw_candidate_list && node && TREE_TYPE (node) != error_mark_node)
++ {
++ pval = (long *) pointer_map_contains (tw_candidate_list, node);
++ rval = pval ? 1 : 0;
++ }
++ return rval;
++}
++
++static tree
++tw_widen_constant (tree node)
++{
++ if (node && tw_candidate_const (node))
++ node = build_int_cst (long_integer_type_node, TREE_INT_CST_LOW (node));
++
++ return node;
++}
++
++static tree
++tw_widen_variable (tree node)
++{
++ if (node && tw_candidacy_valid (node))
++ {
++ TWDBG_MSG ("Widening:\n");
++ TWDBG_TREE(node);
++
++ TREE_TYPE (node) = build_qualified_type (long_integer_type_node,
++ TYPE_QUALS (TREE_TYPE (node)));
++
++ if (TREE_CODE (node) != DEBUG_EXPR_DECL)
++ relayout_decl (node);
++ }
++ return node;
++}
++
++#ifdef TW_FINALIZE_STMTS
++static long
++tw_fn_has_openmp (gimple_seq stmts)
++{
++ gimple_stmt_iterator ittr;
++ long found_openmp = 0;
++
++ for (ittr = gsi_start (stmts); !gsi_end_p (ittr) && !found_openmp; gsi_next (&ittr))
++ {
++ gimple stmt = gsi_stmt (ittr);
++
++ switch (gimple_code (stmt))
++ {
++ case GIMPLE_BIND:
++ found_openmp = tw_fn_has_openmp (gimple_bind_body (stmt));
++ break;
++
++ case GIMPLE_TRY:
++ found_openmp = tw_fn_has_openmp (gimple_try_eval (stmt));
++ found_openmp = tw_fn_has_openmp (gimple_try_cleanup (stmt));
++ break;
++
++ case GIMPLE_EH_FILTER:
++ found_openmp = tw_fn_has_openmp (gimple_eh_filter_failure (stmt));
++ break;
++
++ case GIMPLE_CATCH:
++ found_openmp = tw_fn_has_openmp (gimple_catch_handler (stmt));
++ break;
++
++ default:
++ switch (gimple_code (stmt))
++ {
++ CASE_GIMPLE_OMP:
++ found_openmp = 1;
++ break;
++ default:
++ break;
++ }
++ }
++ }
++ return found_openmp;
++}
++#endif
++
++/* Originally, we implemented type widening over the emitted GIMPLE
++ * sequence. Later on, we discovered that we needed to wait till
++ * after OpenMP expansion, so we implemented type widening over the
++ * CFG-BB form.
++ */
++#ifdef TW_FINALIZE_STMTS
++struct gimple_opt_pass pass_widen_types_stmts =
++{
++ {
++ GIMPLE_PASS,
++ "tw-stmts", /* name */
++ NULL, /* gate */
++ tw_finalize_stmts, /* execute */
++ NULL, /* sub */
++ NULL, /* next */
++ 0, /* static_pass_number */
++ TV_NONE, /* tv_id */
++ PROP_gimple_any, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ TODO_dump_func /* todo_flags_finish */
++ }
++};
++#endif
++
++struct gimple_opt_pass pass_widen_types_bbs =
++{
++ {
++ GIMPLE_PASS,
++ "tw-bbs", /* name */
++ NULL, /* gate */
++ tw_finalize_bbs, /* execute */
++ NULL, /* sub */
++ NULL, /* next */
++ 0, /* static_pass_number */
++ TV_NONE, /* tv_id */
++ PROP_gimple_any, /* properties_required */
++ 0, /* properties_provided */
++ 0, /* properties_destroyed */
++ 0, /* todo_flags_start */
++ TODO_dump_func /* todo_flags_finish */
++ }
++};
++
++static
++void
++tw_log_parms (tree fndecl)
++{
++ tree parm;
++
++ if (!fndecl)
++ return;
++ for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
++ if (tw_candidate (parm))
++ tw_log_candidate (parm);
++ return;
++}
++
++#ifdef TW_FINALIZE_STMTS
++static
++void
++tw_log_vars (gimple_seq stmts)
++{
++ gimple_stmt_iterator ittr;
++ tree vars, vindex;
++
++ if (!stmts)
++ return;
++
++ gcc_assert (tw_candidate_list != NULL);
++
++ for (ittr = gsi_start (stmts); !gsi_end_p (ittr); gsi_next (&ittr))
++ {
++ gimple stmt = gsi_stmt (ittr);
++
++ switch (gimple_code (stmt))
++ {
++ case GIMPLE_BIND:
++ vars = gimple_bind_vars (stmt);
++ for (vindex = vars; vindex; vindex = DECL_CHAIN (vindex))
++ if (tw_candidate (vindex))
++ tw_log_candidate (vindex);
++ tw_log_vars (gimple_bind_body (stmt));
++ break;
++
++ case GIMPLE_TRY:
++ tw_log_vars (gimple_try_eval (stmt));
++ tw_log_vars (gimple_try_cleanup (stmt));
++ break;
++
++ case GIMPLE_EH_FILTER:
++ tw_log_vars (gimple_eh_filter_failure (stmt));
++ break;
++
++ case GIMPLE_CATCH:
++ tw_log_vars (gimple_catch_handler (stmt));
++ break;
++
++ default:
++ break;
++ }
++ }
++
++ return;
++}
++#endif
++
++static
++void
++tw_log_local_decls (void)
++{
++ tree decl;
++ unsigned ix;
++
++ FOR_EACH_LOCAL_DECL (cfun, ix, decl)
++ {
++ TWDBG_MSG ("Testing decl:\n");
++ TWDBG_TREE (decl);
++ if (tw_candidate (decl))
++ tw_log_candidate (decl);
++ }
++}
++
++/* Widen types. tw_finalize_stmts () can be run anytime immediately after
++ * gimplification but before the CFG pass (see comment * accompanying
++ * gimple_body ()).
++ *
++ * After gimplification has occurred, the emitted GIMPLE is
++ * scanned to check if these variables are only used among
++ * themselves (with the exception of being cast to unsigned long);
++ * invalidating the candidacy of any variable that is used with
++ * another outside this set (and so on recursively). The variables
++ * that remain after this process all occur in operations with other
++ * such candidate variables, (or with constants) - the type of all
++ * such residual candidate variables (and of constants that appear
++ * with these in operations) is changed to long (along with the
++ * original accompannying qualifiers on the type).
++ *
++ * void
++ * init_optimization_passes (void)
++ *
++ * p = &all_lowering_passes;
++ * NEXT_PASS (pass_widen_types_stmts);
++ * NEXT_PASS (pass_warn_unused_result);
++ */
++#ifdef TW_FINALIZE_STMTS
++static
++unsigned int
++tw_finalize_stmts (void)
++{
++ long iv = 0;
++ gimple_seq stmts;
++ tree fndecl = current_function_decl;
++
++ if (strcmp (lang_hooks.name, "GNU C") != 0 ||
++ seen_error () ||
++ !flag_strict_overflow ||
++ !flag_widen_types)
++ {
++ TWDBG_MSG ("Skipping: Language not C or seen error or -fno-strict-overflow or -fno-widen-types\n");
++ return 0;
++ }
++
++ /* gcc.dg/pr23518.c execution test */
++ if (flag_wrapv)
++ {
++ TWDBG_MSG ("Skipping: -fwrapv specified.\n");
++ return 0;
++ }
++
++ if (debug_info_level == DINFO_LEVEL_NONE)
++ {
++ /* PS: That we cannot call relayout_decl () on DEBUG_EXPR_DECL is an
++ * issue: Debug information is generated after lowering from tree to
++ * GIMPLE; unless we widen before debug information is generated, the
++ * debug information will record pre-widening information - and that
++ * cannot be changed because relayout_decl () cannot be invoked on
++ * DEBUG_EXPR_DECL. expand_debug_locations () during cfgexpand will
++ * fail gcc_assert ()'s on the DEBUG_INSN's since e.g. the modes will
++ * not agree, etc. So if we are compiling -g, we ought to run the
++ * pass_widen_types_stmts.
++ *
++ * In short: pass_widen_types_stmts runs iff we're generating debug
++ * information.
++ */
++ TWDBG_MSG ("Skipping: Debug level none.\n");
++ return 0;
++ }
++ gcc_assert (debug_info_level != DINFO_LEVEL_NONE);
++
++ if (!fndecl)
++ {
++ TWDBG_MSG ("Skipping: !fndecl.\n");
++ return 0;
++ }
++
++ TWDBG_MSG ("Widening function:\n");
++ TWDBG_TREE (fndecl);
++
++ stmts = gimple_body (fndecl);
++
++ if (!stmts)
++ {
++ TWDBG_MSG ("Skipping: !stmts.\n");
++ return 0;
++ }
++
++ if (tw_fn_has_openmp (stmts))
++ {
++ TWDBG_MSG ("Skipping: OpenMP stmts found.\n");
++ return 0;
++ }
++
++ /* Assume for now that we do not need to check for nested functions:
++ * (cgraph_get_node (fndecl) && cgraph_get_node (fndecl)->nested != NULL) ||
++ * TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL ||
++ * Well, turns out that a nested function is processed only if it is
++ * actually invoked from within the function, so we are in good shape.
++ */
++
++ tw_init ();
++ tw_log_parms (fndecl);
++ tw_log_vars (stmts);
++#if TW_DEBUG
++ tw_dump_candidate_list ();
++#endif
++
++ do
++ {
++ iv = tw_gimple_in_seq (stmts, 0);
++ } while (iv);
++ tw_gimple_in_seq (stmts, 1);
++ verify_types_in_gimple_seq (stmts);
++
++ tw_reset ();
++
++ return 0;
++}
++#endif
++
++static
++unsigned int
++tw_finalize_bbs (void)
++{
++ long iv = 0;
++ basic_block bb;
++ tree fndecl;
++
++ if (strcmp (lang_hooks.name, "GNU C") != 0 ||
++ seen_error () ||
++ !flag_strict_overflow ||
++ !flag_widen_types)
++ {
++ TWDBG_MSG ("Skipping: Language not C or seen error or -fno-strict-overflow or -fno-widen-types\n");
++ return 0;
++ }
++
++ /* gcc.dg/pr23518.c execution test */
++ if (flag_wrapv)
++ {
++ TWDBG_MSG ("Skipping: -fwrapv specified.\n");
++ return 0;
++ }
++
++ if (debug_info_level != DINFO_LEVEL_NONE && flag_openmp)
++ {
++ /* Cannot run this pass as the debug information has already
++ * been recorded; If we type widen now, it'll lead to assert
++ * failures during RTL expansion in expandcfg.c since the
++ * debug information would all be prewidening and would
++ * mismatch with the postwidening information for the variables
++ * that got widened (but whoose debug information was already
++ * generated). This is all because we cannot call relayout_decl ()
++ * on DEBUG_EXPR_DECL's - see note elsewhere.
++ */
++ TWDBG_MSG ("Skipping: Non-zero debug level and -fopenmp specified.\n");
++ return 0;
++ }
++
++ if (!cfun || !(fndecl = cfun->decl) || !(cfun->cfg))
++ {
++ TWDBG_MSG ("Skipping: !cfun or !fndecl or !(cfun->cfg).\n");
++ return 0;
++ }
++
++ TWDBG_MSG ("Widening function:\n");
++ TWDBG_TREE (fndecl);
++
++ /* Assume for now that we do not need to check for nested functions:
++ * (cgraph_get_node (fndecl) && cgraph_get_node (fndecl)->nested != NULL) ||
++ * TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL ||
++ * Well, turns out that a nested function is processed only if it is
++ * actually invoked from within the function, so we are in good shape.
++ */
++
++ tw_init ();
++ tw_log_parms (fndecl);
++ tw_log_local_decls ();
++#if TW_DEBUG
++ tw_dump_candidate_list ();
++#endif
++
++ do
++ {
++ iv = 0;
++ FOR_EACH_BB (bb)
++ iv += tw_gimple_in_bb (bb, 0);
++ } while (iv);
++ FOR_EACH_BB (bb)
++ tw_gimple_in_bb (bb, 1);
++ FOR_EACH_BB (bb)
++ verify_types_in_gimple_seq (bb_seq (bb));
++
++ tw_reset ();
++
++ return 0;
++}
++
++/* Assumes that we have run verify_gimple_in_seq (stmts)
++ * i.e. that we have valid gimple.
++ */
++static long
++tw_gimple_in_seq (gimple_seq stmts, long widen)
++{
++ gimple_stmt_iterator ittr;
++ long iv = 0;
++
++ for (ittr = gsi_start (stmts); !gsi_end_p (ittr); gsi_next (&ittr))
++ {
++ gimple stmt = gsi_stmt (ittr);
++ iv += tw_switch (stmt, widen);
++ }
++ return iv;
++}
++
++static long
++tw_gimple_in_bb (basic_block bb, long widen)
++{
++ gimple_stmt_iterator ittr;
++ long iv = 0;
++
++#if TW_DEBUG
++ fprintf (stderr, "Dumping basic block (widen = %ld):\n", widen);
++ debug_bb (bb);
++ fprintf (stderr, "Done dumping basic block (widen = %ld)\n", widen);
++#endif
++ for (ittr = gsi_start_bb (bb); !gsi_end_p (ittr); gsi_next (&ittr))
++ {
++ gimple stmt = gsi_stmt (ittr);
++ iv += tw_switch (stmt, widen);
++ }
++ return iv;
++}
++
++static long
++tw_switch (gimple stmt, long widen)
++{
++ long iv = 0;
++
++ switch (gimple_code (stmt))
++ {
++ case GIMPLE_BIND:
++ iv += tw_gimple_in_seq (gimple_bind_body (stmt), widen);
++ break;
++
++ case GIMPLE_TRY:
++ iv += tw_gimple_in_seq (gimple_try_eval (stmt), widen);
++ iv += tw_gimple_in_seq (gimple_try_cleanup (stmt), widen);
++ break;
++
++ case GIMPLE_EH_FILTER:
++ iv += tw_gimple_in_seq (gimple_eh_filter_failure (stmt), widen);
++ break;
++
++ case GIMPLE_CATCH:
++ iv += tw_gimple_in_seq (gimple_catch_handler (stmt), widen);
++ break;
++
++ default:
++ iv += tw_gimple_stmt (stmt, widen);
++ break;
++ }
++ return iv;
++}
++
++/* tw_gimple_stmt () mimics verify_gimple_stmt ()
++ */
++static long
++tw_gimple_stmt (gimple stmt, long widen)
++{
++ long iv = 0;
++
++ switch (gimple_code (stmt))
++ {
++ case GIMPLE_ASSIGN:
++ iv = tw_gimple_assign (stmt, widen);
++ break;
++
++ case GIMPLE_CALL:
++ iv = tw_gimple_call (stmt, widen);
++ break;
++
++ case GIMPLE_COND:
++ iv = tw_gimple_comparison (stmt, widen);
++ break;
++
++ case GIMPLE_SWITCH:
++ iv = tw_gimple_switch (stmt, widen);
++ break;
++
++ case GIMPLE_RETURN:
++ iv = tw_gimple_return (stmt, widen);
++ break;
++
++ case GIMPLE_LABEL:
++ TWDBG_STMT(stmt);
++ break;
++
++ case GIMPLE_GOTO:
++ TWDBG_STMT(stmt);
++ break;
++
++ case GIMPLE_ASM:
++ iv = tw_gimple_asm (stmt, widen);
++ break;
++
++ /* Tuples that do not have tree operands. */
++ case GIMPLE_NOP:
++ case GIMPLE_PREDICT:
++ case GIMPLE_RESX:
++ case GIMPLE_EH_DISPATCH:
++ case GIMPLE_EH_MUST_NOT_THROW:
++ TWDBG_STMT(stmt);
++ break;
++
++ CASE_GIMPLE_OMP:
++ TWDBG_STMT(stmt);
++ break;
++
++ case GIMPLE_DEBUG:
++ iv = tw_gimple_debug (stmt, widen);
++ break;
++
++ default:
++ gcc_unreachable ();
++ }
++ return iv;
++}
++
++static long
++tw_gimple_assign (gimple stmt, long widen)
++{
++ long iv = 0;
++
++ switch (gimple_assign_rhs_class (stmt))
++ {
++ case GIMPLE_SINGLE_RHS:
++ iv = tw_gimple_assign_single (stmt, widen);
++ break;
++
++ case GIMPLE_UNARY_RHS:
++ iv = tw_gimple_assign_unary (stmt, widen);
++ break;
++
++ case GIMPLE_BINARY_RHS:
++ iv = tw_gimple_assign_binary (stmt, widen);
++ break;
++
++ case GIMPLE_TERNARY_RHS:
++ iv = tw_gimple_assign_ternary (stmt, widen);
++ break;
++
++ default:
++ gcc_unreachable ();
++ }
++ return iv;
++}
++
++static long
++tw_gimple_assign_single (gimple stmt, long widen)
++{
++ tree lhs = gimple_assign_lhs (stmt);
++ tree rhs1 = gimple_assign_rhs1 (stmt);
++ tree value;
++ long iv = 0;
++ unsigned int idx;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(lhs);
++ TWDBG_TREE(rhs1);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ if (TREE_CODE (rhs1) == ARRAY_REF &&
++ tw_candidacy_valid (TREE_OPERAND (rhs1, 1)))
++ {
++ /* Note that we are widening the array index, hence no
++ * gimple_assign_set_rhs1 () */
++ tw_widen_variable (TREE_OPERAND (rhs1, 1));
++ }
++ else if (TREE_CODE (lhs) == ARRAY_REF &&
++ tw_candidacy_valid (TREE_OPERAND (lhs, 1)))
++ {
++ /* Note that we are widening the array index, hence no
++ * gimple_assign_set_lhs () */
++ tw_widen_variable (TREE_OPERAND (lhs, 1));
++ }
++ else if (tw_candidacy_valid (lhs) && tw_candidate_const (rhs1))
++ {
++ gimple_assign_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_assign_set_rhs1 (stmt, tw_widen_constant (rhs1));
++ }
++ else if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1))
++ {
++ gimple_assign_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_assign_set_rhs1 (stmt, tw_widen_variable (rhs1));
++ }
++ }
++ else
++ {
++ TWDBG_MSG ("Validating run.\n");
++ if (tw_candidacy_valid (lhs) && tw_candidate_const (rhs1))
++ return iv;
++ if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1))
++ return iv;
++ if (TREE_CODE (lhs) == VAR_DECL && TREE_CODE (TREE_TYPE (lhs)) == VECTOR_TYPE &&
++ TREE_CODE (rhs1) == CONSTRUCTOR && TREE_CODE (TREE_TYPE (rhs1)) == VECTOR_TYPE)
++ {
++ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs1), idx, value)
++ {
++ if (tw_candidacy_valid (value))
++ {
++ TWDBG_MSG ("Invalidating candidacy of constructor element:\n");
++ TWDBG_TREE (value);
++ tw_candidacy (value, 0);
++ iv++;
++ }
++ }
++ }
++ if (tw_candidacy_valid (lhs))
++ {
++ tw_candidacy (lhs, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs1))
++ {
++ tw_candidacy (rhs1, 0);
++ iv++;
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_assign_unary (gimple stmt, long widen)
++{
++ tree lhs = gimple_assign_lhs (stmt);
++ tree rhs1 = gimple_assign_rhs1 (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(lhs);
++ TWDBG_TREE(rhs1);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ if (gimple_assign_rhs_code (stmt) == NOP_EXPR &&
++ tw_candidacy_valid (rhs1) &&
++ (TREE_TYPE (lhs) == long_unsigned_type_node ||
++ TREE_TYPE (lhs) == long_integer_type_node))
++ gimple_assign_set_rhs1 (stmt, tw_widen_variable (rhs1));
++ }
++ else
++ {
++ TWDBG_MSG ("Validating run.\n");
++ if (gimple_assign_rhs_code (stmt) == NOP_EXPR &&
++ tw_candidacy_valid (rhs1) &&
++ (TREE_TYPE (lhs) == long_unsigned_type_node ||
++ TREE_TYPE (lhs) == long_integer_type_node))
++ return iv;
++ if (tw_candidacy_valid (lhs))
++ {
++ tw_candidacy (lhs, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs1))
++ {
++ tw_candidacy (rhs1, 0);
++ iv++;
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_assign_binary (gimple stmt, long widen)
++{
++ tree lhs = gimple_assign_lhs (stmt);
++ tree rhs1 = gimple_assign_rhs1 (stmt);
++ tree rhs2 = gimple_assign_rhs2 (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(lhs);
++ TWDBG_TREE(rhs1);
++ TWDBG_TREE(rhs2);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1) && tw_candidate_const (rhs2))
++ {
++ gimple_assign_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_assign_set_rhs1 (stmt, tw_widen_variable (rhs1));
++ gimple_assign_set_rhs2 (stmt, tw_widen_constant (rhs2));
++ }
++ else if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1) && tw_candidacy_valid (rhs2))
++ {
++ gimple_assign_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_assign_set_rhs1 (stmt, tw_widen_variable (rhs1));
++ gimple_assign_set_rhs2 (stmt, tw_widen_variable (rhs2));
++ }
++ }
++ else
++ {
++ TWDBG_MSG ("Validating run.\n");
++ if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1) && tw_candidate_const (rhs2))
++ return iv;
++ if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs1) && tw_candidacy_valid (rhs2))
++ return iv;
++ if (tw_candidacy_valid (lhs))
++ {
++ tw_candidacy (lhs, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs1))
++ {
++ tw_candidacy (rhs1, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs2))
++ {
++ tw_candidacy (rhs2, 0);
++ iv++;
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_assign_ternary (gimple stmt, long widen)
++{
++ tree lhs = gimple_assign_lhs (stmt);
++ tree rhs1 = gimple_assign_rhs1 (stmt);
++ tree rhs2 = gimple_assign_rhs2 (stmt);
++ tree rhs3 = gimple_assign_rhs3 (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(lhs);
++ TWDBG_TREE(rhs1);
++ TWDBG_TREE(rhs2);
++ TWDBG_TREE(rhs3);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ return iv;
++ }
++
++ TWDBG_MSG ("Validating run.\n");
++ if (tw_candidacy_valid (lhs))
++ {
++ tw_candidacy (lhs, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs1))
++ {
++ tw_candidacy (rhs1, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs2))
++ {
++ tw_candidacy (rhs2, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs3))
++ {
++ tw_candidacy (rhs3, 0);
++ iv++;
++ }
++ return iv;
++}
++
++/* Ref. WG14/N1256 Committee Draft - September 7, 2007 ISO/IEC 9899:TC3
++ * 7.19.6 Formatted input/output functions
++ * Sec. 17.19.6.[1 ... 14]
++ */
++#define IO_FN_COUNT 14
++static const char *IO_fn_names[IO_FN_COUNT] =
++{
++ "fprintf", "fscanf",
++ "printf", "scanf",
++ "snprintf",
++ "sprintf", "sscanf",
++ "vfprintf", "vfscanf",
++ "vprintf", "vscanf",
++ "vsnprintf",
++ "vsprintf", "vsscanf",
++};
++
++static bool
++is_formatted_IO_fn (tree decl)
++{
++ const char *fn_name;
++ long i;
++
++ if (decl && TREE_CODE (decl) == FUNCTION_DECL &&
++ DECL_NAME (decl) /* TREE_CODE (decl) == IDENTIFIER_NODE */ &&
++ (fn_name = IDENTIFIER_POINTER (DECL_NAME (decl))))
++ {
++ for (i = 0; i < IO_FN_COUNT; i++)
++ if (strcmp (IO_fn_names[i], fn_name) == 0)
++ return true;
++ }
++ return false;
++}
++
++/* TODO: If you have:
++ *
++ * int i, n, f();
++ *
++ * n = f();
++ *
++ * for (i = 0; i < n; i++)
++ * // stuff
++ *
++ * then (after the candidate set stabilizes) do:
++ *
++ * int n, f();
++ * long twl.n;
++ *
++ * n = f();
++ * twl.n = (long) n;
++ *
++ * for (i = 0; i < twl.n; i++)
++ * // stuff
++ *
++ * only if adding twl.n does not decrease the size of the stabilized
++ * candidate set or "cause any other damage".
++ *
++ * This should help in benchmarks where parameters are set via function
++ * calls to prevent them from being optimized away.
++ *
++ */
++static long
++tw_gimple_call (gimple stmt, long widen)
++{
++#if TW_DEBUG
++ tree fn = gimple_call_fn (stmt);
++#endif
++ long iv = 0;
++ unsigned i;
++ tree arg;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(fn);
++ TWDBG_TREE(gimple_call_fndecl (stmt));
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ for (i = 0; i < gimple_call_num_args (stmt); i++)
++ {
++ arg = gimple_call_arg (stmt, i);
++ if (arg && tw_candidacy_valid (arg))
++ gimple_call_set_arg (stmt, i, tw_widen_variable (arg));
++ }
++ return iv;
++ }
++
++ TWDBG_MSG ("Validating run.\n");
++ if (gimple_call_lhs (stmt) && tw_candidacy_valid (gimple_call_lhs (stmt)))
++ {
++ tw_candidacy (gimple_call_lhs (stmt), 0);
++ iv++;
++ }
++ if (gimple_call_fndecl (stmt) &&
++ (is_builtin_fn (gimple_call_fndecl (stmt)) ||
++ is_formatted_IO_fn (gimple_call_fndecl (stmt))))
++ {
++ /* Certain types of function (printf-scanf family,
++ * formatted IO functions, builtin functions) ought
++ * not to have their args widened.
++ *
++ * e.g. A call to printf () such as:
++ * int x;
++ * printf ("%d", x);
++ * because, we cannot change the %d to a %ld.
++ *
++ * or e.g. in:
++ *
++ * int D.2852;
++ * int si;
++ *
++ * si = 2;
++ * __builtin_altivec_dst (&vi, si, 0);
++ * D.2852 = 0;
++ *
++ * si should not be widened.
++ *
++ * PS: We could generate code for casts to their original types in the
++ * call, but that would slow-down performance and we do not expect
++ * a loop index to be used in a call to a formatted IO function.
++ */
++ for (i = 0; i < gimple_call_num_args (stmt); i++)
++ {
++ arg = gimple_call_arg (stmt, i);
++ if (arg && tw_candidacy_valid (arg))
++ {
++ tw_candidacy (arg, 0);
++ iv++;
++ }
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_comparison (gimple stmt, long widen)
++{
++ tree lhs = gimple_cond_lhs (stmt);
++ tree rhs = gimple_cond_rhs (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(lhs);
++ TWDBG_TREE(rhs);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ if (tw_candidacy_valid (lhs) && tw_candidate_const (rhs))
++ {
++ gimple_cond_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_cond_set_rhs (stmt, tw_widen_constant (rhs));
++ }
++ else if (tw_candidate_const (lhs) && tw_candidacy_valid (rhs))
++ {
++ gimple_cond_set_lhs (stmt, tw_widen_constant (lhs));
++ gimple_cond_set_rhs (stmt, tw_widen_variable (rhs));
++ }
++ else if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs))
++ {
++ gimple_cond_set_lhs (stmt, tw_widen_variable (lhs));
++ gimple_cond_set_rhs (stmt, tw_widen_variable (rhs));
++ }
++ }
++ else
++ {
++ TWDBG_MSG ("Validating run.\n");
++ if (tw_candidacy_valid (lhs) && tw_candidate_const (rhs))
++ return iv;
++ if (tw_candidate_const (lhs) && tw_candidacy_valid (rhs))
++ return iv;
++ if (tw_candidacy_valid (lhs) && tw_candidacy_valid (rhs))
++ return iv;
++ if (tw_candidacy_valid (lhs))
++ {
++ tw_candidacy (lhs, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (rhs))
++ {
++ tw_candidacy (rhs, 0);
++ iv++;
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_switch (gimple stmt, long widen)
++{
++ tree index = gimple_switch_index (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(index);
++
++ if (widen && tw_candidacy_valid (index))
++ {
++ TWDBG_MSG ("Widening run.\n");
++ gimple_switch_set_index (stmt, tw_widen_variable (index));
++ return iv;
++ }
++
++ TWDBG_MSG ("Validating run.\n");
++ return iv;
++}
++
++static long
++tw_gimple_return (gimple stmt, long widen)
++{
++ tree op = gimple_return_retval (stmt);
++ long iv = 0;
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(op);
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ return iv;
++ }
++
++ TWDBG_MSG ("Validating run.\n");
++ if (tw_candidacy_valid (op))
++ {
++ tw_candidacy (op, 0);
++ iv++;
++ }
++ return iv;
++}
++
++static long
++tw_gimple_asm (gimple stmt, long widen)
++{
++ long iv = 0;
++ unsigned int ninputs = gimple_asm_ninputs (stmt);
++ unsigned int noutputs = gimple_asm_noutputs (stmt);
++ unsigned int nclobbers = gimple_asm_nclobbers (stmt);
++ unsigned int i;
++
++ TWDBG_STMT(stmt);
++ TWDBG_MSG("Inputs:\n");
++ for (i = 0; i < ninputs; i++)
++ {
++ TWDBG_MSG1 ("input %d\n", i);
++ TWDBG_TREE (gimple_asm_input_op (stmt, i));
++ }
++ TWDBG_MSG("Outputs:\n");
++ for (i = 0; i < noutputs; i++)
++ {
++ TWDBG_MSG1 ("output %d\n", i);
++ TWDBG_TREE (gimple_asm_output_op (stmt, i));
++ }
++ TWDBG_MSG("Clobbers:\n");
++ for (i = 0; i < nclobbers; i++)
++ {
++ TWDBG_MSG1 ("clobber %d\n", i);
++ TWDBG_TREE (gimple_asm_clobber_op (stmt, i));
++ }
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ return iv;
++ }
++ TWDBG_MSG ("Validating run.\n");
++ for (i = 0; i < ninputs; i++)
++ {
++ if (tw_candidacy_valid (gimple_asm_input_op (stmt, i)))
++ {
++ tw_candidacy (gimple_asm_input_op (stmt, i), 0);
++ iv++;
++ }
++ }
++ for (i = 0; i < noutputs; i++)
++ {
++ if (tw_candidacy_valid (gimple_asm_output_op (stmt, i)))
++ {
++ tw_candidacy (gimple_asm_output_op (stmt, i), 0);
++ iv++;
++ }
++ }
++ for (i = 0; i < nclobbers; i++)
++ {
++ if (tw_candidacy_valid (gimple_asm_clobber_op (stmt, i)))
++ {
++ tw_candidacy (gimple_asm_clobber_op (stmt, i), 0);
++ iv++;
++ }
++ }
++ return iv;
++}
++
++static long
++tw_gimple_debug (gimple stmt, long widen)
++{
++ long iv = 0;
++ tree var, value;
++
++ var = gimple_debug_bind_get_var (stmt);
++ value = gimple_debug_bind_get_value (stmt);
++
++ TWDBG_STMT(stmt);
++ TWDBG_TREE(var);
++ TWDBG_TREE(value);
++
++ /* TODO: What if the value is a constant? */
++
++ if (widen)
++ {
++ TWDBG_MSG ("Widening run.\n");
++ if (tw_candidacy_valid (var) && tw_candidacy_valid (value))
++ {
++ gimple_debug_bind_set_var (stmt, tw_widen_variable (var));
++ gimple_debug_bind_set_value (stmt, tw_widen_variable (value));
++ }
++ else if (tw_candidacy_valid (var) && tw_candidate_const (value))
++ {
++ gimple_debug_bind_set_var (stmt, tw_widen_variable (var));
++ gimple_debug_bind_set_value (stmt, tw_widen_constant (value));
++ }
++ }
++ else
++ {
++ TWDBG_MSG ("Validating run.\n");
++
++ if (var && !tw_in_candidate_list (var) && tw_candidate (var))
++ tw_log_candidate (var);
++ if (value && !tw_in_candidate_list (value) && tw_candidate (value))
++ tw_log_candidate (value);
++ if (tw_candidacy_valid (var) && tw_candidacy_valid (value))
++ return iv;
++ if (tw_candidacy_valid (var))
++ {
++ tw_candidacy (var, 0);
++ iv++;
++ }
++ if (tw_candidacy_valid (value))
++ {
++ tw_candidacy (value, 0);
++ iv++;
++ }
++ }
++
++ return iv;
++}
++
++/* Notes:
++ * ------
++ *
++ * Limitations to be documented:
++ * 0. -g -fopenmp not supported.
++ *
++ * Known DejaGNU failures:
++ * 0. FAIL: gcc.dg/pr38245-2.c scan-tree-dump-not optimized "link_error"
++ * This failure is because the optimization is dependent on the type of the variable;
++ * once the type of the variable has changed from int to long, the inequalities in
++ * this test case no longer hold and the code cannot be optimized anymore, consequently,
++ * the test fails.
++ *
++ * DejaGNU failures that are not due to type-widening:
++ * 0. gcc.dg/vect/vect-120.c scan-tree-dump-times vect "vectorized 1 loops" 1
++ * 1.gcc.dg/vect/vect-120.c -flto scan-tree-dump-times vect "vectorized 1 loops" 1
++ *
++ * DejaGNU PASS'es with -fwiden-types (but FAIL's in the baseline - the baseline needs
++ * to be fixed - it just so happens that the debug information happens to be better in
++ * the type-converted case. We have verified that the generated assembly is the same in
++ * either case (or has extsw eliminated)):
++ * gcc.dg/guality/pr45882.c
++ * gcc.dg/guality/pr43177.c
++ *
++ */
--- /dev/null
+Upstream-Status: Inappropriate [embedded specific]
+
+gcc-runtime builds libstdc++ separately from gcc-cross-*. Its configure tests using g++
+will not run correctly since by default the linker will try to link against libstdc++
+which shouldn't exist yet. We need an option to disable -lstdc++
+option whilst leaving -lc, -lgcc and other automatic library dependencies added by gcc
+driver. This patch adds such an option which only disables the -lstdc++.
+
+A "standard" gcc build uses xgcc and hence avoids this. We should ask upstream how to
+do this officially, the likely answer is don't build libstdc++ separately.
+
+RP 29/6/10
+
+Index: gcc-4.6.0/gcc/cp/g++spec.c
+===================================================================
+--- gcc-4.6.0.orig/gcc/cp/g++spec.c
++++ gcc-4.6.0/gcc/cp/g++spec.c
+@@ -127,6 +127,7 @@ lang_specific_driver (struct cl_decoded_
+ switch (decoded_options[i].opt_index)
+ {
+ case OPT_nostdlib:
++ case OPT_nostdlib__:
+ case OPT_nodefaultlibs:
+ library = -1;
+ break;
+Index: gcc-4.6.0/gcc/doc/invoke.texi
+===================================================================
+--- gcc-4.6.0.orig/gcc/doc/invoke.texi
++++ gcc-4.6.0/gcc/doc/invoke.texi
+@@ -193,7 +193,7 @@ in the following sections.
+ -fno-pretty-templates @gol
+ -frepo -fno-rtti -fstats -ftemplate-depth=@var{n} @gol
+ -fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++ @gol
+--fno-default-inline -fvisibility-inlines-hidden @gol
++-nostdlib++ -fno-default-inline -fvisibility-inlines-hidden @gol
+ -fvisibility-ms-compat @gol
+ -Wabi -Wconversion-null -Wctor-dtor-privacy @gol
+ -Wnoexcept -Wnon-virtual-dtor -Wreorder @gol
+@@ -431,7 +431,7 @@ Objective-C and Objective-C++ Dialects}.
+ @gccoptlist{@var{object-file-name} -l@var{library} @gol
+ -nostartfiles -nodefaultlibs -nostdlib -pie -rdynamic @gol
+ -s -static -static-libgcc -static-libstdc++ -shared @gol
+--shared-libgcc -symbolic @gol
++-shared-libgcc -symbolic -nostdlib++ @gol
+ -T @var{script} -Wl,@var{option} -Xlinker @var{option} @gol
+ -u @var{symbol}}
+
+@@ -9069,6 +9069,11 @@ These entries are usually resolved by en
+ libc. These entry points should be supplied through some other
+ mechanism when this option is specified.
+
++@item -nostdlib++
++@opindex nostdlib++
++Do not use the standard system C++ runtime libraries when linking.
++Only the libraries you specify will be passed to the linker.
++
+ @cindex @option{-lgcc}, use with @option{-nostdlib}
+ @cindex @option{-nostdlib} and unresolved references
+ @cindex unresolved references and @option{-nostdlib}
+Index: gcc-4.6.0/gcc/c-family/c.opt
+===================================================================
+--- gcc-4.6.0.orig/gcc/c-family/c.opt
++++ gcc-4.6.0/gcc/c-family/c.opt
+@@ -1111,6 +1111,10 @@ nostdinc++
+ C++ ObjC++
+ Do not search standard system include directories for C++
+
++nostdlib++
++Driver
++Do not link standard C++ runtime library
++
+ o
+ C ObjC C++ ObjC++ Joined Separate
+ ; Documented in common.opt
+Index: gcc-4.6.0/gcc/gcc.c
+===================================================================
+--- gcc-4.6.0.orig/gcc/gcc.c
++++ gcc-4.6.0/gcc/gcc.c
+@@ -666,6 +666,7 @@ proper position among the other output f
+ %(mflib) " STACK_SPLIT_SPEC "\
+ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
+ %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
++ %{!nostdlib++:}\
+ %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}"
+ #endif
+
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
+
+do_install () {
+ oe_runmake 'DESTDIR=${D}' install
+ install -d ${D}${target_base_libdir}/
+ cp -rf ${D}${exec_prefix}/${TARGET_SYS}/${baselib}/ ${D}${target_base_libdir}/
+
+ # We don't really need this (here shares/ contains man/, info/, locale/).
+ rm -rf ${D}${datadir}/
+
+ # We use libiberty from binutils
+ find ${D}${exec_prefix}/lib -name libiberty.a | xargs rm -f
+ find ${D}${exec_prefix}/lib -name libiberty.h | xargs rm -f
+
+ # Insert symlinks into libexec so when tools without a prefix are searched for, the correct ones are
+ # found. These need to be relative paths so they work in different locations.
+ dest=${D}${libexecdir}/gcc/${TARGET_SYS}/${BINV}/
+ install -d $dest
+ for t in ar as ld nm objcopy objdump ranlib strip g77 gcc cpp gfortran; do
+ ln -sf ${BINRELPATH}/${TARGET_PREFIX}$t $dest$t
+ done
+}
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+#LIC_FILES_CHKSUM = "file://COPYING;md5=59530bdf33659b29e73d4adb9f9f6552 \
+# file://COPYING3;md5=d32239bcb673463ab874e80d47fae504 \
+# file://COPYING3.LIB;md5=6a6a8e020838b23406c81b19c1d46df6 \
+# file://COPYING.LIB;md5=2d5025d4aa3495befef8f17206a5b0a1 \
+# file://COPYING.RUNTIME;md5=fe60d87048567d4fe8c8a0ed2448bcc8"
+
+BINV = "4.6.2"
+
+SRCREV = "180516"
+# ignore linaro backports since we are changing the SRCREV
+GCC-4_6-BRANCH-LINARO-BACKPORTS = ""
+
+SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH};proto=http \
+ file://gcc-4.3.1-ARCH_FLAGS_FOR_TARGET.patch \
+ file://gcc.fix_longversionstring.patch \
+ file://gcc.rm_slow_tests.patch \
+ file://gcc.fix_mingw32.patch \
+ file://gcc.fix_cloogstatic2.patch \
+ file://gcc.fix_build-with-cxx.patch \
+ file://gcc.e6500-FSF46.patch \
+ file://gcc.ld_unaligned-460.patch \
+ file://gcc.local_unaligned_altivec.patch \
+ file://gcc.soft_float-460.patch \
+ file://gcc.case_values.patch \
+ file://gcc.builtin_isel.patch \
+ file://gcc.experimental_move.patch \
+ file://gcc.widen_types-46.patch \
+ file://gcc.extelim-v3.patch \
+ file://gcc.e5500_mfocr.patch \
+ file://gcc.opt-array-offset.patch \
+ file://gcc.load_on_store_bypass-462.patch \
+ file://gcc.fix_constvector.patch \
+ file://gcc.fix_MTWX51204-dwarf-vector-reg.patch \
+ file://gcc.fix_ira-loop-pressure.patch \
+ file://optional_libstdc.patch \
+ file://gcc.remove_CCUNSmode_reference.patch \
+ file://gcc.check_path_validity.patch \
+ file://gcc.fix_header_issue.patch \
+ file://gcc.fix_SSIZE_MAX_undefine_issue.patch \
+"
+
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+PR .= "+${DISTRO}.0"
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc
--- /dev/null
+require gcc-fsl.inc