public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/gcc] rhel-f41-base: 4.4.0-7
@ 2026-06-29 12:24 Jakub Jelinek
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2026-06-29 12:24 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/gcc
Branch : rhel-f41-base
Commit : 1418c181c1a6807419f24793d4813c031742e03c
Author : Jakub Jelinek <jakub@fedoraproject.org>
Date : 2009-06-09T14:26:59+00:00
Stats : +9176/-87 in 11 file(s)
URL : https://src.fedoraproject.org/rpms/gcc/c/1418c181c1a6807419f24793d4813c031742e03c?branch=rhel-f41-base
Log:
4.4.0-7
---
diff --git a/.cvsignore b/.cvsignore
index 23f2f52..4e39550 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,2 +1,2 @@
fastjar-0.97.tar.gz
-gcc-4.4.0-20090514.tar.bz2
+gcc-4.4.0-20090609.tar.bz2
diff --git a/gcc.spec b/gcc.spec
index 5c77bbc..8ebf849 100644
--- a/gcc.spec
+++ b/gcc.spec
@@ -1,9 +1,9 @@
-%global DATE 20090514
-%global SVNREV 147523
+%global DATE 20090609
+%global SVNREV 148308
%global gcc_version 4.4.0
# Note, gcc_release must be integer, if you want to add suffixes to
# %{release}, append them after %{gcc_release} on Release: line.
-%global gcc_release 5
+%global gcc_release 7
%global _unpackaged_files_terminate_build 0
%global multilib_64_archs sparc64 ppc64 s390x x86_64
%global include_gappletviewer 1
@@ -157,9 +157,13 @@ Patch25: gcc44-power7.patch
Patch26: gcc44-power7-2.patch
Patch27: gcc44-power7-3.patch
Patch28: gcc44-pr38757.patch
-Patch29: gcc44-pr39856.patch
-Patch30: gcc44-libstdc++-docs.patch
-Patch31: gcc44-pr39942.patch
+Patch29: gcc44-libstdc++-docs.patch
+Patch30: gcc44-atom-mnative.patch
+Patch31: gcc44-atom-movbe.patch
+Patch32: gcc44-ix86-insn-length.patch
+Patch33: gcc44-builtin-object-size.patch
+Patch34: gcc44-epilogue-unwind.patch
+Patch35: gcc44-unwind-debug-hook.patch
Patch1000: fastjar-0.97-segfault.patch
@@ -464,11 +468,15 @@ which are required to compile with the GNAT.
%patch26 -p0 -b .power7-2~
%patch27 -p0 -b .power7-3~
%patch28 -p0 -b .pr38757~
-%patch29 -p0 -b .pr39856~
%if %{build_libstdcxx_docs}
-%patch30 -p0 -b .libstdc++-docs~
+%patch29 -p0 -b .libstdc++-docs~
%endif
-%patch31 -p0 -b .pr39942~
+%patch30 -p0 -b .atom-mnative~
+%patch31 -p0 -b .atom-movbe~
+%patch32 -p0 -b .ix86-insn-length~
+%patch33 -p0 -b .builtin-object-size~
+%patch34 -p0 -b .epilogue-unwind~
+%patch35 -p0 -b .unwind-debug-hook~
# This testcase doesn't compile.
rm libjava/testsuite/libjava.lang/PR35020*
@@ -1803,6 +1811,29 @@ fi
%doc rpm.doc/changelogs/libmudflap/ChangeLog*
%changelog
+* Tue Jun 9 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-7
+- update from gcc-4_4-branch
+ - PRs ada/40166, bootstrap/40027, c++/38064, c++/39754, c++/40007,
+ c++/40139, c/40172, c++/40306, c++/40307, c++/40308, c++/40311,
+ c++/40370, c++/40372, c++/40373, debug/40109, fortran/22423,
+ fortran/38654, fortran/39893, fortran/40019, fortran/40195,
+ libfortran/25561, libfortran/37754, libfortran/38668,
+ libfortran/39665, libfortran/39667, libfortran/39702,
+ libfortran/39709, libfortran/39782, libfortran/40334,
+ libgfortran/39664, libgomp/40174, libstdc++/36211, libstdc++/40192,
+ libstdc++/40296, libstdc++/40299, middle-end/32950, middle-end/40147,
+ middle-end/40204, middle-end/40233, middle-end/40252,
+ middle-end/40291, middle-end/40328, middle-end/40340,
+ rtl-optimization/40105, target/40017, target/40153, target/40266,
+ testsuite/39907, tree-optimization/39999, tree-optimization/40087,
+ tree-optimization/40238, tree-optimization/40254
+- support Atom for -march=native
+- add -mmovbe support for Atom
+- improve ix86 instruction length computation, remove some unneeded padding
+- -D_FORTIFY_SOURCE improvements
+- emit accurate epilogue unwinding information
+- add unwind debug hook for gdb
+
* Thu May 14 2009 Jakub Jelinek <jakub@redhat.com> 4.4.0-5
- update from gcc-4_4-branch
- PRs c++/17395, c/39983, fortran/38863, fortran/38956, fortran/39879,
diff --git a/gcc44-atom-mnative.patch b/gcc44-atom-mnative.patch
new file mode 100644
index 0000000..9c8a7a3
--- /dev/null
+++ b/gcc44-atom-mnative.patch
@@ -0,0 +1,43 @@
+2009-05-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check
+ extended family and model for Intel processors. Support Intel
+ Atom.
+
+--- gcc/config/i386/driver-i386.c (revision 147735)
++++ gcc/config/i386/driver-i386.c (revision 147736)
+@@ -395,9 +395,22 @@ const char *host_detect_local_cpu (int a
+
+ __cpuid (1, eax, ebx, ecx, edx);
+
+- /* We don't care for extended family. */
+ model = (eax >> 4) & 0x0f;
+ family = (eax >> 8) & 0x0f;
++ if (vendor == SIG_INTEL)
++ {
++ unsigned int extended_model, extended_family;
++
++ extended_model = (eax >> 12) & 0xf0;
++ extended_family = (eax >> 20) & 0xff;
++ if (family == 0x0f)
++ {
++ family += extended_family;
++ model += extended_model;
++ }
++ else if (family == 0x06)
++ model += extended_model;
++ }
+
+ has_sse3 = ecx & bit_SSE3;
+ has_ssse3 = ecx & bit_SSSE3;
+@@ -496,8 +509,8 @@ const char *host_detect_local_cpu (int a
+ break;
+ case PROCESSOR_PENTIUMPRO:
+ if (has_longmode)
+- /* It is Core 2 Duo. */
+- cpu = "core2";
++ /* It is Core 2 or Atom. */
++ cpu = (model == 28) ? "atom" : "core2";
+ else if (arch)
+ {
+ if (has_sse3)
diff --git a/gcc44-atom-movbe.patch b/gcc44-atom-movbe.patch
new file mode 100644
index 0000000..74f57b1
--- /dev/null
+++ b/gcc44-atom-movbe.patch
@@ -0,0 +1,301 @@
+2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/cpuid.h (bit_MOVBE): New.
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check movbe.
+
+ * config/i386/i386.c (OPTION_MASK_ISA_MOVBE_SET): New.
+ (OPTION_MASK_ISA_MOVBE_UNSET): Likewise.
+ (ix86_handle_option): Handle OPT_mmovbe.
+ (ix86_target_string): Add -mmovbe.
+ (pta_flags): Add PTA_MOVBE.
+ (processor_alias_table): Add PTA_MOVBE to "atom".
+ (override_options): Handle PTA_MOVBE.
+
+ * config/i386/i386.h (TARGET_MOVBE): New.
+
+ * config/i386/i386.md (bswapsi2): Check TARGET_MOVBE.
+ (*bswapsi_movbe): New.
+ (*bswapdi_movbe): Likewise.
+ (bswapdi2): Renamed to ...
+ (*bswapdi_1): This.
+ (bswapdi2): New expander.
+
+ * config/i386/i386.opt (mmovbe): New.
+
+ * doc/invoke.texi: Document -mmovbe.
+
+ * gcc.target/i386/movbe-1.c: New.
+ * gcc.target/i386/movbe-2.c: Likewise.
+
+--- gcc/doc/invoke.texi (revision 147772)
++++ gcc/doc/invoke.texi (revision 147773)
+@@ -577,7 +577,7 @@ Objective-C and Objective-C++ Dialects}.
+ -mno-wide-multiply -mrtd -malign-double @gol
+ -mpreferred-stack-boundary=@var{num}
+ -mincoming-stack-boundary=@var{num}
+--mcld -mcx16 -msahf -mrecip @gol
++-mcld -mcx16 -msahf -mmovbe -mrecip @gol
+ -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
+ -maes -mpclmul @gol
+ -msse4a -m3dnow -mpopcnt -mabm -msse5 @gol
+@@ -11458,6 +11458,11 @@ SAHF are load and store instructions, re
+ In 64-bit mode, SAHF instruction is used to optimize @code{fmod}, @code{drem}
+ or @code{remainder} built-in functions: see @ref{Other Builtins} for details.
+
++@item -mmovbe
++@opindex mmovbe
++This option will enable GCC to use movbe instruction to implement
++@code{__builtin_bswap32} and @code{__builtin_bswap64}.
++
+ @item -mrecip
+ @opindex mrecip
+ This option will enable GCC to use RCPSS and RSQRTSS instructions (and their
+--- gcc/testsuite/gcc.target/i386/movbe-1.c (revision 0)
++++ gcc/testsuite/gcc.target/i386/movbe-1.c (revision 147773)
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mmovbe" } */
++
++extern int x;
++
++void
++foo (int i)
++{
++ x = __builtin_bswap32 (i);
++}
++
++int
++bar ()
++{
++ return __builtin_bswap32 (x);
++}
++
++/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 } } */
+--- gcc/testsuite/gcc.target/i386/movbe-2.c (revision 0)
++++ gcc/testsuite/gcc.target/i386/movbe-2.c (revision 147773)
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mmovbe" } */
++
++extern long long x;
++
++void
++foo (long long i)
++{
++ x = __builtin_bswap64 (i);
++}
++
++long long
++bar ()
++{
++ return __builtin_bswap64 (x);
++}
++
++/* { dg-final { scan-assembler-times "movbe\[ \t\]" 4 { target ilp32 } } } */
++/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 { target lp64 } } } */
+--- gcc/config/i386/i386.h (revision 147772)
++++ gcc/config/i386/i386.h (revision 147773)
+@@ -59,6 +59,7 @@ see the files COPYING3 and COPYING.RUNTI
+ #define TARGET_ABM OPTION_ISA_ABM
+ #define TARGET_POPCNT OPTION_ISA_POPCNT
+ #define TARGET_SAHF OPTION_ISA_SAHF
++#define TARGET_MOVBE OPTION_ISA_MOVBE
+ #define TARGET_AES OPTION_ISA_AES
+ #define TARGET_PCLMUL OPTION_ISA_PCLMUL
+ #define TARGET_CMPXCHG16B OPTION_ISA_CX16
+--- gcc/config/i386/i386.md (revision 147772)
++++ gcc/config/i386/i386.md (revision 147773)
+@@ -16105,7 +16105,7 @@ (define_expand "bswapsi2"
+ (bswap:SI (match_operand:SI 1 "register_operand" "")))]
+ ""
+ {
+- if (!TARGET_BSWAP)
++ if (!(TARGET_BSWAP || TARGET_MOVBE))
+ {
+ rtx x = operands[0];
+
+@@ -16117,6 +16117,21 @@ (define_expand "bswapsi2"
+ }
+ })
+
++(define_insn "*bswapsi_movbe"
++ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m")
++ (bswap:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,r")))]
++ "TARGET_MOVBE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
++ "@
++ bswap\t%0
++ movbe\t{%1, %0|%0, %1}
++ movbe\t{%1, %0|%0, %1}"
++ [(set_attr "type" "*,imov,imov")
++ (set_attr "modrm" "*,1,1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "prefix_extra" "*,1,1")
++ (set_attr "length" "2,*,*")
++ (set_attr "mode" "SI")])
++
+ (define_insn "*bswapsi_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (bswap:SI (match_operand:SI 1 "register_operand" "0")))]
+@@ -16145,7 +16160,29 @@ (define_insn "bswaphi_lowpart"
+ [(set_attr "length" "4")
+ (set_attr "mode" "HI")])
+
+-(define_insn "bswapdi2"
++(define_expand "bswapdi2"
++ [(set (match_operand:DI 0 "register_operand" "")
++ (bswap:DI (match_operand:DI 1 "register_operand" "")))]
++ "TARGET_64BIT"
++ "")
++
++(define_insn "*bswapdi_movbe"
++ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
++ (bswap:DI (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))]
++ "TARGET_64BIT && TARGET_MOVBE
++ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
++ "@
++ bswap\t%0
++ movbe\t{%1, %0|%0, %1}
++ movbe\t{%1, %0|%0, %1}"
++ [(set_attr "type" "*,imov,imov")
++ (set_attr "modrm" "*,1,1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "prefix_extra" "*,1,1")
++ (set_attr "length" "3,*,*")
++ (set_attr "mode" "DI")])
++
++(define_insn "*bswapdi_1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (bswap:DI (match_operand:DI 1 "register_operand" "0")))]
+ "TARGET_64BIT"
+--- gcc/config/i386/cpuid.h (revision 147772)
++++ gcc/config/i386/cpuid.h (revision 147773)
+@@ -29,6 +29,7 @@
+ #define bit_CMPXCHG16B (1 << 13)
+ #define bit_SSE4_1 (1 << 19)
+ #define bit_SSE4_2 (1 << 20)
++#define bit_MOVBE (1 << 22)
+ #define bit_POPCNT (1 << 23)
+ #define bit_AES (1 << 25)
+ #define bit_XSAVE (1 << 26)
+--- gcc/config/i386/i386.opt (revision 147772)
++++ gcc/config/i386/i386.opt (revision 147773)
+@@ -339,6 +339,10 @@ msahf
+ Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) VarExists Save
+ Support code generation of sahf instruction in 64bit x86-64 code.
+
++mmovbe
++Target Report Mask(ISA_MOVBE) Var(ix86_isa_flags) VarExists Save
++Support code generation of movbe instruction.
++
+ maes
+ Target Report Mask(ISA_AES) Var(ix86_isa_flags) VarExists Save
+ Support AES built-in functions and code generation
+--- gcc/config/i386/driver-i386.c (revision 147772)
++++ gcc/config/i386/driver-i386.c (revision 147773)
+@@ -378,7 +378,7 @@ const char *host_detect_local_cpu (int a
+ /* Extended features */
+ unsigned int has_lahf_lm = 0, has_sse4a = 0;
+ unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0;
+- unsigned int has_sse4_1 = 0, has_sse4_2 = 0;
++ unsigned int has_movbe = 0, has_sse4_1 = 0, has_sse4_2 = 0;
+ unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0;
+ unsigned int has_pclmul = 0;
+
+@@ -408,6 +408,7 @@ const char *host_detect_local_cpu (int a
+ has_sse4_2 = ecx & bit_SSE4_2;
+ has_avx = ecx & bit_AVX;
+ has_cmpxchg16b = ecx & bit_CMPXCHG16B;
++ has_movbe = ecx & bit_MOVBE;
+ has_popcnt = ecx & bit_POPCNT;
+ has_aes = ecx & bit_AES;
+ has_pclmul = ecx & bit_PCLMUL;
+@@ -597,6 +598,8 @@ const char *host_detect_local_cpu (int a
+ options = concat (options, "-mcx16 ", NULL);
+ if (has_lahf_lm)
+ options = concat (options, "-msahf ", NULL);
++ if (has_movbe)
++ options = concat (options, "-mmovbe ", NULL);
+ if (has_aes)
+ options = concat (options, "-maes ", NULL);
+ if (has_pclmul)
+--- gcc/config/i386/i386.c (revision 147772)
++++ gcc/config/i386/i386.c (revision 147773)
+@@ -1965,9 +1965,11 @@ static int ix86_isa_flags_explicit;
+
+ #define OPTION_MASK_ISA_ABM_SET \
+ (OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT)
++
+ #define OPTION_MASK_ISA_POPCNT_SET OPTION_MASK_ISA_POPCNT
+ #define OPTION_MASK_ISA_CX16_SET OPTION_MASK_ISA_CX16
+ #define OPTION_MASK_ISA_SAHF_SET OPTION_MASK_ISA_SAHF
++#define OPTION_MASK_ISA_MOVBE_SET OPTION_MASK_ISA_MOVBE
+
+ /* Define a set of ISAs which aren't available when a given ISA is
+ disabled. MMX and SSE ISAs are handled separately. */
+@@ -2009,6 +2011,7 @@ static int ix86_isa_flags_explicit;
+ #define OPTION_MASK_ISA_POPCNT_UNSET OPTION_MASK_ISA_POPCNT
+ #define OPTION_MASK_ISA_CX16_UNSET OPTION_MASK_ISA_CX16
+ #define OPTION_MASK_ISA_SAHF_UNSET OPTION_MASK_ISA_SAHF
++#define OPTION_MASK_ISA_MOVBE_UNSET OPTION_MASK_ISA_MOVBE
+
+ /* Vectorization library interface and handlers. */
+ tree (*ix86_veclib_handler)(enum built_in_function, tree, tree) = NULL;
+@@ -2299,6 +2302,19 @@ ix86_handle_option (size_t code, const c
+ }
+ return true;
+
++ case OPT_mmovbe:
++ if (value)
++ {
++ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET;
++ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET;
++ }
++ else
++ {
++ ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET;
++ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET;
++ }
++ return true;
++
+ case OPT_maes:
+ if (value)
+ {
+@@ -2361,6 +2377,7 @@ ix86_target_string (int isa, int flags,
+ { "-mmmx", OPTION_MASK_ISA_MMX },
+ { "-mabm", OPTION_MASK_ISA_ABM },
+ { "-mpopcnt", OPTION_MASK_ISA_POPCNT },
++ { "-mmovbe", OPTION_MASK_ISA_MOVBE },
+ { "-maes", OPTION_MASK_ISA_AES },
+ { "-mpclmul", OPTION_MASK_ISA_PCLMUL },
+ };
+@@ -2577,7 +2594,8 @@ override_options (bool main_args_p)
+ PTA_AES = 1 << 17,
+ PTA_PCLMUL = 1 << 18,
+ PTA_AVX = 1 << 19,
+- PTA_FMA = 1 << 20
++ PTA_FMA = 1 << 20,
++ PTA_MOVBE = 1 << 21
+ };
+
+ static struct pta
+@@ -2621,7 +2639,7 @@ override_options (bool main_args_p)
+ | PTA_SSSE3 | PTA_CX16},
+ {"atom", PROCESSOR_ATOM, CPU_ATOM,
+ PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
+- | PTA_SSSE3 | PTA_CX16},
++ | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE},
+ {"geode", PROCESSOR_GEODE, CPU_GEODE,
+ PTA_MMX | PTA_3DNOW | PTA_3DNOW_A |PTA_PREFETCH_SSE},
+ {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX},
+@@ -2935,6 +2953,9 @@ override_options (bool main_args_p)
+ if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF))
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF))
+ ix86_isa_flags |= OPTION_MASK_ISA_SAHF;
++ if (processor_alias_table[i].flags & PTA_MOVBE
++ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE))
++ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE;
+ if (processor_alias_table[i].flags & PTA_AES
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES))
+ ix86_isa_flags |= OPTION_MASK_ISA_AES;
diff --git a/gcc44-builtin-object-size.patch b/gcc44-builtin-object-size.patch
new file mode 100644
index 0000000..3de03a1
--- /dev/null
+++ b/gcc44-builtin-object-size.patch
@@ -0,0 +1,764 @@
+2009-06-08 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-object-size.c (addr_object_size): Add OSI argument.
+ Handle also INDIRECT_REF with SSA_NAME inside of it as base address.
+ (compute_builtin_object_size, expr_object_size): Adjust callers.
+ (plus_stmt_object_size): Call addr_object_size instead of
+ compute_builtin_object_size.
+
+ * gcc.dg/builtin-object-size-2.c (test1): Adjust expected results.
+ * gcc.dg/builtin-object-size-4.c (test1): Adjust expected results.
+ * gcc.dg/builtin-object-size-6.c: New test.
+
+--- gcc/testsuite/gcc.dg/builtin-object-size-4.c (revision 148278)
++++ gcc/testsuite/gcc.dg/builtin-object-size-4.c (revision 148279)
+@@ -130,15 +130,15 @@ test1 (void *q, int x)
+ abort ();
+ if (__builtin_object_size (&vara[5], 3) != 0)
+ abort ();
+- if (__builtin_object_size (&vara[0].a, 3) != 0)
++ if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a))
+ abort ();
+- if (__builtin_object_size (&vara[10].a[0], 3) != 0)
++ if (__builtin_object_size (&vara[10].a[0], 3) != sizeof (vara[0].a))
+ abort ();
+- if (__builtin_object_size (&vara[5].a[4], 3) != 0)
++ if (__builtin_object_size (&vara[5].a[4], 3) != sizeof (vara[0].a) - 4)
+ abort ();
+- if (__builtin_object_size (&vara[5].b, 3) != 0)
++ if (__builtin_object_size (&vara[5].b, 3) != sizeof (vara[0].b))
+ abort ();
+- if (__builtin_object_size (&vara[7].c[7], 3) != 0)
++ if (__builtin_object_size (&vara[7].c[7], 3) != sizeof (vara[0].c) - 7)
+ abort ();
+ if (__builtin_object_size (zerol, 3) != 0)
+ abort ();
+--- gcc/testsuite/gcc.dg/builtin-object-size-2.c (revision 148278)
++++ gcc/testsuite/gcc.dg/builtin-object-size-2.c (revision 148279)
+@@ -130,15 +130,15 @@ test1 (void *q, int x)
+ abort ();
+ if (__builtin_object_size (&vara[5], 1) != (size_t) -1)
+ abort ();
+- if (__builtin_object_size (&vara[0].a, 1) != (size_t) -1)
++ if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a))
+ abort ();
+- if (__builtin_object_size (&vara[10].a[0], 1) != (size_t) -1)
++ if (__builtin_object_size (&vara[10].a[0], 1) != sizeof (vara[0].a))
+ abort ();
+- if (__builtin_object_size (&vara[5].a[4], 1) != (size_t) -1)
++ if (__builtin_object_size (&vara[5].a[4], 1) != sizeof (vara[0].a) - 4)
+ abort ();
+- if (__builtin_object_size (&vara[5].b, 1) != (size_t) -1)
++ if (__builtin_object_size (&vara[5].b, 1) != sizeof (vara[0].b))
+ abort ();
+- if (__builtin_object_size (&vara[7].c[7], 1) != (size_t) -1)
++ if (__builtin_object_size (&vara[7].c[7], 1) != sizeof (vara[0].c) - 7)
+ abort ();
+ if (__builtin_object_size (zerol, 1) != 0)
+ abort ();
+--- gcc/testsuite/gcc.dg/builtin-object-size-6.c (revision 0)
++++ gcc/testsuite/gcc.dg/builtin-object-size-6.c (revision 148279)
+@@ -0,0 +1,435 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++
++typedef __SIZE_TYPE__ size_t;
++extern void abort (void);
++extern void exit (int);
++extern void *malloc (size_t);
++extern void free (void *);
++
++struct A
++{
++ char a[10];
++ int b;
++ char c[10];
++};
++
++void
++__attribute__ ((noinline))
++test1 (struct A *p)
++{
++ char *c;
++ if (__builtin_object_size (&p->a, 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->b, 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->c, 0) != (size_t) -1)
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 0) != (size_t) -1)
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 0) != (size_t) -1)
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 0) != (size_t) -1)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 0) != (size_t) -1)
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
++ abort ();
++ if (__builtin_object_size (&p->c, 1) != (size_t) -1)
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 1) != sizeof (p->a))
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 1) != sizeof (p->a))
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 1) != sizeof (p->a) - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 1) != sizeof (p->b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 1) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&p->a, 2) != 0)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 2) != 0)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 2) != 0)
++ abort ();
++ if (__builtin_object_size (&p->b, 2) != 0)
++ abort ();
++ if (__builtin_object_size (&p->c, 2) != 0)
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 2) != 0)
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 2) != 0)
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 2) != 0)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 2) != 0)
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 2) != 0)
++ abort ();
++ if (__builtin_object_size (&p->a, 3) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[0], 3) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[3], 3) != sizeof (p->a) - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 3) != sizeof (p->b))
++ abort ();
++ if (__builtin_object_size (&p->c, 3) != 0)
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 3) != sizeof (p->a))
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 3) != sizeof (p->a))
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 3) != sizeof (p->a) - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 3) != sizeof (p->b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 3) != 0)
++ abort ();
++}
++
++void
++__attribute__ ((noinline))
++test2 (void)
++{
++ char *c;
++ size_t s = 2 * sizeof (struct A);
++ struct A *p = malloc (2 * sizeof (struct A));
++ if (__builtin_object_size (&p->a, 0) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 0) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 0) != s - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 0) != s - __builtin_offsetof (struct A, b))
++ abort ();
++ if (__builtin_object_size (&p->c, 0) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 0) != s)
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 0) != s)
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 0) != s - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 0) != s - __builtin_offsetof (struct A, b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 0) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
++ abort ();
++ if (__builtin_object_size (&p->c, 1) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 1) != sizeof (p->a))
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 1) != sizeof (p->a))
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 1) != sizeof (p->a) - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 1) != sizeof (p->b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 1) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ if (__builtin_object_size (&p->a, 2) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 2) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 2) != s - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 2) != s - __builtin_offsetof (struct A, b))
++ abort ();
++ if (__builtin_object_size (&p->c, 2) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 2) != s)
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 2) != s)
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 2) != s - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 2) != s - __builtin_offsetof (struct A, b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 2) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ if (__builtin_object_size (&p->a, 3) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[0], 3) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[3], 3) != sizeof (p->a) - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 3) != sizeof (p->b))
++ abort ();
++ if (__builtin_object_size (&p->c, 3) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ c = p->a;
++ if (__builtin_object_size (c, 3) != sizeof (p->a))
++ abort ();
++ c = &p->a[0];
++ if (__builtin_object_size (c, 3) != sizeof (p->a))
++ abort ();
++ c = &p->a[3];
++ if (__builtin_object_size (c, 3) != sizeof (p->a) - 3)
++ abort ();
++ c = (char *) &p->b;
++ if (__builtin_object_size (c, 3) != sizeof (p->b))
++ abort ();
++ c = (char *) &p->c;
++ if (__builtin_object_size (c, 3) != s - __builtin_offsetof (struct A, c))
++ abort ();
++ free (p);
++}
++
++void
++__attribute__ ((noinline))
++test3 (void)
++{
++ char *c;
++ size_t s;
++ struct A *p = malloc (4);
++ if (__builtin_object_size (&p->a, 0) != 4)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 0) != 4)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 0) != 1)
++ abort ();
++ if (__builtin_object_size (&p->b, 0) != 0)
++ abort ();
++ if (__builtin_object_size (&p->c, 0) != 0)
++ abort ();
++ if (__builtin_object_size (&p->a, 1) != 4)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 1) != 4)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 1) != 1)
++ abort ();
++ if (__builtin_object_size (&p->b, 1) != 0)
++ abort ();
++ if (__builtin_object_size (&p->c, 1) != 0)
++ abort ();
++ free (p);
++ s = __builtin_offsetof (struct A, c) + 4;
++ p = malloc (s);
++ if (__builtin_object_size (&p->a, 0) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[0], 0) != s)
++ abort ();
++ if (__builtin_object_size (&p->a[3], 0) != s - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 0) != s - __builtin_offsetof (struct A, b))
++ abort ();
++ if (__builtin_object_size (&p->c, 0) != 4)
++ abort ();
++ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
++ abort ();
++ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
++ abort ();
++ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
++ abort ();
++ if (__builtin_object_size (&p->c, 1) != 4)
++ abort ();
++ free (p);
++}
++
++struct B
++{
++ struct A a[4];
++};
++
++void
++__attribute__ ((noinline))
++test4 (struct B *q, int i)
++{
++ if (__builtin_object_size (&q->a[2].a[2], 1) != sizeof (q->a[0].a) - 2)
++ abort ();
++ if (__builtin_object_size (&q->a[2].c[2], 1) != sizeof (q->a[0].c) - 2)
++ abort ();
++ if (__builtin_object_size (&q->a[3].a[2], 1) != sizeof (q->a[0].a) - 2)
++ abort ();
++ if (__builtin_object_size (&q->a[3].c[2], 1) != sizeof (q->a[0].c) - 2)
++ abort ();
++ if (__builtin_object_size (&q->a[i].a[2], 1) != sizeof (q->a[0].a) - 2)
++ abort ();
++ if (__builtin_object_size (&q->a[i].c[2], 1) != sizeof (q->a[0].c) - 2)
++ abort ();
++}
++
++struct C
++{
++ char a[10];
++ char b;
++};
++
++void
++__attribute__ ((noinline))
++test5 (struct C *c)
++{
++ if (__builtin_object_size (&c->b, 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&c->b, 1) != 1)
++ abort ();
++ if (__builtin_object_size (&c->b, 2) != 0)
++ abort ();
++ if (__builtin_object_size (&c->b, 3) != 1)
++ abort ();
++}
++
++struct D
++{
++ int i;
++ struct D1
++ {
++ char b;
++ char a[10];
++ } j;
++};
++
++void
++__attribute__ ((noinline))
++test6 (struct D *d)
++{
++ if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3)
++ abort ();
++ if (__builtin_object_size (&d->j.a[3], 2) != 0)
++ abort ();
++ if (__builtin_object_size (&d->j.a[3], 3) != sizeof (d->j.a) - 3)
++ abort ();
++}
++
++struct E
++{
++ int i;
++ struct E1
++ {
++ char b;
++ char a[10];
++ } j[1];
++};
++
++void
++__attribute__ ((noinline))
++test7 (struct E *e)
++{
++ if (__builtin_object_size (&e->j[0].a[3], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&e->j[0].a[3], 1) != sizeof (e->j[0].a) - 3)
++ abort ();
++ if (__builtin_object_size (&e->j[0].a[3], 2) != 0)
++ abort ();
++ if (__builtin_object_size (&e->j[0].a[3], 3) != sizeof (e->j[0].a) - 3)
++ abort ();
++ if (__builtin_object_size ((char *) &e->j[0], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size ((char *) &e->j[0], 1) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size ((char *) &e->j[0], 2) != 0)
++ abort ();
++ if (__builtin_object_size ((char *) &e->j[0], 3) != 0)
++ abort ();
++}
++
++union F
++{
++ char a[1];
++ struct F1
++ {
++ char b;
++ char c[10];
++ } d;
++};
++
++void
++__attribute__ ((noinline))
++test8 (union F *f)
++{
++ if (__builtin_object_size (&f->d.c[3], 0) != (size_t) -1)
++ abort ();
++ if (__builtin_object_size (&f->d.c[3], 1) != sizeof (f->d.c) - 3)
++ abort ();
++ if (__builtin_object_size (&f->d.c[3], 2) != 0)
++ abort ();
++ if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3)
++ abort ();
++}
++
++int
++main (void)
++{
++ struct A a, *p = &a;
++ int i = 1;
++ __asm ("" : "+r" (p));
++ test1 (p);
++ test2 ();
++ test3 ();
++ struct B b, *q = &b;
++ __asm ("" : "+r" (q), "+r" (i));
++ test4 (q, i);
++ struct C c, *cp = &c;
++ __asm ("" : "+r" (cp));
++ test5 (cp);
++ struct D d, *dp = &d;
++ __asm ("" : "+r" (dp));
++ test6 (dp);
++ struct E e, *ep = &e;
++ __asm ("" : "+r" (ep));
++ test7 (ep);
++ union F f, *fp = &f;
++ __asm ("" : "+r" (fp));
++ test8 (fp);
++ exit (0);
++}
+--- gcc/tree-object-size.c (revision 148278)
++++ gcc/tree-object-size.c (revision 148279)
+@@ -43,7 +43,8 @@ struct object_size_info
+ static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
+
+ static tree compute_object_offset (const_tree, const_tree);
+-static unsigned HOST_WIDE_INT addr_object_size (const_tree, int);
++static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
++ const_tree, int);
+ static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int);
+ static tree pass_through_call (const_gimple);
+ static void collect_object_sizes_for (struct object_size_info *, tree);
+@@ -152,9 +153,10 @@ compute_object_offset (const_tree expr,
+ If unknown, return unknown[object_size_type]. */
+
+ static unsigned HOST_WIDE_INT
+-addr_object_size (const_tree ptr, int object_size_type)
++addr_object_size (struct object_size_info *osi, const_tree ptr,
++ int object_size_type)
+ {
+- tree pt_var;
++ tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
+
+ gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
+
+@@ -163,58 +165,170 @@ addr_object_size (const_tree ptr, int ob
+ pt_var = get_base_address (pt_var);
+
+ if (pt_var
+- && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
+- && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
+- && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
+- && (unsigned HOST_WIDE_INT)
+- tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
++ && TREE_CODE (pt_var) == INDIRECT_REF
++ && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME
++ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0))))
++ {
++ unsigned HOST_WIDE_INT sz;
++
++ if (!osi)
++ sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
++ object_size_type);
++ else
++ {
++ tree var = TREE_OPERAND (pt_var, 0);
++ if (osi->pass == 0)
++ collect_object_sizes_for (osi, var);
++ if (bitmap_bit_p (computed[object_size_type],
++ SSA_NAME_VERSION (var)))
++ sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
++ else
++ sz = unknown[object_size_type];
++ }
++
++ if (sz != unknown[object_size_type] && sz < offset_limit)
++ pt_var_size = size_int (sz);
++ }
++ else if (pt_var
++ && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST)
++ && TYPE_SIZE_UNIT (TREE_TYPE (pt_var))
++ && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
++ && (unsigned HOST_WIDE_INT)
++ tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
++ < offset_limit)
++ pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
++ else
++ return unknown[object_size_type];
++
++ if (pt_var != TREE_OPERAND (ptr, 0))
+ {
+- tree bytes;
++ tree var;
+
+- if (pt_var != TREE_OPERAND (ptr, 0))
++ if (object_size_type & 1)
+ {
+- tree var;
++ var = TREE_OPERAND (ptr, 0);
+
+- if (object_size_type & 1)
++ while (var != pt_var
++ && TREE_CODE (var) != BIT_FIELD_REF
++ && TREE_CODE (var) != COMPONENT_REF
++ && TREE_CODE (var) != ARRAY_REF
++ && TREE_CODE (var) != ARRAY_RANGE_REF
++ && TREE_CODE (var) != REALPART_EXPR
++ && TREE_CODE (var) != IMAGPART_EXPR)
++ var = TREE_OPERAND (var, 0);
++ if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
++ var = TREE_OPERAND (var, 0);
++ if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
++ || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
++ || (pt_var_size
++ && tree_int_cst_lt (pt_var_size,
++ TYPE_SIZE_UNIT (TREE_TYPE (var)))))
++ var = pt_var;
++ else if (var != pt_var && TREE_CODE (pt_var) == INDIRECT_REF)
+ {
+- var = TREE_OPERAND (ptr, 0);
+-
+- while (var != pt_var
+- && TREE_CODE (var) != BIT_FIELD_REF
+- && TREE_CODE (var) != COMPONENT_REF
+- && TREE_CODE (var) != ARRAY_REF
+- && TREE_CODE (var) != ARRAY_RANGE_REF
+- && TREE_CODE (var) != REALPART_EXPR
+- && TREE_CODE (var) != IMAGPART_EXPR)
+- var = TREE_OPERAND (var, 0);
+- if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
+- var = TREE_OPERAND (var, 0);
+- if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
+- || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
+- || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
+- TYPE_SIZE_UNIT (TREE_TYPE (var))))
++ tree v = var;
++ /* For &X->fld, compute object size only if fld isn't the last
++ field, as struct { int i; char c[1]; } is often used instead
++ of flexible array member. */
++ while (v && v != pt_var)
++ switch (TREE_CODE (v))
++ {
++ case ARRAY_REF:
++ if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
++ && TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
++ {
++ tree domain
++ = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
++ if (domain
++ && TYPE_MAX_VALUE (domain)
++ && TREE_CODE (TYPE_MAX_VALUE (domain))
++ == INTEGER_CST
++ && tree_int_cst_lt (TREE_OPERAND (v, 1),
++ TYPE_MAX_VALUE (domain)))
++ {
++ v = NULL_TREE;
++ break;
++ }
++ }
++ v = TREE_OPERAND (v, 0);
++ break;
++ case REALPART_EXPR:
++ case IMAGPART_EXPR:
++ v = NULL_TREE;
++ break;
++ case COMPONENT_REF:
++ if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
++ == RECORD_TYPE
++ && TREE_CHAIN (TREE_OPERAND (v, 1)))
++ || TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
++ v = NULL_TREE;
++ else
++ {
++ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
++ == RECORD_TYPE)
++ v = TREE_OPERAND (v, 0);
++ while (v && v != pt_var && TREE_CODE (v) == COMPONENT_REF)
++ if (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE
++ && TREE_CODE (TREE_TYPE (v)) != QUAL_UNION_TYPE)
++ break;
++ else
++ v = TREE_OPERAND (v, 0);
++ if (v && v != pt_var)
++ v = NULL_TREE;
++ else
++ v = pt_var;
++ }
++ break;
++ default:
++ v = pt_var;
++ break;
++ }
++ if (v == pt_var)
+ var = pt_var;
+ }
+- else
+- var = pt_var;
++ }
++ else
++ var = pt_var;
+
+- bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
+- if (bytes != error_mark_node)
++ if (var != pt_var)
++ var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
++ else if (!pt_var_size)
++ return unknown[object_size_type];
++ else
++ var_size = pt_var_size;
++ bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
++ if (bytes != error_mark_node)
++ {
++ if (TREE_CODE (bytes) == INTEGER_CST
++ && tree_int_cst_lt (var_size, bytes))
++ bytes = size_zero_node;
++ else
++ bytes = size_binop (MINUS_EXPR, var_size, bytes);
++ }
++ if (var != pt_var
++ && pt_var_size
++ && TREE_CODE (pt_var) == INDIRECT_REF
++ && bytes != error_mark_node)
++ {
++ tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
++ if (bytes2 != error_mark_node)
+ {
+- if (TREE_CODE (bytes) == INTEGER_CST
+- && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
+- bytes = size_zero_node;
++ if (TREE_CODE (bytes2) == INTEGER_CST
++ && tree_int_cst_lt (pt_var_size, bytes2))
++ bytes2 = size_zero_node;
+ else
+- bytes = size_binop (MINUS_EXPR,
+- TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
++ bytes2 = size_binop (MINUS_EXPR, var_size, bytes2);
++ bytes = size_binop (MIN_EXPR, bytes, bytes2);
+ }
+ }
+- else
+- bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
+-
+- if (host_integerp (bytes, 1))
+- return tree_low_cst (bytes, 1);
+ }
++ else if (!pt_var_size)
++ return unknown[object_size_type];
++ else
++ bytes = pt_var_size;
++
++ if (host_integerp (bytes, 1))
++ return tree_low_cst (bytes, 1);
+
+ return unknown[object_size_type];
+ }
+@@ -332,11 +446,11 @@ compute_builtin_object_size (tree ptr, i
+ init_offset_limit ();
+
+ if (TREE_CODE (ptr) == ADDR_EXPR)
+- return addr_object_size (ptr, object_size_type);
++ return addr_object_size (NULL, ptr, object_size_type);
+
+ if (TREE_CODE (ptr) == SSA_NAME
+- && POINTER_TYPE_P (TREE_TYPE (ptr))
+- && object_sizes[object_size_type] != NULL)
++ && POINTER_TYPE_P (TREE_TYPE (ptr))
++ && object_sizes[object_size_type] != NULL)
+ {
+ if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
+ {
+@@ -477,7 +591,7 @@ expr_object_size (struct object_size_inf
+ || !POINTER_TYPE_P (TREE_TYPE (value)));
+
+ if (TREE_CODE (value) == ADDR_EXPR)
+- bytes = addr_object_size (value, object_size_type);
++ bytes = addr_object_size (osi, value, object_size_type);
+ else
+ bytes = unknown[object_size_type];
+
+@@ -633,7 +747,7 @@ plus_stmt_object_size (struct object_siz
+ unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
+
+ /* op0 will be ADDR_EXPR here. */
+- bytes = compute_builtin_object_size (op0, object_size_type);
++ bytes = addr_object_size (osi, op0, object_size_type);
+ if (bytes == unknown[object_size_type])
+ ;
+ else if (off > offset_limit)
diff --git a/gcc44-epilogue-unwind.patch b/gcc44-epilogue-unwind.patch
new file mode 100644
index 0000000..a8c0061
--- /dev/null
+++ b/gcc44-epilogue-unwind.patch
@@ -0,0 +1,3107 @@
+2009-06-08 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (emit_cfa_remember): New variable.
+ (add_fde_cfi): If emit_cfa_remember, recurse to add
+ DW_CFA_remember_state first.
+ (dwarf2out_begin_epilogue): Don't add_fde_cfi DW_CFA_remember_state,
+ instead just set emit_cfa_remember.
+
+2009-06-08 Adam Nemet <anemet@caviumnetworks.com>
+
+ * jump.c (returnjump_p): Handle delayed branches. Add missing
+ function comment.
+
+2009-06-05 Nathan Froyd <froydnj@codesourcery.com>
+
+ * config/rs6000/ppc-asm.h: Protect auto-host.h inclusion and
+ CFI_* definitions with IN_GCC.
+
+2009-06-04 Jakub Jelinek <jakub@redhat.com>
+
+ * config/s390/s390.c (global_not_special_regno_p): New static inline.
+ (save_gprs): Don't tell unwinder when a global register is saved.
+ (s390_emit_epilogue): Emit needed epilogue unwind info.
+
+2009-06-03 Jakub Jelinek <jakub@redhat.com>
+
+ * config/rs6000/rs6000.c (rs6000_emit_stack_reset): Return generated
+ insn if it is changing sp. Use gen_add3_insn instead of
+ conditionally gen_addsi3 and gen_adddi3.
+ (offset_below_red_zone_p): New static inline function.
+ (rs6000_emit_epilogue): Emit needed epilogue unwind info.
+ Use gen_add3_insn instead of conditionally gen_addsi3 and gen_adddi3.
+ * config/rs6000/ppc-asm.h: Include auto-host.h.
+ (CFI_STARTPROC, CFI_ENDPROC, CFI_DEF_CFA_REGISTER, CFI_OFFSET,
+ CFI_RESTORE): Define.
+ * config/rs6000/crtresxgpr.asm: Add unwind info.
+ * config/rs6000/crtresxfpr.asm: Likewise.
+ * config/rs6000/crtresgpr.asm: Likewise.
+ * config/rs6000/crtresfpr.asm: Likewise.
+ * config/rs6000/crtsavgpr.asm: Likewise.
+ * config/rs6000/crtsavfpr.asm: Likewise.
+
+2009-06-01 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (queued_cfa_restores): New static variable.
+ (ix86_add_cfa_restore_note, ix86_add_queued_cfa_restore_notes): New
+ functions.
+ (pro_epilogue_adjust_stack): Call ix86_add_queued_cfa_restore_notes.
+ (ix86_emit_restore_reg_using_pop): Add RED_OFFSET argument.
+ Set RTX_FRAME_RELATED_P immediately after adding a REG_CFA_* note.
+ Call ix86_add_cfa_restore_note instead of adding REG_CFA_OFFSET
+ note unconditionally.
+ (ix86_emit_restore_regs_using_mov): Likewise.
+ (ix86_emit_restore_sse_regs_using_mov): Likewise.
+ (ix86_emit_restore_regs_using_pop): Add RED_OFFSET argument, pass
+ it through to ix86_emit_restore_reg_using_pop.
+ (ix86_emit_leave): Add RED_OFFSET argument. Call
+ ix86_add_queued_cfa_restore_notes. Call ix86_add_cfa_restore_note
+ instead of adding REG_CFA_OFFSET note unconditionally.
+ (ix86_expand_epilogue): Compute RED_OFFSET, pass it down to
+ the above functions. Call ix86_add_queued_cfa_restore_notes when
+ needed.
+
+ * config/i386/i386.h (struct machine_cfa_state,
+ struct machine_function): Guard with ifndef USED_FOR_TARGET
+ instead of not IN_LIBGCC2 and not in IN_TARGET_LIBS.
+
+ PR middle-end/40316
+ * recog.c (peep2_reinit_state): New function.
+ (peephole2_init_state): Use it at the end of a basic block and also
+ when seeing a RTX_FRAME_RELATED_P insn.
+
+2009-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40304
+ * config/i386/i386.c (pro_epilogue_adjust_stack): Mark insns
+ frame related even if !set_cfa && style < 0.
+
+2009-05-29 Richard Henderson <rth@redhat.com>
+
+ * cfgcleanup.c (try_crossjump_to_edge): Only skip past
+ NOTE_INSN_BASIC_BLOCK.
+ * cfglayout.c (duplicate_insn_chain): Copy epilogue insn marks.
+ Duplicate NOTE_INSN_EPILOGUE_BEG notes.
+ * cfgrtl.c (can_delete_note_p): Allow NOTE_INSN_EPILOGUE_BEG
+ to be deleted.
+ * dwarf2out.c (struct cfa_loc): Change indirect field to bitfield,
+ add in_use field.
+ (add_cfi): Disable check redefining cfa away from drap.
+ (lookup_cfa_1): Add remember argument; handle remember/restore.
+ (lookup_cfa): Pass remember argument.
+ (cfa_remember): New.
+ (compute_barrier_args_size_1): Remove sibcall check.
+ (dwarf2out_frame_debug_def_cfa): New.
+ (dwarf2out_frame_debug_adjust_cfa): New.
+ (dwarf2out_frame_debug_cfa_offset): New.
+ (dwarf2out_frame_debug_cfa_register): New.
+ (dwarf2out_frame_debug_cfa_restore): New.
+ (dwarf2out_frame_debug): Handle REG_CFA_* notes.
+ (dwarf2out_begin_epilogue): New.
+ (dwarf2out_frame_debug_restore_state): New.
+ (dw_cfi_oprnd1_desc): Handle DW_CFA_remember_state,
+ DW_CFA_restore_state.
+ (output_cfi_directive): Likewise.
+ (convert_cfa_to_fb_loc_list): Likewise.
+ (dw_cfi_oprnd1_desc): Handle DW_CFA_restore.
+ * dwarf2out.h: Update.
+ * emit-rtl.c (try_split): Don't split RTX_FRAME_RELATED_P.
+ (copy_insn_1): Early out for null.
+ * final.c (final_scan_insn): Call dwarf2out_begin_epilogue
+ and dwarf2out_frame_debug_restore_state.
+ * function.c (prologue, epilogue, sibcall_epilogue): Remove.
+ (prologue_insn_hash, epilogue_insn_hash): New.
+ (free_after_compilation): Adjust freeing accordingly.
+ (record_insns): Create hash table if needed; push insns into
+ hash instead of array.
+ (maybe_copy_epilogue_insn): New.
+ (contains): Search hash table instead of array.
+ (sibcall_epilogue_contains): Remove.
+ (thread_prologue_and_epilogue_insns): Split eh_return insns
+ and mark them as epilogues.
+ (reposition_prologue_and_epilogue_notes): Rewrite epilogue
+ scanning in terms of basic blocks.
+ * insn-notes.def (CFA_RESTORE_STATE): New.
+ * jump.c (returnjump_p_1): Accept EH_RETURN.
+ (eh_returnjump_p_1, eh_returnjump_p): New.
+ * reg-notes.def (CFA_DEF_CFA, CFA_ADJUST_CFA, CFA_OFFSET,
+ CFA_REGISTER, CFA_RESTORE): New.
+ * rtl.def (EH_RETURN): New.
+ * rtl.h (eh_returnjump_p, maybe_copy_epilogue_insn): Declare.
+
+ * config/bfin/bfin.md (UNSPEC_VOLATILE_EH_RETURN): Remove.
+ (eh_return_internal): Use eh_return rtx; split w/ epilogue.
+
+ * config/i386/i386.c (gen_push): Update cfa state.
+ (pro_epilogue_adjust_stack): Add set_cfa argument. When true,
+ add a CFA_ADJUST_CFA note.
+ (ix86_dwarf_handle_frame_unspec): Remove.
+ (ix86_expand_prologue): Update cfa state.
+ (ix86_emit_restore_reg_using_pop): New.
+ (ix86_emit_restore_regs_using_pop): New.
+ (ix86_emit_leave): New.
+ (ix86_emit_restore_regs_using_mov): Add CFA_RESTORE notes.
+ (ix86_expand_epilogue): Add notes for unwinding the epilogue.
+ * config/i386/i386.h (struct machine_cfa_state): New.
+ (ix86_cfa_state): New.
+ * config/i386/i386.md (UNSPEC_EH_RETURN): Remove.
+ (eh_return_internal): Merge from eh_return_<mode>,
+ use eh_return rtx, split w/ epilogue.
+
+--- gcc/rtl.def.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/rtl.def 2009-06-09 08:58:04.000000000 +0200
+@@ -281,6 +281,10 @@ DEF_RTL_EXPR(CALL, "call", "ee", RTX_EXT
+
+ DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
+
++/* Special for EH return from subroutine. */
++
++DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
++
+ /* Conditional trap.
+ Operand 1 is the condition.
+ Operand 2 is the trap code.
+--- gcc/cfglayout.c.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/cfglayout.c 2009-06-09 08:58:04.000000000 +0200
+@@ -1112,7 +1112,7 @@ cfg_layout_can_duplicate_bb_p (const_bas
+ rtx
+ duplicate_insn_chain (rtx from, rtx to)
+ {
+- rtx insn, last;
++ rtx insn, last, copy;
+
+ /* Avoid updating of boundaries of previous basic block. The
+ note will get removed from insn stream in fixup. */
+@@ -1133,7 +1133,8 @@ duplicate_insn_chain (rtx from, rtx to)
+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ break;
+- emit_copy_of_insn_after (insn, get_last_insn ());
++ copy = emit_copy_of_insn_after (insn, get_last_insn ());
++ maybe_copy_epilogue_insn (insn, copy);
+ break;
+
+ case CODE_LABEL:
+@@ -1153,23 +1154,18 @@ duplicate_insn_chain (rtx from, rtx to)
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
+ /* No problem to strip these. */
+- case NOTE_INSN_EPILOGUE_BEG:
+- /* Debug code expect these notes to exist just once.
+- Keep them in the master copy.
+- ??? It probably makes more sense to duplicate them for each
+- epilogue copy. */
+ case NOTE_INSN_FUNCTION_BEG:
+ /* There is always just single entry to function. */
+ case NOTE_INSN_BASIC_BLOCK:
+ break;
+
++ case NOTE_INSN_EPILOGUE_BEG:
+ case NOTE_INSN_SWITCH_TEXT_SECTIONS:
+ emit_note_copy (insn);
+ break;
+
+ default:
+- /* All other notes should have already been eliminated.
+- */
++ /* All other notes should have already been eliminated. */
+ gcc_unreachable ();
+ }
+ break;
+--- gcc/insn-notes.def.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/insn-notes.def 2009-06-09 08:58:04.000000000 +0200
+@@ -70,4 +70,8 @@ INSN_NOTE (BASIC_BLOCK)
+ between hot and cold text sections. */
+ INSN_NOTE (SWITCH_TEXT_SECTIONS)
+
++/* Mark the restore point after an epilogue changed CFI data. Used only
++ when an epilogue appears in the middle of a function. */
++INSN_NOTE (CFA_RESTORE_STATE)
++
+ #undef INSN_NOTE
+--- gcc/cfgcleanup.c.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/cfgcleanup.c 2009-06-09 08:58:04.000000000 +0200
+@@ -1672,8 +1672,7 @@ try_crossjump_to_edge (int mode, edge e1
+ /* Skip possible basic block header. */
+ if (LABEL_P (newpos1))
+ newpos1 = NEXT_INSN (newpos1);
+-
+- if (NOTE_P (newpos1))
++ if (NOTE_INSN_BASIC_BLOCK_P (newpos1))
+ newpos1 = NEXT_INSN (newpos1);
+
+ redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
+--- gcc/reg-notes.def.jj 2009-03-04 12:15:29.000000000 +0100
++++ gcc/reg-notes.def 2009-06-09 08:58:05.000000000 +0200
+@@ -118,6 +118,41 @@ REG_NOTE (BR_PRED)
+ instead of intuition. */
+ REG_NOTE (FRAME_RELATED_EXPR)
+
++/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
++ for FRAME_RELATED_EXPR intuition. The insn's first pattern must be
++ a SET, and the destination must be the CFA register. The attached
++ rtx is an expression that defines the CFA. In the simplest case, the
++ rtx could be just the stack_pointer_rtx; more common would be a PLUS
++ with a base register and a constant offset. In the most complicated
++ cases, this will result in a DW_CFA_def_cfa_expression with the rtx
++ expression rendered in a dwarf location expression. */
++REG_NOTE (CFA_DEF_CFA)
++
++/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
++ for FRAME_RELATED_EXPR intuition. This note adjusts the expression
++ from which the CFA is computed. The attached rtx defines a new CFA
++ expression, relative to the old CFA expression. This rtx must be of
++ the form (SET new-cfa-reg (PLUS old-cfa-reg const_int)). If the note
++ rtx is NULL, we use the first SET of the insn. */
++REG_NOTE (CFA_ADJUST_CFA)
++
++/* Similar to FRAME_RELATED_EXPR, with the additional information that
++ this is a save to memory, i.e. will result in DW_CFA_offset or the
++ like. The pattern or the insn should be a simple store relative to
++ the CFA. */
++REG_NOTE (CFA_OFFSET)
++
++/* Similar to FRAME_RELATED_EXPR, with the additional information that this
++ is a save to a register, i.e. will result in DW_CFA_register. The insn
++ or the pattern should be simple reg-reg move. */
++REG_NOTE (CFA_REGISTER)
++
++/* Attached to insns that are RTX_FRAME_RELATED_P, with the information
++ that this is a restore operation, i.e. will result in DW_CFA_restore
++ or the like. Either the attached rtx, or the destination of the insn's
++ first pattern is the register to be restored. */
++REG_NOTE (CFA_RESTORE)
++
+ /* Indicates that REG holds the exception context for the function.
+ This context is shared by inline functions, so the code to acquire
+ the real exception context is delayed until after inlining. */
+--- gcc/config/i386/i386.md.jj 2009-03-17 20:04:10.000000000 +0100
++++ gcc/config/i386/i386.md 2009-06-09 08:58:04.000000000 +0200
+@@ -84,7 +84,6 @@ (define_constants
+ (UNSPEC_ADD_CARRY 34)
+ (UNSPEC_FLDCW 35)
+ (UNSPEC_REP 36)
+- (UNSPEC_EH_RETURN 37)
+ (UNSPEC_LD_MPIC 38) ; load_macho_picbase
+ (UNSPEC_TRUNC_NOOP 39)
+
+@@ -15379,21 +15378,16 @@ (define_expand "eh_return"
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (tmp, ra);
+
+- if (Pmode == SImode)
+- emit_jump_insn (gen_eh_return_si (sa));
+- else
+- emit_jump_insn (gen_eh_return_di (sa));
++ emit_jump_insn (gen_eh_return_internal ());
+ emit_barrier ();
+ DONE;
+ })
+
+-(define_insn_and_split "eh_return_<mode>"
+- [(set (pc)
+- (unspec [(match_operand:P 0 "register_operand" "c")]
+- UNSPEC_EH_RETURN))]
++(define_insn_and_split "eh_return_internal"
++ [(eh_return)]
+ ""
+ "#"
+- "reload_completed"
++ "epilogue_completed"
+ [(const_int 0)]
+ "ix86_expand_epilogue (2); DONE;")
+
+--- gcc/config/i386/i386.h.jj 2009-04-14 15:51:36.000000000 +0200
++++ gcc/config/i386/i386.h 2009-06-09 09:08:50.000000000 +0200
+@@ -2406,6 +2406,15 @@ enum ix86_stack_slot
+ \f
+ #define FASTCALL_PREFIX '@'
+ \f
++/* Machine specific CFA tracking during prologue/epilogue generation. */
++
++#ifndef USED_FOR_TARGET
++struct machine_cfa_state GTY(())
++{
++ rtx reg;
++ HOST_WIDE_INT offset;
++};
++
+ struct machine_function GTY(())
+ {
+ struct stack_local_entry *stack_locals;
+@@ -2434,7 +2443,9 @@ struct machine_function GTY(())
+ /* This value is used for amd64 targets and specifies the current abi
+ to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */
+ int call_abi;
++ struct machine_cfa_state cfa;
+ };
++#endif
+
+ #define ix86_stack_locals (cfun->machine->stack_locals)
+ #define ix86_varargs_gpr_size (cfun->machine->varargs_gpr_size)
+@@ -2450,6 +2461,7 @@ struct machine_function GTY(())
+ REG_SP is live. */
+ #define ix86_current_function_calls_tls_descriptor \
+ (ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
++#define ix86_cfa_state (&cfun->machine->cfa)
+
+ /* Control behavior of x86_file_start. */
+ #define X86_FILE_START_VERSION_DIRECTIVE false
+--- gcc/config/i386/i386.c.jj 2009-06-09 08:16:00.000000000 +0200
++++ gcc/config/i386/i386.c 2009-06-09 09:09:14.000000000 +0200
+@@ -7480,6 +7480,9 @@ output_set_got (rtx dest, rtx label ATTR
+ static rtx
+ gen_push (rtx arg)
+ {
++ if (ix86_cfa_state->reg == stack_pointer_rtx)
++ ix86_cfa_state->offset += UNITS_PER_WORD;
++
+ return gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (Pmode,
+ gen_rtx_PRE_DEC (Pmode,
+@@ -7539,8 +7542,7 @@ ix86_save_reg (unsigned int regno, int m
+ }
+ }
+
+- if (crtl->drap_reg
+- && regno == REGNO (crtl->drap_reg))
++ if (crtl->drap_reg && regno == REGNO (crtl->drap_reg))
+ return 1;
+
+ return (df_regs_ever_live_p (regno)
+@@ -7869,6 +7871,49 @@ ix86_emit_save_sse_regs_using_mov (rtx p
+ }
+ }
+
++static GTY(()) rtx queued_cfa_restores;
++
++/* Add a REG_CFA_RESTORE REG note to INSN or queue them until next stack
++ manipulation insn. Don't add it if the previously
++ saved value will be left untouched within stack red-zone till return,
++ as unwinders can find the same value in the register and
++ on the stack. */
++
++static void
++ix86_add_cfa_restore_note (rtx insn, rtx reg, HOST_WIDE_INT red_offset)
++{
++ if (TARGET_RED_ZONE
++ && !TARGET_64BIT_MS_ABI
++ && red_offset + RED_ZONE_SIZE >= 0
++ && crtl->args.pops_args < 65536)
++ return;
++
++ if (insn)
++ {
++ add_reg_note (insn, REG_CFA_RESTORE, reg);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++ else
++ queued_cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE, reg, queued_cfa_restores);
++}
++
++/* Add queued REG_CFA_RESTORE notes if any to INSN. */
++
++static void
++ix86_add_queued_cfa_restore_notes (rtx insn)
++{
++ rtx last;
++ if (!queued_cfa_restores)
++ return;
++ for (last = queued_cfa_restores; XEXP (last, 1); last = XEXP (last, 1))
++ ;
++ XEXP (last, 1) = REG_NOTES (insn);
++ REG_NOTES (insn) = queued_cfa_restores;
++ queued_cfa_restores = NULL_RTX;
++ RTX_FRAME_RELATED_P (insn) = 1;
++}
++
+ /* Expand prologue or epilogue stack adjustment.
+ The pattern exist to put a dependency on all ebp-based memory accesses.
+ STYLE should be negative if instructions should be marked as frame related,
+@@ -7876,7 +7921,8 @@ ix86_emit_save_sse_regs_using_mov (rtx p
+ otherwise. */
+
+ static void
+-pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
++pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset,
++ int style, bool set_cfa)
+ {
+ rtx insn;
+
+@@ -7899,7 +7945,24 @@ pro_epilogue_adjust_stack (rtx dest, rtx
+ insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64_2 (dest, src, r11,
+ offset));
+ }
+- if (style < 0)
++
++ if (style >= 0)
++ ix86_add_queued_cfa_restore_notes (insn);
++
++ if (set_cfa)
++ {
++ rtx r;
++
++ gcc_assert (ix86_cfa_state->reg == src);
++ ix86_cfa_state->offset += INTVAL (offset);
++ ix86_cfa_state->reg = dest;
++
++ r = gen_rtx_PLUS (Pmode, src, offset);
++ r = gen_rtx_SET (VOIDmode, dest, r);
++ add_reg_note (insn, REG_CFA_ADJUST_CFA, r);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++ else if (style < 0)
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+@@ -8035,30 +8098,6 @@ ix86_internal_arg_pointer (void)
+ return virtual_incoming_args_rtx;
+ }
+
+-/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
+- This is called from dwarf2out.c to emit call frame instructions
+- for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
+-static void
+-ix86_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
+-{
+- rtx unspec = SET_SRC (pattern);
+- gcc_assert (GET_CODE (unspec) == UNSPEC);
+-
+- switch (index)
+- {
+- case UNSPEC_REG_SAVE:
+- dwarf2out_reg_save_reg (label, XVECEXP (unspec, 0, 0),
+- SET_DEST (pattern));
+- break;
+- case UNSPEC_DEF_CFA:
+- dwarf2out_def_cfa (label, REGNO (SET_DEST (pattern)),
+- INTVAL (XVECEXP (unspec, 0, 0)));
+- break;
+- default:
+- gcc_unreachable ();
+- }
+-}
+-
+ /* Finalize stack_realign_needed flag, which will guide prologue/epilogue
+ to be generated in correct form. */
+ static void
+@@ -8102,6 +8141,10 @@ ix86_expand_prologue (void)
+ /* DRAP should not coexist with stack_realign_fp */
+ gcc_assert (!(crtl->drap_reg && stack_realign_fp));
+
++ /* Initialize CFA state for before the prologue. */
++ ix86_cfa_state->reg = stack_pointer_rtx;
++ ix86_cfa_state->offset = INCOMING_FRAME_SP_OFFSET;
++
+ ix86_compute_frame_layout (&frame);
+
+ /* Emit prologue code to adjust stack alignment and setup DRAP, in case
+@@ -8131,6 +8174,7 @@ ix86_expand_prologue (void)
+
+ insn = emit_insn (gen_rtx_SET (VOIDmode, y, x));
+ RTX_FRAME_RELATED_P (insn) = 1;
++ ix86_cfa_state->reg = crtl->drap_reg;
+
+ /* Align the stack. */
+ insn = emit_insn ((*ix86_gen_andsp) (stack_pointer_rtx,
+@@ -8159,6 +8203,9 @@ ix86_expand_prologue (void)
+
+ insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
++
++ if (ix86_cfa_state->reg == stack_pointer_rtx)
++ ix86_cfa_state->reg = hard_frame_pointer_rtx;
+ }
+
+ if (stack_realign_fp)
+@@ -8197,7 +8244,8 @@ ix86_expand_prologue (void)
+ ;
+ else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT)
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+- GEN_INT (-allocate), -1);
++ GEN_INT (-allocate), -1,
++ ix86_cfa_state->reg == stack_pointer_rtx);
+ else
+ {
+ /* Only valid for Win32. */
+@@ -8225,11 +8273,15 @@ ix86_expand_prologue (void)
+ else
+ insn = gen_allocate_stack_worker_32 (eax, eax);
+ insn = emit_insn (insn);
+- RTX_FRAME_RELATED_P (insn) = 1;
+- t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
+- t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
+- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+- t, REG_NOTES (insn));
++
++ if (ix86_cfa_state->reg == stack_pointer_rtx)
++ {
++ ix86_cfa_state->offset += allocate;
++ t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
++ t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
++ add_reg_note (insn, REG_CFA_ADJUST_CFA, t);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
+
+ if (eax_live)
+ {
+@@ -8336,18 +8388,104 @@ ix86_expand_prologue (void)
+ emit_insn (gen_cld ());
+ }
+
++/* Emit code to restore REG using a POP insn. */
++
++static void
++ix86_emit_restore_reg_using_pop (rtx reg, HOST_WIDE_INT red_offset)
++{
++ rtx insn = emit_insn (ix86_gen_pop1 (reg));
++
++ if (ix86_cfa_state->reg == crtl->drap_reg
++ && REGNO (reg) == REGNO (crtl->drap_reg))
++ {
++ /* Previously we'd represented the CFA as an expression
++ like *(%ebp - 8). We've just popped that value from
++ the stack, which means we need to reset the CFA to
++ the drap register. This will remain until we restore
++ the stack pointer. */
++ add_reg_note (insn, REG_CFA_DEF_CFA, reg);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ return;
++ }
++
++ if (ix86_cfa_state->reg == stack_pointer_rtx)
++ {
++ ix86_cfa_state->offset -= UNITS_PER_WORD;
++ add_reg_note (insn, REG_CFA_ADJUST_CFA,
++ copy_rtx (XVECEXP (PATTERN (insn), 0, 1)));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++
++ /* When the frame pointer is the CFA, and we pop it, we are
++ swapping back to the stack pointer as the CFA. This happens
++ for stack frames that don't allocate other data, so we assume
++ the stack pointer is now pointing at the return address, i.e.
++ the function entry state, which makes the offset be 1 word. */
++ else if (ix86_cfa_state->reg == hard_frame_pointer_rtx
++ && reg == hard_frame_pointer_rtx)
++ {
++ ix86_cfa_state->reg = stack_pointer_rtx;
++ ix86_cfa_state->offset = UNITS_PER_WORD;
++
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++ GEN_INT (UNITS_PER_WORD)));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++
++ ix86_add_cfa_restore_note (insn, reg, red_offset);
++}
++
++/* Emit code to restore saved registers using POP insns. */
++
++static void
++ix86_emit_restore_regs_using_pop (HOST_WIDE_INT red_offset)
++{
++ int regno;
++
++ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
++ if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, false))
++ {
++ ix86_emit_restore_reg_using_pop (gen_rtx_REG (Pmode, regno),
++ red_offset);
++ red_offset += UNITS_PER_WORD;
++ }
++}
++
++/* Emit code and notes for the LEAVE instruction. */
++
++static void
++ix86_emit_leave (HOST_WIDE_INT red_offset)
++{
++ rtx insn = emit_insn (ix86_gen_leave ());
++
++ ix86_add_queued_cfa_restore_notes (insn);
++
++ if (ix86_cfa_state->reg == hard_frame_pointer_rtx)
++ {
++ add_reg_note (insn, REG_CFA_ADJUST_CFA,
++ copy_rtx (XVECEXP (PATTERN (insn), 0, 0)));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ ix86_add_cfa_restore_note (insn, hard_frame_pointer_rtx, red_offset);
++ }
++}
++
+ /* Emit code to restore saved registers using MOV insns. First register
+ is restored from POINTER + OFFSET. */
+ static void
+ ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
++ HOST_WIDE_INT red_offset,
+ int maybe_eh_return)
+ {
+- int regno;
++ unsigned int regno;
+ rtx base_address = gen_rtx_MEM (Pmode, pointer);
++ rtx insn;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, maybe_eh_return))
+ {
++ rtx reg = gen_rtx_REG (Pmode, regno);
++
+ /* Ensure that adjust_address won't be forced to produce pointer
+ out of range allowed by x86-64 instruction set. */
+ if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
+@@ -8360,9 +8498,25 @@ ix86_emit_restore_regs_using_mov (rtx po
+ base_address = gen_rtx_MEM (Pmode, r11);
+ offset = 0;
+ }
+- emit_move_insn (gen_rtx_REG (Pmode, regno),
+- adjust_address (base_address, Pmode, offset));
++ insn = emit_move_insn (reg,
++ adjust_address (base_address, Pmode, offset));
+ offset += UNITS_PER_WORD;
++
++ if (ix86_cfa_state->reg == crtl->drap_reg
++ && regno == REGNO (crtl->drap_reg))
++ {
++ /* Previously we'd represented the CFA as an expression
++ like *(%ebp - 8). We've just popped that value from
++ the stack, which means we need to reset the CFA to
++ the drap register. This will remain until we restore
++ the stack pointer. */
++ add_reg_note (insn, REG_CFA_DEF_CFA, reg);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++ else
++ ix86_add_cfa_restore_note (NULL_RTX, reg, red_offset);
++
++ red_offset += UNITS_PER_WORD;
+ }
+ }
+
+@@ -8370,15 +8524,18 @@ ix86_emit_restore_regs_using_mov (rtx po
+ is restored from POINTER + OFFSET. */
+ static void
+ ix86_emit_restore_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
++ HOST_WIDE_INT red_offset,
+ int maybe_eh_return)
+ {
+ int regno;
+ rtx base_address = gen_rtx_MEM (TImode, pointer);
+- rtx mem;
++ rtx mem, insn;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (SSE_REGNO_P (regno) && ix86_save_reg (regno, maybe_eh_return))
+ {
++ rtx reg = gen_rtx_REG (TImode, regno);
++
+ /* Ensure that adjust_address won't be forced to produce pointer
+ out of range allowed by x86-64 instruction set. */
+ if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
+@@ -8393,8 +8550,12 @@ ix86_emit_restore_sse_regs_using_mov (rt
+ }
+ mem = adjust_address (base_address, TImode, offset);
+ set_mem_align (mem, 128);
+- emit_move_insn (gen_rtx_REG (TImode, regno), mem);
++ insn = emit_move_insn (reg, mem);
+ offset += 16;
++
++ ix86_add_cfa_restore_note (NULL_RTX, reg, red_offset);
++
++ red_offset += 16;
+ }
+ }
+
+@@ -8403,10 +8564,11 @@ ix86_emit_restore_sse_regs_using_mov (rt
+ void
+ ix86_expand_epilogue (int style)
+ {
+- int regno;
+ int sp_valid;
+ struct ix86_frame frame;
+- HOST_WIDE_INT offset;
++ HOST_WIDE_INT offset, red_offset;
++ struct machine_cfa_state cfa_state_save = *ix86_cfa_state;
++ bool using_drap;
+
+ ix86_finalize_stack_realign_flags ();
+
+@@ -8422,6 +8584,9 @@ ix86_expand_epilogue (int style)
+ if (frame_pointer_needed && frame.red_zone_size)
+ emit_insn (gen_memory_blockage ());
+
++ using_drap = crtl->drap_reg && crtl->stack_realign_needed;
++ gcc_assert (!using_drap || ix86_cfa_state->reg == crtl->drap_reg);
++
+ /* Calculate start of saved registers relative to ebp. Special care
+ must be taken for the normal return case of a function using
+ eh_return: the eax and edx registers are marked as saved, but not
+@@ -8432,6 +8597,19 @@ ix86_expand_epilogue (int style)
+ offset *= -UNITS_PER_WORD;
+ offset -= frame.nsseregs * 16 + frame.padding0;
+
++ /* Calculate start of saved registers relative to esp on entry of the
++ function. When realigning stack, this needs to be the most negative
++ value possible at runtime. */
++ red_offset = offset;
++ if (using_drap)
++ red_offset -= crtl->stack_alignment_needed / BITS_PER_UNIT
++ + UNITS_PER_WORD;
++ else if (stack_realign_fp)
++ red_offset -= crtl->stack_alignment_needed / BITS_PER_UNIT
++ - UNITS_PER_WORD;
++ if (frame_pointer_needed)
++ red_offset -= UNITS_PER_WORD;
++
+ /* If we're only restoring one register and sp is not valid then
+ using a move instruction to restore the register since it's
+ less work than reloading sp and popping the register.
+@@ -8446,7 +8624,8 @@ ix86_expand_epilogue (int style)
+ || (TARGET_EPILOGUE_USING_MOVE
+ && cfun->machine->use_fast_prologue_epilogue
+ && ((frame.nregs + frame.nsseregs) > 1 || frame.to_allocate))
+- || (frame_pointer_needed && !(frame.nregs + frame.nsseregs) && frame.to_allocate)
++ || (frame_pointer_needed && !(frame.nregs + frame.nsseregs)
++ && frame.to_allocate)
+ || (frame_pointer_needed && TARGET_USE_LEAVE
+ && cfun->machine->use_fast_prologue_epilogue
+ && (frame.nregs + frame.nsseregs) == 1)
+@@ -8466,22 +8645,32 @@ ix86_expand_epilogue (int style)
+ || stack_realign_fp)
+ {
+ ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
+- frame.to_allocate, style == 2);
++ frame.to_allocate, red_offset,
++ style == 2);
+ ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
+ frame.to_allocate
+ + frame.nsseregs * 16
++ + frame.padding0,
++ red_offset
++ + frame.nsseregs * 16
+ + frame.padding0, style == 2);
+ }
+ else
+ {
+ ix86_emit_restore_sse_regs_using_mov (hard_frame_pointer_rtx,
+- offset, style == 2);
++ offset, red_offset,
++ style == 2);
+ ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
+ offset
+ + frame.nsseregs * 16
++ + frame.padding0,
++ red_offset
++ + frame.nsseregs * 16
+ + frame.padding0, style == 2);
+ }
+
++ red_offset -= offset;
++
+ /* eh_return epilogues need %ecx added to the stack pointer. */
+ if (style == 2)
+ {
+@@ -8494,13 +8683,29 @@ ix86_expand_epilogue (int style)
+ {
+ tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
+ tmp = plus_constant (tmp, UNITS_PER_WORD);
+- emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
++ tmp = emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
+
+ tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
+- emit_move_insn (hard_frame_pointer_rtx, tmp);
++ tmp = emit_move_insn (hard_frame_pointer_rtx, tmp);
++
++ /* Note that we use SA as a temporary CFA, as the return
++ address is at the proper place relative to it. We
++ pretend this happens at the FP restore insn because
++ prior to this insn the FP would be stored at the wrong
++ offset relative to SA, and after this insn we have no
++ other reasonable register to use for the CFA. We don't
++ bother resetting the CFA to the SP for the duration of
++ the return insn. */
++ add_reg_note (tmp, REG_CFA_DEF_CFA,
++ plus_constant (sa, UNITS_PER_WORD));
++ ix86_add_queued_cfa_restore_notes (tmp);
++ add_reg_note (tmp, REG_CFA_RESTORE, hard_frame_pointer_rtx);
++ RTX_FRAME_RELATED_P (tmp) = 1;
++ ix86_cfa_state->reg = sa;
++ ix86_cfa_state->offset = UNITS_PER_WORD;
+
+ pro_epilogue_adjust_stack (stack_pointer_rtx, sa,
+- const0_rtx, style);
++ const0_rtx, style, false);
+ }
+ else
+ {
+@@ -8509,7 +8714,18 @@ ix86_expand_epilogue (int style)
+ + frame.nregs * UNITS_PER_WORD
+ + frame.nsseregs * 16
+ + frame.padding0));
+- emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
++ tmp = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
++ ix86_add_queued_cfa_restore_notes (tmp);
++
++ gcc_assert (ix86_cfa_state->reg == stack_pointer_rtx);
++ if (ix86_cfa_state->offset != UNITS_PER_WORD)
++ {
++ ix86_cfa_state->offset = UNITS_PER_WORD;
++ add_reg_note (tmp, REG_CFA_DEF_CFA,
++ plus_constant (stack_pointer_rtx,
++ UNITS_PER_WORD));
++ RTX_FRAME_RELATED_P (tmp) = 1;
++ }
+ }
+ }
+ else if (!frame_pointer_needed)
+@@ -8518,18 +8734,18 @@ ix86_expand_epilogue (int style)
+ + frame.nregs * UNITS_PER_WORD
+ + frame.nsseregs * 16
+ + frame.padding0),
+- style);
++ style, !using_drap);
+ /* If not an i386, mov & pop is faster than "leave". */
+ else if (TARGET_USE_LEAVE || optimize_function_for_size_p (cfun)
+ || !cfun->machine->use_fast_prologue_epilogue)
+- emit_insn ((*ix86_gen_leave) ());
++ ix86_emit_leave (red_offset);
+ else
+ {
+ pro_epilogue_adjust_stack (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+- const0_rtx, style);
++ const0_rtx, style, !using_drap);
+
+- emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
++ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx, red_offset);
+ }
+ }
+ else
+@@ -8547,32 +8763,36 @@ ix86_expand_epilogue (int style)
+ gcc_assert (!stack_realign_fp);
+ pro_epilogue_adjust_stack (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+- GEN_INT (offset), style);
++ GEN_INT (offset), style, false);
+ ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
+- frame.to_allocate, style == 2);
++ frame.to_allocate, red_offset,
++ style == 2);
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+- GEN_INT (frame.nsseregs * 16), style);
++ GEN_INT (frame.nsseregs * 16),
++ style, false);
+ }
+ else if (frame.to_allocate || frame.nsseregs)
+ {
+ ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
+- frame.to_allocate,
++ frame.to_allocate, red_offset,
+ style == 2);
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (frame.to_allocate
+ + frame.nsseregs * 16
+- + frame.padding0), style);
++ + frame.padding0), style,
++ !using_drap && !frame_pointer_needed);
+ }
+
+- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+- if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, false))
+- emit_insn ((*ix86_gen_pop1) (gen_rtx_REG (Pmode, regno)));
++ ix86_emit_restore_regs_using_pop (red_offset + frame.nsseregs * 16
++ + frame.padding0);
++ red_offset -= offset;
++
+ if (frame_pointer_needed)
+ {
+ /* Leave results in shorter dependency chains on CPUs that are
+ able to grok it fast. */
+ if (TARGET_USE_LEAVE)
+- emit_insn ((*ix86_gen_leave) ());
++ ix86_emit_leave (red_offset);
+ else
+ {
+ /* For stack realigned really happens, recover stack
+@@ -8581,47 +8801,71 @@ ix86_expand_epilogue (int style)
+ if (stack_realign_fp)
+ pro_epilogue_adjust_stack (stack_pointer_rtx,
+ hard_frame_pointer_rtx,
+- const0_rtx, style);
+- emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
++ const0_rtx, style, !using_drap);
++ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx,
++ red_offset);
+ }
+ }
+ }
+
+- if (crtl->drap_reg && crtl->stack_realign_needed)
++ if (using_drap)
+ {
+ int param_ptr_offset = (call_used_regs[REGNO (crtl->drap_reg)]
+ ? 0 : UNITS_PER_WORD);
++ rtx insn;
++
+ gcc_assert (stack_realign_drap);
+- emit_insn ((*ix86_gen_add3) (stack_pointer_rtx,
+- crtl->drap_reg,
+- GEN_INT (-(UNITS_PER_WORD
+- + param_ptr_offset))));
+- if (!call_used_regs[REGNO (crtl->drap_reg)])
+- emit_insn ((*ix86_gen_pop1) (crtl->drap_reg));
+-
++
++ insn = emit_insn ((*ix86_gen_add3) (stack_pointer_rtx,
++ crtl->drap_reg,
++ GEN_INT (-(UNITS_PER_WORD
++ + param_ptr_offset))));
++
++ ix86_cfa_state->reg = stack_pointer_rtx;
++ ix86_cfa_state->offset = UNITS_PER_WORD + param_ptr_offset;
++
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ gen_rtx_PLUS (Pmode, ix86_cfa_state->reg,
++ GEN_INT (ix86_cfa_state->offset)));
++ RTX_FRAME_RELATED_P (insn) = 1;
++
++ if (param_ptr_offset)
++ ix86_emit_restore_reg_using_pop (crtl->drap_reg, -UNITS_PER_WORD);
+ }
+
+ /* Sibcall epilogues don't want a return instruction. */
+ if (style == 0)
+- return;
++ {
++ *ix86_cfa_state = cfa_state_save;
++ return;
++ }
+
+ if (crtl->args.pops_args && crtl->args.size)
+ {
+ rtx popc = GEN_INT (crtl->args.pops_args);
+
+- /* i386 can only pop 64K bytes. If asked to pop more, pop
+- return address, do explicit add, and jump indirectly to the
+- caller. */
++ /* i386 can only pop 64K bytes. If asked to pop more, pop return
++ address, do explicit add, and jump indirectly to the caller. */
+
+ if (crtl->args.pops_args >= 65536)
+ {
+ rtx ecx = gen_rtx_REG (SImode, CX_REG);
++ rtx insn;
+
+ /* There is no "pascal" calling convention in any 64bit ABI. */
+ gcc_assert (!TARGET_64BIT);
+
+- emit_insn (gen_popsi1 (ecx));
+- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
++ insn = emit_insn (gen_popsi1 (ecx));
++ ix86_cfa_state->offset -= UNITS_PER_WORD;
++
++ add_reg_note (insn, REG_CFA_ADJUST_CFA,
++ copy_rtx (XVECEXP (PATTERN (insn), 0, 1)));
++ add_reg_note (insn, REG_CFA_REGISTER,
++ gen_rtx_SET (VOIDmode, ecx, pc_rtx));
++ RTX_FRAME_RELATED_P (insn) = 1;
++
++ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
++ popc, -1, true);
+ emit_jump_insn (gen_return_indirect_internal (ecx));
+ }
+ else
+@@ -8629,6 +8873,10 @@ ix86_expand_epilogue (int style)
+ }
+ else
+ emit_jump_insn (gen_return_internal ());
++
++ /* Restore the state back to the state from the prologue,
++ so that it's correct for the next epilogue. */
++ *ix86_cfa_state = cfa_state_save;
+ }
+
+ /* Reset from the function's potential modifications. */
+@@ -29760,8 +30008,6 @@ ix86_enum_va_list (int idx, const char *
+ #define TARGET_UPDATE_STACK_BOUNDARY ix86_update_stack_boundary
+ #undef TARGET_GET_DRAP_RTX
+ #define TARGET_GET_DRAP_RTX ix86_get_drap_rtx
+-#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
+-#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
+ #undef TARGET_STRICT_ARGUMENT_NAMING
+ #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+
+--- gcc/config/rs6000/crtresxgpr.asm.jj 2009-04-14 15:52:24.000000000 +0200
++++ gcc/config/rs6000/crtresxgpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -38,27 +38,68 @@
+ /* Called with r11 pointing to the stack header word of the caller of the */
+ /* function, just beyond the end of the integer restore area. */
+
++CFI_STARTPROC
++CFI_DEF_CFA_REGISTER (11)
++CFI_OFFSET (65, 4)
++CFI_OFFSET (14, -72)
++CFI_OFFSET (15, -68)
++CFI_OFFSET (16, -64)
++CFI_OFFSET (17, -60)
++CFI_OFFSET (18, -56)
++CFI_OFFSET (19, -52)
++CFI_OFFSET (20, -48)
++CFI_OFFSET (21, -44)
++CFI_OFFSET (22, -40)
++CFI_OFFSET (23, -36)
++CFI_OFFSET (24, -32)
++CFI_OFFSET (25, -28)
++CFI_OFFSET (26, -24)
++CFI_OFFSET (27, -20)
++CFI_OFFSET (28, -16)
++CFI_OFFSET (29, -12)
++CFI_OFFSET (30, -8)
++CFI_OFFSET (31, -4)
+ HIDDEN_FUNC(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */
++CFI_RESTORE (14)
+ HIDDEN_FUNC(_restgpr_15_x) lwz 15,-68(11)
++CFI_RESTORE (15)
+ HIDDEN_FUNC(_restgpr_16_x) lwz 16,-64(11)
++CFI_RESTORE (16)
+ HIDDEN_FUNC(_restgpr_17_x) lwz 17,-60(11)
++CFI_RESTORE (17)
+ HIDDEN_FUNC(_restgpr_18_x) lwz 18,-56(11)
++CFI_RESTORE (18)
+ HIDDEN_FUNC(_restgpr_19_x) lwz 19,-52(11)
++CFI_RESTORE (19)
+ HIDDEN_FUNC(_restgpr_20_x) lwz 20,-48(11)
++CFI_RESTORE (20)
+ HIDDEN_FUNC(_restgpr_21_x) lwz 21,-44(11)
++CFI_RESTORE (21)
+ HIDDEN_FUNC(_restgpr_22_x) lwz 22,-40(11)
++CFI_RESTORE (22)
+ HIDDEN_FUNC(_restgpr_23_x) lwz 23,-36(11)
++CFI_RESTORE (23)
+ HIDDEN_FUNC(_restgpr_24_x) lwz 24,-32(11)
++CFI_RESTORE (24)
+ HIDDEN_FUNC(_restgpr_25_x) lwz 25,-28(11)
++CFI_RESTORE (25)
+ HIDDEN_FUNC(_restgpr_26_x) lwz 26,-24(11)
++CFI_RESTORE (26)
+ HIDDEN_FUNC(_restgpr_27_x) lwz 27,-20(11)
++CFI_RESTORE (27)
+ HIDDEN_FUNC(_restgpr_28_x) lwz 28,-16(11)
++CFI_RESTORE (28)
+ HIDDEN_FUNC(_restgpr_29_x) lwz 29,-12(11)
++CFI_RESTORE (29)
+ HIDDEN_FUNC(_restgpr_30_x) lwz 30,-8(11)
++CFI_RESTORE (30)
+ HIDDEN_FUNC(_restgpr_31_x) lwz 0,4(11)
+ lwz 31,-4(11)
++CFI_RESTORE (31)
+ mtlr 0
++CFI_RESTORE (65)
+ mr 1,11
++CFI_DEF_CFA_REGISTER (1)
+ blr
+ FUNC_END(_restgpr_31_x)
+ FUNC_END(_restgpr_30_x)
+@@ -78,5 +119,6 @@ FUNC_END(_restgpr_17_x)
+ FUNC_END(_restgpr_16_x)
+ FUNC_END(_restgpr_15_x)
+ FUNC_END(_restgpr_14_x)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/rs6000/crtresfpr.asm.jj 2009-04-14 15:52:30.000000000 +0200
++++ gcc/config/rs6000/crtresfpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -38,6 +38,7 @@
+ /* Called with r11 pointing to the stack header word of the caller of the */
+ /* function, just beyond the end of the floating point save area. */
+
++CFI_STARTPROC
+ HIDDEN_FUNC(_restfpr_14) lfd 14,-144(11) /* restore fp registers */
+ HIDDEN_FUNC(_restfpr_15) lfd 15,-136(11)
+ HIDDEN_FUNC(_restfpr_16) lfd 16,-128(11)
+@@ -75,5 +76,6 @@ FUNC_END(_restfpr_17)
+ FUNC_END(_restfpr_16)
+ FUNC_END(_restfpr_15)
+ FUNC_END(_restfpr_14)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/rs6000/crtsavfpr.asm.jj 2009-04-14 15:52:24.000000000 +0200
++++ gcc/config/rs6000/crtsavfpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -38,6 +38,7 @@
+ /* Called with r11 pointing to the stack header word of the caller of the */
+ /* function, just beyond the end of the floating point save area. */
+
++CFI_STARTPROC
+ HIDDEN_FUNC(_savefpr_14) stfd 14,-144(11) /* save fp registers */
+ HIDDEN_FUNC(_savefpr_15) stfd 15,-136(11)
+ HIDDEN_FUNC(_savefpr_16) stfd 16,-128(11)
+@@ -75,5 +76,6 @@ FUNC_END(_savefpr_17)
+ FUNC_END(_savefpr_16)
+ FUNC_END(_savefpr_15)
+ FUNC_END(_savefpr_14)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/rs6000/ppc-asm.h.jj 2009-01-14 12:33:03.000000000 +0100
++++ gcc/config/rs6000/ppc-asm.h 2009-06-09 09:20:04.000000000 +0200
+@@ -172,6 +172,25 @@ GLUE(.L,name): \
+ .size FUNC_NAME(name),GLUE(.L,name)-FUNC_NAME(name)
+ #endif
+
++#ifdef IN_GCC
++/* For HAVE_GAS_CFI_DIRECTIVE. */
++#include "auto-host.h"
++
++#ifdef HAVE_GAS_CFI_DIRECTIVE
++# define CFI_STARTPROC .cfi_startproc
++# define CFI_ENDPROC .cfi_endproc
++# define CFI_OFFSET(reg, off) .cfi_offset reg, off
++# define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
++# define CFI_RESTORE(reg) .cfi_restore reg
++#else
++# define CFI_STARTPROC
++# define CFI_ENDPROC
++# define CFI_OFFSET(reg, off)
++# define CFI_DEF_CFA_REGISTER(reg)
++# define CFI_RESTORE(reg)
++#endif
++#endif
++
+ #if defined __linux__
+ .section .note.GNU-stack
+ .previous
+--- gcc/config/rs6000/crtsavgpr.asm.jj 2009-04-14 15:52:22.000000000 +0200
++++ gcc/config/rs6000/crtsavgpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -38,6 +38,7 @@
+ /* Called with r11 pointing to the stack header word of the caller of the */
+ /* function, just beyond the end of the integer save area. */
+
++CFI_STARTPROC
+ HIDDEN_FUNC(_savegpr_14) stw 14,-72(11) /* save gp registers */
+ HIDDEN_FUNC(_savegpr_15) stw 15,-68(11)
+ HIDDEN_FUNC(_savegpr_16) stw 16,-64(11)
+@@ -75,5 +76,6 @@ FUNC_END(_savegpr_17)
+ FUNC_END(_savegpr_16)
+ FUNC_END(_savegpr_15)
+ FUNC_END(_savegpr_14)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/rs6000/rs6000.c.jj 2009-03-19 17:17:23.000000000 +0100
++++ gcc/config/rs6000/rs6000.c 2009-06-09 09:10:24.000000000 +0200
+@@ -782,7 +782,7 @@ static const char *rs6000_mangle_type (c
+ extern const struct attribute_spec rs6000_attribute_table[];
+ static void rs6000_set_default_type_attributes (tree);
+ static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool);
+-static void rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
++static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
+ static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
+ enum machine_mode, bool, bool, bool);
+ static bool rs6000_reg_live_or_pic_offset_p (int);
+@@ -15918,7 +15918,7 @@ rs6000_savres_routine_sym (rs6000_stack_
+ stack pointer, but move the base of the frame into r11 for use by
+ out-of-line register restore routines. */
+
+-static void
++static rtx
+ rs6000_emit_stack_reset (rs6000_stack_t *info,
+ rtx sp_reg_rtx, rtx frame_reg_rtx,
+ int sp_offset, bool savres)
+@@ -15935,10 +15935,10 @@ rs6000_emit_stack_reset (rs6000_stack_t
+ {
+ rs6000_emit_stack_tie ();
+ if (sp_offset != 0)
+- emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx,
+- GEN_INT (sp_offset)));
++ return emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx,
++ GEN_INT (sp_offset)));
+ else if (!savres)
+- emit_move_insn (sp_reg_rtx, frame_reg_rtx);
++ return emit_move_insn (sp_reg_rtx, frame_reg_rtx);
+ }
+ else if (sp_offset != 0)
+ {
+@@ -15950,12 +15950,12 @@ rs6000_emit_stack_reset (rs6000_stack_t
+ ? gen_rtx_REG (Pmode, 11)
+ : sp_reg_rtx);
+
+- emit_insn (TARGET_32BIT
+- ? gen_addsi3 (dest_reg, sp_reg_rtx,
+- GEN_INT (sp_offset))
+- : gen_adddi3 (dest_reg, sp_reg_rtx,
+- GEN_INT (sp_offset)));
++ rtx insn = emit_insn (gen_add3_insn (dest_reg, sp_reg_rtx,
++ GEN_INT (sp_offset)));
++ if (!savres)
++ return insn;
+ }
++ return NULL_RTX;
+ }
+
+ /* Construct a parallel rtx describing the effect of a call to an
+@@ -16870,12 +16870,19 @@ rs6000_restore_saved_cr (rtx reg, int us
+ }
+ }
+
+-/* Emit function epilogue as insns.
++/* Return true if OFFSET from stack pointer can be clobbered by signals.
++ V.4 doesn't have any stack cushion, AIX ABIs have 220 or 288 bytes
++ below stack pointer not cloberred by signals. */
++
++static inline bool
++offset_below_red_zone_p (HOST_WIDE_INT offset)
++{
++ return offset < (DEFAULT_ABI == ABI_V4
++ ? 0
++ : TARGET_32BIT ? -220 : -288);
++}
+
+- At present, dwarf2out_frame_debug_expr doesn't understand
+- register restores, so we don't bother setting RTX_FRAME_RELATED_P
+- anywhere in the epilogue. Most of the insns below would in any case
+- need special notes to explain where r11 is in relation to the stack. */
++/* Emit function epilogue as insns. */
+
+ void
+ rs6000_emit_epilogue (int sibcall)
+@@ -16891,6 +16898,8 @@ rs6000_emit_epilogue (int sibcall)
+ int sp_offset = 0;
+ rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
+ rtx frame_reg_rtx = sp_reg_rtx;
++ rtx cfa_restores = NULL_RTX;
++ rtx insn;
+ enum machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ int i;
+@@ -17031,7 +17040,7 @@ rs6000_emit_epilogue (int sibcall)
+ && info->altivec_size != 0
+ && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ || (DEFAULT_ABI != ABI_V4
+- && info->altivec_save_offset < (TARGET_32BIT ? -220 : -288))))
++ && offset_below_red_zone_p (info->altivec_save_offset))))
+ {
+ int i;
+
+@@ -17048,7 +17057,7 @@ rs6000_emit_epilogue (int sibcall)
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+- rtx addr, areg, mem;
++ rtx addr, areg, mem, reg;
+
+ areg = gen_rtx_REG (Pmode, 0);
+ emit_move_insn
+@@ -17060,7 +17069,13 @@ rs6000_emit_epilogue (int sibcall)
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
+ mem = gen_frame_mem (V4SImode, addr);
+
+- emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
++ reg = gen_rtx_REG (V4SImode, i);
++ emit_move_insn (reg, mem);
++ if (offset_below_red_zone_p (info->altivec_save_offset
++ + (i - info->first_altivec_reg_save)
++ * 16))
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
+ }
+ }
+
+@@ -17070,7 +17085,7 @@ rs6000_emit_epilogue (int sibcall)
+ && info->vrsave_mask != 0
+ && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ || (DEFAULT_ABI != ABI_V4
+- && info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288))))
++ && offset_below_red_zone_p (info->vrsave_save_offset))))
+ {
+ rtx addr, mem, reg;
+
+@@ -17096,6 +17111,7 @@ rs6000_emit_epilogue (int sibcall)
+ emit_insn (generate_set_vrsave (reg, info, 1));
+ }
+
++ insn = NULL_RTX;
+ /* If we have a large stack frame, restore the old stack pointer
+ using the backchain. */
+ if (use_backchain_to_restore_sp)
+@@ -17107,8 +17123,8 @@ rs6000_emit_epilogue (int sibcall)
+ if (DEFAULT_ABI == ABI_V4)
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+
+- emit_move_insn (frame_reg_rtx,
+- gen_rtx_MEM (Pmode, sp_reg_rtx));
++ insn = emit_move_insn (frame_reg_rtx,
++ gen_rtx_MEM (Pmode, sp_reg_rtx));
+ sp_offset = 0;
+ }
+ else if (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+@@ -17117,7 +17133,7 @@ rs6000_emit_epilogue (int sibcall)
+ ;
+ else
+ {
+- emit_move_insn (sp_reg_rtx, frame_reg_rtx);
++ insn = emit_move_insn (sp_reg_rtx, frame_reg_rtx);
+ frame_reg_rtx = sp_reg_rtx;
+ }
+ }
+@@ -17129,38 +17145,42 @@ rs6000_emit_epilogue (int sibcall)
+ if (DEFAULT_ABI == ABI_V4)
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+
+- emit_insn (TARGET_32BIT
+- ? gen_addsi3 (frame_reg_rtx, hard_frame_pointer_rtx,
+- GEN_INT (info->total_size))
+- : gen_adddi3 (frame_reg_rtx, hard_frame_pointer_rtx,
+- GEN_INT (info->total_size)));
++ insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx,
++ GEN_INT (info->total_size)));
+ sp_offset = 0;
+ }
+ else if (info->push_p
+ && DEFAULT_ABI != ABI_V4
+ && !crtl->calls_eh_return)
+ {
+- emit_insn (TARGET_32BIT
+- ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
+- GEN_INT (info->total_size))
+- : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
+- GEN_INT (info->total_size)));
++ insn = emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx,
++ GEN_INT (info->total_size)));
+ sp_offset = 0;
+ }
++ if (insn && frame_reg_rtx == sp_reg_rtx)
++ {
++ if (cfa_restores)
++ {
++ REG_NOTES (insn) = cfa_restores;
++ cfa_restores = NULL_RTX;
++ }
++ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
+
+ /* Restore AltiVec registers if we have not done so already. */
+ if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ && TARGET_ALTIVEC_ABI
+ && info->altivec_size != 0
+ && (DEFAULT_ABI == ABI_V4
+- || info->altivec_save_offset >= (TARGET_32BIT ? -220 : -288)))
++ || !offset_below_red_zone_p (info->altivec_save_offset)))
+ {
+ int i;
+
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+- rtx addr, areg, mem;
++ rtx addr, areg, mem, reg;
+
+ areg = gen_rtx_REG (Pmode, 0);
+ emit_move_insn
+@@ -17172,7 +17192,11 @@ rs6000_emit_epilogue (int sibcall)
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
+ mem = gen_frame_mem (V4SImode, addr);
+
+- emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
++ reg = gen_rtx_REG (V4SImode, i);
++ emit_move_insn (reg, mem);
++ if (DEFAULT_ABI == ABI_V4)
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
+ }
+ }
+
+@@ -17182,7 +17206,7 @@ rs6000_emit_epilogue (int sibcall)
+ && TARGET_ALTIVEC_VRSAVE
+ && info->vrsave_mask != 0
+ && (DEFAULT_ABI == ABI_V4
+- || info->vrsave_save_offset >= (TARGET_32BIT ? -220 : -288)))
++ || !offset_below_red_zone_p (info->vrsave_save_offset)))
+ {
+ rtx addr, mem, reg;
+
+@@ -17215,7 +17239,8 @@ rs6000_emit_epilogue (int sibcall)
+ emit_move_insn (gen_rtx_REG (SImode, 12), mem);
+ }
+
+- /* Set LR here to try to overlap restores below. */
++ /* Set LR here to try to overlap restores below. LR is always saved
++ above incoming stack, so it never needs REG_CFA_RESTORE. */
+ if (restore_lr)
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
+ gen_rtx_REG (Pmode, 0));
+@@ -17297,7 +17322,7 @@ rs6000_emit_epilogue (int sibcall)
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ if (rs6000_reg_live_or_pic_offset_p (info->first_gp_reg_save + i))
+ {
+- rtx offset, addr, mem;
++ rtx offset, addr, mem, reg;
+
+ /* We're doing all this to ensure that the immediate offset
+ fits into the immediate field of 'evldd'. */
+@@ -17306,9 +17331,24 @@ rs6000_emit_epilogue (int sibcall)
+ offset = GEN_INT (spe_offset + reg_size * i);
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, offset);
+ mem = gen_rtx_MEM (V2SImode, addr);
++ reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
++
++ insn = emit_move_insn (reg, mem);
++ if (DEFAULT_ABI == ABI_V4)
++ {
++ if (frame_pointer_needed
++ && info->first_gp_reg_save + i
++ == HARD_FRAME_POINTER_REGNUM)
++ {
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (frame_reg_rtx,
++ sp_offset));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
+
+- emit_move_insn (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+- mem);
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
++ }
+ }
+ }
+ else
+@@ -17320,7 +17360,6 @@ rs6000_emit_epilogue (int sibcall)
+ /*savep=*/false, /*gpr=*/true,
+ /*exitp=*/true);
+ emit_jump_insn (par);
+-
+ /* We don't want anybody else emitting things after we jumped
+ back. */
+ return;
+@@ -17349,8 +17388,15 @@ rs6000_emit_epilogue (int sibcall)
+ if (can_use_exit)
+ {
+ if (info->cr_save_p)
+- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12),
+- using_mtcr_multiple);
++ {
++ rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12),
++ using_mtcr_multiple);
++ if (DEFAULT_ABI == ABI_V4)
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE,
++ gen_rtx_REG (SImode, CR2_REGNO),
++ cfa_restores);
++ }
+
+ emit_jump_insn (par);
+
+@@ -17358,8 +17404,22 @@ rs6000_emit_epilogue (int sibcall)
+ back. */
+ return;
+ }
+- else
+- emit_insn (par);
++
++ insn = emit_insn (par);
++ if (DEFAULT_ABI == ABI_V4)
++ {
++ if (frame_pointer_needed)
++ {
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (frame_reg_rtx, sp_offset));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
++
++ for (i = info->first_gp_reg_save; i < 32; i++)
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE,
++ gen_rtx_REG (reg_mode, i), cfa_restores);
++ }
+ }
+ else if (using_load_multiple)
+ {
+@@ -17372,13 +17432,20 @@ rs6000_emit_epilogue (int sibcall)
+ + sp_offset
+ + reg_size * i));
+ rtx mem = gen_frame_mem (reg_mode, addr);
++ rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
+
+- RTVEC_ELT (p, i) =
+- gen_rtx_SET (VOIDmode,
+- gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+- mem);
++ RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem);
++ if (DEFAULT_ABI == ABI_V4)
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
++ }
++ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
++ if (DEFAULT_ABI == ABI_V4 && frame_pointer_needed)
++ {
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (frame_reg_rtx, sp_offset));
++ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ }
+ else
+ {
+@@ -17390,9 +17457,23 @@ rs6000_emit_epilogue (int sibcall)
+ + sp_offset
+ + reg_size * i));
+ rtx mem = gen_frame_mem (reg_mode, addr);
++ rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
++
++ insn = emit_move_insn (reg, mem);
++ if (DEFAULT_ABI == ABI_V4)
++ {
++ if (frame_pointer_needed
++ && info->first_gp_reg_save + i
++ == HARD_FRAME_POINTER_REGNUM)
++ {
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (frame_reg_rtx, sp_offset));
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
+
+- emit_move_insn (gen_rtx_REG (reg_mode,
+- info->first_gp_reg_save + i), mem);
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
++ }
+ }
+ }
+
+@@ -17402,36 +17483,52 @@ rs6000_emit_epilogue (int sibcall)
+ if ((df_regs_ever_live_p (info->first_fp_reg_save+i)
+ && ! call_used_regs[info->first_fp_reg_save+i]))
+ {
+- rtx addr, mem;
++ rtx addr, mem, reg;
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->fp_save_offset
+ + sp_offset
+ + 8 * i));
+ mem = gen_frame_mem (((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT)
+ ? DFmode : SFmode), addr);
++ reg = gen_rtx_REG (((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT)
++ ? DFmode : SFmode),
++ info->first_fp_reg_save + i);
+
+- emit_move_insn (gen_rtx_REG (((TARGET_HARD_FLOAT
+- && TARGET_DOUBLE_FLOAT)
+- ? DFmode : SFmode),
+- info->first_fp_reg_save + i),
+- mem);
++ emit_move_insn (reg, mem);
++ if (DEFAULT_ABI == ABI_V4)
++ cfa_restores = alloc_EXPR_LIST (REG_CFA_RESTORE, reg,
++ cfa_restores);
+ }
+
+ /* If we saved cr, restore it here. Just those that were used. */
+ if (info->cr_save_p)
+- rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple);
++ {
++ rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple);
++ if (DEFAULT_ABI == ABI_V4)
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
++ cfa_restores);
++ }
+
+ /* If this is V.4, unwind the stack pointer after all of the loads
+ have been done. */
+- rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
+- sp_offset, !restoring_FPRs_inline);
++ insn = rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
++ sp_offset, !restoring_FPRs_inline);
++ if (insn)
++ {
++ if (cfa_restores)
++ {
++ REG_NOTES (insn) = cfa_restores;
++ cfa_restores = NULL_RTX;
++ }
++ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
++ RTX_FRAME_RELATED_P (insn) = 1;
++ }
+
+ if (crtl->calls_eh_return)
+ {
+ rtx sa = EH_RETURN_STACKADJ_RTX;
+- emit_insn (TARGET_32BIT
+- ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx, sa)
+- : gen_adddi3 (sp_reg_rtx, sp_reg_rtx, sa));
++ emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
+ }
+
+ if (!sibcall)
+--- gcc/config/rs6000/crtresxfpr.asm.jj 2009-04-14 15:52:25.000000000 +0200
++++ gcc/config/rs6000/crtresxfpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -40,27 +40,68 @@
+ /* In addition to restoring the fp registers, it will return to the caller's */
+ /* caller */
+
++CFI_STARTPROC
++CFI_DEF_CFA_REGISTER (11)
++CFI_OFFSET (65, 4)
++CFI_OFFSET (46, -144)
++CFI_OFFSET (47, -136)
++CFI_OFFSET (48, -128)
++CFI_OFFSET (49, -120)
++CFI_OFFSET (50, -112)
++CFI_OFFSET (51, -104)
++CFI_OFFSET (52, -96)
++CFI_OFFSET (53, -88)
++CFI_OFFSET (54, -80)
++CFI_OFFSET (55, -72)
++CFI_OFFSET (56, -64)
++CFI_OFFSET (57, -56)
++CFI_OFFSET (58, -48)
++CFI_OFFSET (59, -40)
++CFI_OFFSET (60, -32)
++CFI_OFFSET (61, -24)
++CFI_OFFSET (62, -16)
++CFI_OFFSET (63, -8)
+ HIDDEN_FUNC(_restfpr_14_x) lfd 14,-144(11) /* restore fp registers */
++CFI_RESTORE (46)
+ HIDDEN_FUNC(_restfpr_15_x) lfd 15,-136(11)
++CFI_RESTORE (47)
+ HIDDEN_FUNC(_restfpr_16_x) lfd 16,-128(11)
++CFI_RESTORE (48)
+ HIDDEN_FUNC(_restfpr_17_x) lfd 17,-120(11)
++CFI_RESTORE (49)
+ HIDDEN_FUNC(_restfpr_18_x) lfd 18,-112(11)
++CFI_RESTORE (50)
+ HIDDEN_FUNC(_restfpr_19_x) lfd 19,-104(11)
++CFI_RESTORE (51)
+ HIDDEN_FUNC(_restfpr_20_x) lfd 20,-96(11)
++CFI_RESTORE (52)
+ HIDDEN_FUNC(_restfpr_21_x) lfd 21,-88(11)
++CFI_RESTORE (53)
+ HIDDEN_FUNC(_restfpr_22_x) lfd 22,-80(11)
++CFI_RESTORE (54)
+ HIDDEN_FUNC(_restfpr_23_x) lfd 23,-72(11)
++CFI_RESTORE (55)
+ HIDDEN_FUNC(_restfpr_24_x) lfd 24,-64(11)
++CFI_RESTORE (56)
+ HIDDEN_FUNC(_restfpr_25_x) lfd 25,-56(11)
++CFI_RESTORE (57)
+ HIDDEN_FUNC(_restfpr_26_x) lfd 26,-48(11)
++CFI_RESTORE (58)
+ HIDDEN_FUNC(_restfpr_27_x) lfd 27,-40(11)
++CFI_RESTORE (59)
+ HIDDEN_FUNC(_restfpr_28_x) lfd 28,-32(11)
++CFI_RESTORE (60)
+ HIDDEN_FUNC(_restfpr_29_x) lfd 29,-24(11)
++CFI_RESTORE (61)
+ HIDDEN_FUNC(_restfpr_30_x) lfd 30,-16(11)
++CFI_RESTORE (62)
+ HIDDEN_FUNC(_restfpr_31_x) lwz 0,4(11)
+ lfd 31,-8(11)
++CFI_RESTORE (63)
+ mtlr 0
++CFI_RESTORE (65)
+ mr 1,11
++CFI_DEF_CFA_REGISTER (1)
+ blr
+ FUNC_END(_restfpr_31_x)
+ FUNC_END(_restfpr_30_x)
+@@ -80,5 +121,6 @@ FUNC_END(_restfpr_17_x)
+ FUNC_END(_restfpr_16_x)
+ FUNC_END(_restfpr_15_x)
+ FUNC_END(_restfpr_14_x)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/rs6000/crtresgpr.asm.jj 2009-04-14 15:52:24.000000000 +0200
++++ gcc/config/rs6000/crtresgpr.asm 2009-06-09 09:10:24.000000000 +0200
+@@ -38,6 +38,7 @@
+ /* Called with r11 pointing to the stack header word of the caller of the */
+ /* function, just beyond the end of the integer restore area. */
+
++CFI_STARTPROC
+ HIDDEN_FUNC(_restgpr_14) lwz 14,-72(11) /* restore gp registers */
+ HIDDEN_FUNC(_restgpr_15) lwz 15,-68(11)
+ HIDDEN_FUNC(_restgpr_16) lwz 16,-64(11)
+@@ -75,5 +76,6 @@ FUNC_END(_restgpr_17)
+ FUNC_END(_restgpr_16)
+ FUNC_END(_restgpr_15)
+ FUNC_END(_restgpr_14)
++CFI_ENDPROC
+
+ #endif
+--- gcc/config/s390/s390.c.jj 2009-03-04 12:12:30.000000000 +0100
++++ gcc/config/s390/s390.c 2009-06-09 09:19:20.000000000 +0200
+@@ -7428,6 +7428,21 @@ restore_fpr (rtx base, int offset, int r
+ return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
+ }
+
++/* Return true if REGNO is a global register, but not one
++ of the special ones that need to be saved/restored in anyway. */
++
++static inline bool
++global_not_special_regno_p (int regno)
++{
++ return (global_regs[regno]
++ /* These registers are special and need to be
++ restored in any case. */
++ && !(regno == STACK_POINTER_REGNUM
++ || regno == RETURN_REGNUM
++ || regno == BASE_REGNUM
++ || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM)));
++}
++
+ /* Generate insn to save registers FIRST to LAST into
+ the register save area located at offset OFFSET
+ relative to register BASE. */
+@@ -7451,7 +7466,8 @@ save_gprs (rtx base, int offset, int fir
+ else
+ insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
+
+- RTX_FRAME_RELATED_P (insn) = 1;
++ if (!global_not_special_regno_p (first))
++ RTX_FRAME_RELATED_P (insn) = 1;
+ return insn;
+ }
+
+@@ -7481,30 +7497,41 @@ save_gprs (rtx base, int offset, int fir
+ set, even if it does not. Therefore we emit a new pattern
+ without those registers as REG_FRAME_RELATED_EXPR note. */
+
+- if (first >= 6)
++ if (first >= 6 && !global_not_special_regno_p (first))
+ {
+ rtx pat = PATTERN (insn);
+
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+- if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
++ if (GET_CODE (XVECEXP (pat, 0, i)) == SET
++ && !global_not_special_regno_p (REGNO (SET_SRC (XVECEXP (pat,
++ 0, i)))))
+ RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (last >= 6)
+ {
+- addr = plus_constant (base, offset + (6 - first) * UNITS_PER_WORD);
++ int start;
++
++ for (start = first >= 6 ? first : 6; start <= last; start++)
++ if (!global_not_special_regno_p (start))
++ break;
++
++ if (start > last)
++ return insn;
++
++ addr = plus_constant (base, offset + (start - first) * UNITS_PER_WORD);
+ note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
+- gen_rtx_REG (Pmode, 6),
+- GEN_INT (last - 6 + 1));
++ gen_rtx_REG (Pmode, start),
++ GEN_INT (last - start + 1));
+ note = PATTERN (note);
+
+- REG_NOTES (insn) =
+- gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+- note, REG_NOTES (insn));
++ add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
+
+ for (i = 0; i < XVECLEN (note, 0); i++)
+- if (GET_CODE (XVECEXP (note, 0, i)) == SET)
++ if (GET_CODE (XVECEXP (note, 0, i)) == SET
++ && !global_not_special_regno_p (REGNO (SET_SRC (XVECEXP (note,
++ 0, i)))))
+ RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1;
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+@@ -7894,7 +7921,7 @@ s390_emit_prologue (void)
+ void
+ s390_emit_epilogue (bool sibcall)
+ {
+- rtx frame_pointer, return_reg;
++ rtx frame_pointer, return_reg, cfa_restores = NULL_RTX;
+ int area_bottom, area_top, offset = 0;
+ int next_offset;
+ rtvec p;
+@@ -7936,11 +7963,13 @@ s390_emit_epilogue (bool sibcall)
+ }
+ else
+ {
+- rtx insn, frame_off;
++ rtx insn, frame_off, cfa;
+
+ offset = area_bottom < 0 ? -area_bottom : 0;
+ frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
+
++ cfa = gen_rtx_SET (VOIDmode, frame_pointer,
++ gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
+ if (DISP_IN_RANGE (INTVAL (frame_off)))
+ {
+ insn = gen_rtx_SET (VOIDmode, frame_pointer,
+@@ -7955,6 +7984,8 @@ s390_emit_epilogue (bool sibcall)
+ insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
+ annotate_constant_pool_refs (&PATTERN (insn));
+ }
++ add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa);
++ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Restore call saved fprs. */
+@@ -7970,6 +8001,9 @@ s390_emit_epilogue (bool sibcall)
+ {
+ restore_fpr (frame_pointer,
+ offset + next_offset, i);
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE,
++ gen_rtx_REG (DFmode, i), cfa_restores);
+ next_offset += 8;
+ }
+ }
+@@ -7985,6 +8019,9 @@ s390_emit_epilogue (bool sibcall)
+ {
+ restore_fpr (frame_pointer,
+ offset + next_offset, i);
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE,
++ gen_rtx_REG (DFmode, i), cfa_restores);
+ next_offset += 8;
+ }
+ else if (!TARGET_PACKED_STACK)
+@@ -8011,15 +8048,7 @@ s390_emit_epilogue (bool sibcall)
+ i <= cfun_frame_layout.last_restore_gpr;
+ i++)
+ {
+- /* These registers are special and need to be
+- restored in any case. */
+- if (i == STACK_POINTER_REGNUM
+- || i == RETURN_REGNUM
+- || i == BASE_REGNUM
+- || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
+- continue;
+-
+- if (global_regs[i])
++ if (global_not_special_regno_p (i))
+ {
+ addr = plus_constant (frame_pointer,
+ offset + cfun_frame_layout.gprs_offset
+@@ -8029,6 +8058,10 @@ s390_emit_epilogue (bool sibcall)
+ set_mem_alias_set (addr, get_frame_alias_set ());
+ emit_move_insn (addr, gen_rtx_REG (Pmode, i));
+ }
++ else
++ cfa_restores
++ = alloc_EXPR_LIST (REG_CFA_RESTORE,
++ gen_rtx_REG (Pmode, i), cfa_restores);
+ }
+
+ if (! sibcall)
+@@ -8063,7 +8096,11 @@ s390_emit_epilogue (bool sibcall)
+ * UNITS_PER_WORD,
+ cfun_frame_layout.first_restore_gpr,
+ cfun_frame_layout.last_restore_gpr);
+- emit_insn (insn);
++ insn = emit_insn (insn);
++ REG_NOTES (insn) = cfa_restores;
++ add_reg_note (insn, REG_CFA_DEF_CFA,
++ plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET));
++ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (! sibcall)
+--- gcc/config/bfin/bfin.md.jj 2009-03-04 12:15:28.000000000 +0100
++++ gcc/config/bfin/bfin.md 2009-06-09 08:58:05.000000000 +0200
+@@ -141,8 +141,7 @@ (define_constants
+ (UNSPEC_ONES 12)])
+
+ (define_constants
+- [(UNSPEC_VOLATILE_EH_RETURN 0)
+- (UNSPEC_VOLATILE_CSYNC 1)
++ [(UNSPEC_VOLATILE_CSYNC 1)
+ (UNSPEC_VOLATILE_SSYNC 2)
+ (UNSPEC_VOLATILE_LOAD_FUNCDESC 3)
+ (UNSPEC_VOLATILE_STORE_EH_HANDLER 4)
+@@ -2740,8 +2739,7 @@ (define_expand "sibcall_epilogue"
+ "bfin_expand_epilogue (0, 0, 1); DONE;")
+
+ (define_expand "eh_return"
+- [(unspec_volatile [(match_operand:SI 0 "register_operand" "")]
+- UNSPEC_VOLATILE_EH_RETURN)]
++ [(use (match_operand:SI 0 "register_operand" ""))]
+ ""
+ {
+ emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0]));
+@@ -2759,11 +2757,10 @@ (define_insn "eh_store_handler"
+ [(set_attr "type" "mcst")])
+
+ (define_insn_and_split "eh_return_internal"
+- [(set (pc)
+- (unspec_volatile [(reg:SI REG_P2)] UNSPEC_VOLATILE_EH_RETURN))]
++ [(eh_return)]
+ ""
+ "#"
+- "reload_completed"
++ "epilogue_completed"
+ [(const_int 1)]
+ "bfin_expand_epilogue (1, 1, 0); DONE;")
+
+--- gcc/dwarf2out.c.jj 2009-06-09 08:13:58.000000000 +0200
++++ gcc/dwarf2out.c 2009-06-09 09:22:55.000000000 +0200
+@@ -250,7 +250,8 @@ typedef struct cfa_loc GTY(())
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT base_offset;
+ unsigned int reg;
+- int indirect; /* 1 if CFA is accessed via a dereference. */
++ BOOL_BITFIELD indirect : 1; /* 1 if CFA is accessed via a dereference. */
++ BOOL_BITFIELD in_use : 1; /* 1 if a saved cfa is stored here. */
+ } dw_cfa_location;
+
+ /* All call frame descriptions (FDE's) in the GCC generated DWARF
+@@ -409,7 +410,7 @@ static const char *dwarf_cfi_name (unsig
+ static dw_cfi_ref new_cfi (void);
+ static void add_cfi (dw_cfi_ref *, dw_cfi_ref);
+ static void add_fde_cfi (const char *, dw_cfi_ref);
+-static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *);
++static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *, dw_cfa_location *);
+ static void lookup_cfa (dw_cfa_location *);
+ static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
+ #ifdef DWARF2_UNWIND_INFO
+@@ -673,7 +674,10 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_r
+
+ /* When DRAP is used, CFA is defined with an expression. Redefine
+ CFA may lead to a different CFA value. */
+- if (fde && fde->drap_reg != INVALID_REGNUM)
++ /* ??? Of course, this heuristic fails when we're annotating epilogues,
++ because of course we'll always want to redefine the CFA back to the
++ stack pointer on the way out. Where should we move this check? */
++ if (0 && fde && fde->drap_reg != INVALID_REGNUM)
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_def_cfa_register:
+@@ -718,13 +722,29 @@ dwarf2out_cfi_label (bool force)
+ return label;
+ }
+
++/* True if remember_state should be emitted before following CFI directive. */
++static bool emit_cfa_remember;
++
+ /* Add CFI to the current fde at the PC value indicated by LABEL if specified,
+ or to the CIE if LABEL is NULL. */
+
+ static void
+ add_fde_cfi (const char *label, dw_cfi_ref cfi)
+ {
+- dw_cfi_ref *list_head = &cie_cfi_head;
++ dw_cfi_ref *list_head;
++
++ if (emit_cfa_remember)
++ {
++ dw_cfi_ref cfi_remember;
++
++ /* Emit the state save. */
++ emit_cfa_remember = false;
++ cfi_remember = new_cfi ();
++ cfi_remember->dw_cfi_opc = DW_CFA_remember_state;
++ add_fde_cfi (label, cfi_remember);
++ }
++
++ list_head = &cie_cfi_head;
+
+ if (dwarf2out_do_cfi_asm ())
+ {
+@@ -828,7 +848,7 @@ add_fde_cfi (const char *label, dw_cfi_r
+ /* Subroutine of lookup_cfa. */
+
+ static void
+-lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
++lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
+ {
+ switch (cfi->dw_cfi_opc)
+ {
+@@ -847,6 +867,18 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_loc
+ case DW_CFA_def_cfa_expression:
+ get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
+ break;
++
++ case DW_CFA_remember_state:
++ gcc_assert (!remember->in_use);
++ *remember = *loc;
++ remember->in_use = 1;
++ break;
++ case DW_CFA_restore_state:
++ gcc_assert (remember->in_use);
++ *loc = *remember;
++ remember->in_use = 0;
++ break;
++
+ default:
+ break;
+ }
+@@ -859,19 +891,19 @@ lookup_cfa (dw_cfa_location *loc)
+ {
+ dw_cfi_ref cfi;
+ dw_fde_ref fde;
++ dw_cfa_location remember;
+
++ memset (loc, 0, sizeof (*loc));
+ loc->reg = INVALID_REGNUM;
+- loc->offset = 0;
+- loc->indirect = 0;
+- loc->base_offset = 0;
++ remember = *loc;
+
+ for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
+- lookup_cfa_1 (cfi, loc);
++ lookup_cfa_1 (cfi, loc, &remember);
+
+ fde = current_fde ();
+ if (fde)
+ for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
+- lookup_cfa_1 (cfi, loc);
++ lookup_cfa_1 (cfi, loc, &remember);
+ }
+
+ /* The current rule for calculating the DWARF2 canonical frame address. */
+@@ -881,6 +913,9 @@ static dw_cfa_location cfa;
+ from the CFA. */
+ static dw_cfa_location cfa_store;
+
++/* The current save location around an epilogue. */
++static dw_cfa_location cfa_remember;
++
+ /* The running total of the size of arguments pushed onto the stack. */
+ static HOST_WIDE_INT args_size;
+
+@@ -1266,8 +1301,7 @@ compute_barrier_args_size_1 (rtx insn, H
+
+ if (! RTX_FRAME_RELATED_P (insn))
+ {
+- if (prologue_epilogue_contains (insn)
+- || sibcall_epilogue_contains (insn))
++ if (prologue_epilogue_contains (insn))
+ /* Nothing */;
+ else if (GET_CODE (PATTERN (insn)) == SET)
+ offset = stack_adjust_offset (PATTERN (insn), cur_args_size, 0);
+@@ -1440,7 +1474,7 @@ dwarf2out_stack_adjust (rtx insn, bool a
+ with this function. Proper support would require all frame-related
+ insns to be marked, and to be able to handle saving state around
+ epilogues textually in the middle of the function. */
+- if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
++ if (prologue_epilogue_contains (insn))
+ return;
+
+ /* If INSN is an instruction from target of an annulled branch, the
+@@ -1715,6 +1749,156 @@ reg_saved_in (rtx reg)
+ value, not an offset. */
+ static dw_cfa_location cfa_temp;
+
++/* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note. */
++
++static void
++dwarf2out_frame_debug_def_cfa (rtx pat, const char *label)
++{
++ memset (&cfa, 0, sizeof (cfa));
++
++ switch (GET_CODE (pat))
++ {
++ case PLUS:
++ cfa.reg = REGNO (XEXP (pat, 0));
++ cfa.offset = INTVAL (XEXP (pat, 1));
++ break;
++
++ case REG:
++ cfa.reg = REGNO (pat);
++ break;
++
++ default:
++ /* Recurse and define an expression. */
++ gcc_unreachable ();
++ }
++
++ def_cfa_1 (label, &cfa);
++}
++
++/* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */
++
++static void
++dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label)
++{
++ rtx src, dest;
++
++ gcc_assert (GET_CODE (pat) == SET);
++ dest = XEXP (pat, 0);
++ src = XEXP (pat, 1);
++
++ switch (GET_CODE (src))
++ {
++ case PLUS:
++ gcc_assert (REGNO (XEXP (src, 0)) == cfa.reg);
++ cfa.offset -= INTVAL (XEXP (src, 1));
++ break;
++
++ case REG:
++ break;
++
++ default:
++ gcc_unreachable ();
++ }
++
++ cfa.reg = REGNO (dest);
++ gcc_assert (cfa.indirect == 0);
++
++ def_cfa_1 (label, &cfa);
++}
++
++/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note. */
++
++static void
++dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
++{
++ HOST_WIDE_INT offset;
++ rtx src, addr, span;
++
++ src = XEXP (set, 1);
++ addr = XEXP (set, 0);
++ gcc_assert (MEM_P (addr));
++ addr = XEXP (addr, 0);
++
++ /* As documented, only consider extremely simple addresses. */
++ switch (GET_CODE (addr))
++ {
++ case REG:
++ gcc_assert (REGNO (addr) == cfa.reg);
++ offset = -cfa.offset;
++ break;
++ case PLUS:
++ gcc_assert (REGNO (XEXP (addr, 0)) == cfa.reg);
++ offset = INTVAL (XEXP (addr, 1)) - cfa.offset;
++ break;
++ default:
++ gcc_unreachable ();
++ }
++
++ span = targetm.dwarf_register_span (src);
++
++ /* ??? We'd like to use queue_reg_save, but we need to come up with
++ a different flushing heuristic for epilogues. */
++ if (!span)
++ reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
++ else
++ {
++ /* We have a PARALLEL describing where the contents of SRC live.
++ Queue register saves for each piece of the PARALLEL. */
++ int par_index;
++ int limit;
++ HOST_WIDE_INT span_offset = offset;
++
++ gcc_assert (GET_CODE (span) == PARALLEL);
++
++ limit = XVECLEN (span, 0);
++ for (par_index = 0; par_index < limit; par_index++)
++ {
++ rtx elem = XVECEXP (span, 0, par_index);
++
++ reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
++ INVALID_REGNUM, span_offset);
++ span_offset += GET_MODE_SIZE (GET_MODE (elem));
++ }
++ }
++}
++
++/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note. */
++
++static void
++dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
++{
++ rtx src, dest;
++ unsigned sregno, dregno;
++
++ src = XEXP (set, 1);
++ dest = XEXP (set, 0);
++
++ if (src == pc_rtx)
++ sregno = DWARF_FRAME_RETURN_COLUMN;
++ else
++ sregno = DWARF_FRAME_REGNUM (REGNO (src));
++
++ dregno = DWARF_FRAME_REGNUM (REGNO (dest));
++
++ /* ??? We'd like to use queue_reg_save, but we need to come up with
++ a different flushing heuristic for epilogues. */
++ reg_save (label, sregno, dregno, 0);
++}
++
++/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
++
++static void
++dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
++{
++ dw_cfi_ref cfi = new_cfi ();
++ unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg));
++
++ cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
++ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
++
++ add_fde_cfi (label, cfi);
++}
++
+ /* Record call frame debugging information for an expression EXPR,
+ which either sets SP or FP (adjusting how we calculate the frame
+ address) or saves a register to the stack or another register.
+@@ -2422,7 +2606,8 @@ void
+ dwarf2out_frame_debug (rtx insn, bool after_p)
+ {
+ const char *label;
+- rtx src;
++ rtx note, n;
++ bool handled_one = false;
+
+ if (insn == NULL_RTX)
+ {
+@@ -2467,15 +2652,154 @@ dwarf2out_frame_debug (rtx insn, bool af
+ }
+
+ label = dwarf2out_cfi_label (false);
+- src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+- if (src)
+- insn = XEXP (src, 0);
+- else
+- insn = PATTERN (insn);
+
++ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
++ switch (REG_NOTE_KIND (note))
++ {
++ case REG_FRAME_RELATED_EXPR:
++ insn = XEXP (note, 0);
++ goto found;
++
++ case REG_CFA_DEF_CFA:
++ dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label);
++ handled_one = true;
++ break;
++
++ case REG_CFA_ADJUST_CFA:
++ n = XEXP (note, 0);
++ if (n == NULL)
++ {
++ n = PATTERN (insn);
++ if (GET_CODE (n) == PARALLEL)
++ n = XVECEXP (n, 0, 0);
++ }
++ dwarf2out_frame_debug_adjust_cfa (n, label);
++ handled_one = true;
++ break;
++
++ case REG_CFA_OFFSET:
++ n = XEXP (note, 0);
++ if (n == NULL)
++ n = single_set (insn);
++ dwarf2out_frame_debug_cfa_offset (n, label);
++ handled_one = true;
++ break;
++
++ case REG_CFA_REGISTER:
++ n = XEXP (note, 0);
++ if (n == NULL)
++ {
++ n = PATTERN (insn);
++ if (GET_CODE (n) == PARALLEL)
++ n = XVECEXP (n, 0, 0);
++ }
++ dwarf2out_frame_debug_cfa_register (n, label);
++ handled_one = true;
++ break;
++
++ case REG_CFA_RESTORE:
++ n = XEXP (note, 0);
++ if (n == NULL)
++ {
++ n = PATTERN (insn);
++ if (GET_CODE (n) == PARALLEL)
++ n = XVECEXP (n, 0, 0);
++ n = XEXP (n, 0);
++ }
++ dwarf2out_frame_debug_cfa_restore (n, label);
++ handled_one = true;
++ break;
++
++ default:
++ break;
++ }
++ if (handled_one)
++ return;
++
++ insn = PATTERN (insn);
++ found:
+ dwarf2out_frame_debug_expr (insn, label);
+ }
+
++/* Determine if we need to save and restore CFI information around this
++ epilogue. If SIBCALL is true, then this is a sibcall epilogue. If
++ we do need to save/restore, then emit the save now, and insert a
++ NOTE_INSN_CFA_RESTORE_STATE at the appropriate place in the stream. */
++
++void
++dwarf2out_begin_epilogue (rtx insn)
++{
++ bool saw_frp = false;
++ rtx i;
++
++ /* Scan forward to the return insn, noticing if there are possible
++ frame related insns. */
++ for (i = NEXT_INSN (insn); i ; i = NEXT_INSN (i))
++ {
++ if (!INSN_P (i))
++ continue;
++
++ /* Look for both regular and sibcalls to end the block. */
++ if (returnjump_p (i))
++ break;
++ if (CALL_P (i) && SIBLING_CALL_P (i))
++ break;
++
++ if (RTX_FRAME_RELATED_P (i))
++ saw_frp = true;
++ }
++
++ /* If the port doesn't emit epilogue unwind info, we don't need a
++ save/restore pair. */
++ if (!saw_frp)
++ return;
++
++ /* Otherwise, search forward to see if the return insn was the last
++ basic block of the function. If so, we don't need save/restore. */
++ gcc_assert (i != NULL);
++ i = next_real_insn (i);
++ if (i == NULL)
++ return;
++
++ /* Insert the restore before that next real insn in the stream, and before
++ a potential NOTE_INSN_EPILOGUE_BEG -- we do need these notes to be
++ properly nested. This should be after any label or alignment. This
++ will be pushed into the CFI stream by the function below. */
++ while (1)
++ {
++ rtx p = PREV_INSN (i);
++ if (!NOTE_P (p))
++ break;
++ if (NOTE_KIND (p) == NOTE_INSN_BASIC_BLOCK)
++ break;
++ i = p;
++ }
++ emit_note_before (NOTE_INSN_CFA_RESTORE_STATE, i);
++
++ emit_cfa_remember = true;
++
++ /* And emulate the state save. */
++ gcc_assert (!cfa_remember.in_use);
++ cfa_remember = cfa;
++ cfa_remember.in_use = 1;
++}
++
++/* A "subroutine" of dwarf2out_begin_epilogue. Emit the restore required. */
++
++void
++dwarf2out_frame_debug_restore_state (void)
++{
++ dw_cfi_ref cfi = new_cfi ();
++ const char *label = dwarf2out_cfi_label (false);
++
++ cfi->dw_cfi_opc = DW_CFA_restore_state;
++ add_fde_cfi (label, cfi);
++
++ gcc_assert (cfa_remember.in_use);
++ cfa = cfa_remember;
++ cfa_remember.in_use = 0;
++}
++
+ #endif
+
+ /* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
+@@ -2489,6 +2813,8 @@ dw_cfi_oprnd1_desc (enum dwarf_call_fram
+ {
+ case DW_CFA_nop:
+ case DW_CFA_GNU_window_save:
++ case DW_CFA_remember_state:
++ case DW_CFA_restore_state:
+ return dw_cfi_oprnd_unused;
+
+ case DW_CFA_set_loc:
+@@ -2503,6 +2829,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_fram
+ case DW_CFA_def_cfa:
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
++ case DW_CFA_restore:
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+@@ -2826,6 +3153,13 @@ output_cfi_directive (dw_cfi_ref cfi)
+ cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ break;
+
++ case DW_CFA_remember_state:
++ fprintf (asm_out_file, "\t.cfi_remember_state\n");
++ break;
++ case DW_CFA_restore_state:
++ fprintf (asm_out_file, "\t.cfi_restore_state\n");
++ break;
++
+ case DW_CFA_GNU_args_size:
+ fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size);
+ dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+@@ -12173,6 +12507,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN
+ dw_cfi_ref cfi;
+ dw_cfa_location last_cfa, next_cfa;
+ const char *start_label, *last_label, *section;
++ dw_cfa_location remember;
+
+ fde = current_fde ();
+ gcc_assert (fde != NULL);
+@@ -12181,17 +12516,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN
+ list_tail = &list;
+ list = NULL;
+
++ memset (&next_cfa, 0, sizeof (next_cfa));
+ next_cfa.reg = INVALID_REGNUM;
+- next_cfa.offset = 0;
+- next_cfa.indirect = 0;
+- next_cfa.base_offset = 0;
++ remember = next_cfa;
+
+ start_label = fde->dw_fde_begin;
+
+ /* ??? Bald assumption that the CIE opcode list does not contain
+ advance opcodes. */
+ for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
+- lookup_cfa_1 (cfi, &next_cfa);
++ lookup_cfa_1 (cfi, &next_cfa, &remember);
+
+ last_cfa = next_cfa;
+ last_label = start_label;
+@@ -12218,14 +12552,10 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_IN
+
+ case DW_CFA_advance_loc:
+ /* The encoding is complex enough that we should never emit this. */
+- case DW_CFA_remember_state:
+- case DW_CFA_restore_state:
+- /* We don't handle these two in this function. It would be possible
+- if it were to be required. */
+ gcc_unreachable ();
+
+ default:
+- lookup_cfa_1 (cfi, &next_cfa);
++ lookup_cfa_1 (cfi, &next_cfa, &remember);
+ break;
+ }
+
+--- gcc/function.c.jj 2009-03-19 17:17:02.000000000 +0100
++++ gcc/function.c 2009-06-09 08:58:04.000000000 +0200
+@@ -124,13 +124,11 @@ struct machine_function * (*init_machine
+ /* The currently compiled function. */
+ struct function *cfun = 0;
+
+-/* These arrays record the INSN_UIDs of the prologue and epilogue insns. */
+-static VEC(int,heap) *prologue;
+-static VEC(int,heap) *epilogue;
+-
+-/* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
+- in this function. */
+-static VEC(int,heap) *sibcall_epilogue;
++/* These hashes record the prologue and epilogue insns. */
++static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
++ htab_t prologue_insn_hash;
++static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
++ htab_t epilogue_insn_hash;
+ \f
+ /* Forward declarations. */
+
+@@ -143,8 +141,8 @@ static tree *get_block_vector (tree, int
+ extern tree debug_find_var_in_block_tree (tree, tree);
+ /* We always define `record_insns' even if it's not used so that we
+ can always export `prologue_epilogue_contains'. */
+-static void record_insns (rtx, VEC(int,heap) **) ATTRIBUTE_UNUSED;
+-static int contains (const_rtx, VEC(int,heap) **);
++static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
++static bool contains (const_rtx, htab_t);
+ #ifdef HAVE_return
+ static void emit_return_into_block (basic_block);
+ #endif
+@@ -207,9 +205,9 @@ free_after_parsing (struct function *f)
+ void
+ free_after_compilation (struct function *f)
+ {
+- VEC_free (int, heap, prologue);
+- VEC_free (int, heap, epilogue);
+- VEC_free (int, heap, sibcall_epilogue);
++ prologue_insn_hash = NULL;
++ epilogue_insn_hash = NULL;
++
+ if (crtl->emit.regno_pointer_align)
+ free (crtl->emit.regno_pointer_align);
+
+@@ -4198,18 +4196,11 @@ init_function_start (tree subr)
+ warning (OPT_Waggregate_return, "function returns an aggregate");
+ }
+
+-/* Make sure all values used by the optimization passes have sane
+- defaults. */
++/* Make sure all values used by the optimization passes have sane defaults. */
+ unsigned int
+ init_function_for_compilation (void)
+ {
+ reg_renumber = 0;
+-
+- /* No prologue/epilogue insns yet. Make sure that these vectors are
+- empty. */
+- gcc_assert (VEC_length (int, prologue) == 0);
+- gcc_assert (VEC_length (int, epilogue) == 0);
+- gcc_assert (VEC_length (int, sibcall_epilogue) == 0);
+ return 0;
+ }
+
+@@ -4875,16 +4866,42 @@ get_arg_pointer_save_area (void)
+ return ret;
+ }
+ \f
+-/* Extend a vector that records the INSN_UIDs of INSNS
+- (a list of one or more insns). */
++/* Add a list of INSNS to the hash HASHP, possibly allocating HASHP
++ for the first time. */
+
+ static void
+-record_insns (rtx insns, VEC(int,heap) **vecp)
++record_insns (rtx insns, rtx end, htab_t *hashp)
+ {
+ rtx tmp;
++ htab_t hash = *hashp;
++
++ if (hash == NULL)
++ *hashp = hash
++ = htab_create_ggc (17, htab_hash_pointer, htab_eq_pointer, NULL);
+
+- for (tmp = insns; tmp != NULL_RTX; tmp = NEXT_INSN (tmp))
+- VEC_safe_push (int, heap, *vecp, INSN_UID (tmp));
++ for (tmp = insns; tmp != end; tmp = NEXT_INSN (tmp))
++ {
++ void **slot = htab_find_slot (hash, tmp, INSERT);
++ gcc_assert (*slot == NULL);
++ *slot = tmp;
++ }
++}
++
++/* INSN has been duplicated as COPY, as part of duping a basic block.
++ If INSN is an epilogue insn, then record COPY as epilogue as well. */
++
++void
++maybe_copy_epilogue_insn (rtx insn, rtx copy)
++{
++ void **slot;
++
++ if (epilogue_insn_hash == NULL
++ || htab_find (epilogue_insn_hash, insn) == NULL)
++ return;
++
++ slot = htab_find_slot (epilogue_insn_hash, copy, INSERT);
++ gcc_assert (*slot == NULL);
++ *slot = copy;
+ }
+
+ /* Set the locator of the insn chain starting at INSN to LOC. */
+@@ -4899,52 +4916,37 @@ set_insn_locators (rtx insn, int loc)
+ }
+ }
+
+-/* Determine how many INSN_UIDs in VEC are part of INSN. Because we can
+- be running after reorg, SEQUENCE rtl is possible. */
++/* Determine if any INSNs in HASH are, or are part of, INSN. Because
++ we can be running after reorg, SEQUENCE rtl is possible. */
+
+-static int
+-contains (const_rtx insn, VEC(int,heap) **vec)
++static bool
++contains (const_rtx insn, htab_t hash)
+ {
+- int i, j;
++ if (hash == NULL)
++ return false;
+
+- if (NONJUMP_INSN_P (insn)
+- && GET_CODE (PATTERN (insn)) == SEQUENCE)
++ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+- int count = 0;
++ int i;
+ for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+- for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
+- if (INSN_UID (XVECEXP (PATTERN (insn), 0, i))
+- == VEC_index (int, *vec, j))
+- count++;
+- return count;
++ if (htab_find (hash, XVECEXP (PATTERN (insn), 0, i)))
++ return true;
++ return false;
+ }
+- else
+- {
+- for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
+- if (INSN_UID (insn) == VEC_index (int, *vec, j))
+- return 1;
+- }
+- return 0;
++
++ return htab_find (hash, insn) != NULL;
+ }
+
+ int
+ prologue_epilogue_contains (const_rtx insn)
+ {
+- if (contains (insn, &prologue))
++ if (contains (insn, prologue_insn_hash))
+ return 1;
+- if (contains (insn, &epilogue))
++ if (contains (insn, epilogue_insn_hash))
+ return 1;
+ return 0;
+ }
+
+-int
+-sibcall_epilogue_contains (const_rtx insn)
+-{
+- if (sibcall_epilogue)
+- return contains (insn, &sibcall_epilogue);
+- return 0;
+-}
+-
+ #ifdef HAVE_return
+ /* Insert gen_return at the end of block BB. This also means updating
+ block_for_insn appropriately. */
+@@ -4987,7 +4989,7 @@ thread_prologue_and_epilogue_insns (void
+ emit_use (hard_frame_pointer_rtx);
+
+ /* Retain a map of the prologue insns. */
+- record_insns (seq, &prologue);
++ record_insns (seq, NULL, &prologue_insn_hash);
+ emit_note (NOTE_INSN_PROLOGUE_END);
+
+ #ifndef PROFILE_BEFORE_PROLOGUE
+@@ -5119,6 +5121,38 @@ thread_prologue_and_epilogue_insns (void
+ }
+ }
+ #endif
++
++ /* A small fib -- epilogue is not yet completed, but we wish to re-use
++ this marker for the splits of EH_RETURN patterns, and nothing else
++ uses the flag in the meantime. */
++ epilogue_completed = 1;
++
++#ifdef HAVE_eh_return
++ /* Find non-fallthru edges that end with EH_RETURN instructions. On
++ some targets, these get split to a special version of the epilogue
++ code. In order to be able to properly annotate these with unwind
++ info, try to split them now. If we get a valid split, drop an
++ EPILOGUE_BEG note and mark the insns as epilogue insns. */
++ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
++ {
++ rtx prev, last, trial;
++
++ if (e->flags & EDGE_FALLTHRU)
++ continue;
++ last = BB_END (e->src);
++ if (!eh_returnjump_p (last))
++ continue;
++
++ prev = PREV_INSN (last);
++ trial = try_split (PATTERN (last), last, 1);
++ if (trial == last)
++ continue;
++
++ record_insns (NEXT_INSN (prev), NEXT_INSN (trial), &epilogue_insn_hash);
++ emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
++ }
++#endif
++
+ /* Find the edge that falls through to EXIT. Other edges may exist
+ due to RETURN instructions, but those don't need epilogues.
+ There really shouldn't be a mixture -- either all should have
+@@ -5139,7 +5173,7 @@ thread_prologue_and_epilogue_insns (void
+ emit_jump_insn (seq);
+
+ /* Retain a map of the epilogue insns. */
+- record_insns (seq, &epilogue);
++ record_insns (seq, NULL, &epilogue_insn_hash);
+ set_insn_locators (seq, epilogue_locator);
+
+ seq = get_insns ();
+@@ -5201,6 +5235,7 @@ epilogue_done:
+ }
+
+ start_sequence ();
++ emit_note (NOTE_INSN_EPILOGUE_BEG);
+ emit_insn (gen_sibcall_epilogue ());
+ seq = get_insns ();
+ end_sequence ();
+@@ -5208,7 +5243,7 @@ epilogue_done:
+ /* Retain a map of the epilogue insns. Used in life analysis to
+ avoid getting rid of sibcall epilogue insns. Do this before we
+ actually emit the sequence. */
+- record_insns (seq, &sibcall_epilogue);
++ record_insns (seq, NULL, &epilogue_insn_hash);
+ set_insn_locators (seq, epilogue_locator);
+
+ emit_insn_before (seq, insn);
+@@ -5242,23 +5277,29 @@ epilogue_done:
+ df_update_entry_exit_and_calls ();
+ }
+
+-/* Reposition the prologue-end and epilogue-begin notes after instruction
+- scheduling and delayed branch scheduling. */
++/* Reposition the prologue-end and epilogue-begin notes after
++ instruction scheduling. */
+
+ void
+ reposition_prologue_and_epilogue_notes (void)
+ {
+-#if defined (HAVE_prologue) || defined (HAVE_epilogue)
++#if defined (HAVE_prologue) || defined (HAVE_epilogue) \
++ || defined (HAVE_sibcall_epilogue)
+ rtx insn, last, note;
+- int len;
++ basic_block bb;
+
+- if ((len = VEC_length (int, prologue)) > 0)
++ /* Since the hash table is created on demand, the fact that it is
++ non-null is a signal that it is non-empty. */
++ if (prologue_insn_hash != NULL)
+ {
++ size_t len = htab_elements (prologue_insn_hash);
+ last = 0, note = 0;
+
+- /* Scan from the beginning until we reach the last prologue insn.
+- We apparently can't depend on basic_block_{head,end} after
+- reorg has run. */
++ /* Scan from the beginning until we reach the last prologue insn. */
++ /* ??? While we do have the CFG intact, there are two problems:
++ (1) The prologue can contain loops (typically probing the stack),
++ which means that the end of the prologue isn't in the first bb.
++ (2) Sometimes the PROLOGUE_END note gets pushed into the next bb. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (NOTE_P (insn))
+@@ -5266,7 +5307,7 @@ reposition_prologue_and_epilogue_notes (
+ if (NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
+ note = insn;
+ }
+- else if (contains (insn, &prologue))
++ else if (contains (insn, prologue_insn_hash))
+ {
+ last = insn;
+ if (--len == 0)
+@@ -5276,14 +5317,17 @@ reposition_prologue_and_epilogue_notes (
+
+ if (last)
+ {
+- /* Find the prologue-end note if we haven't already, and
+- move it to just after the last prologue insn. */
+- if (note == 0)
++ if (note == NULL)
+ {
+- for (note = last; (note = NEXT_INSN (note));)
+- if (NOTE_P (note)
+- && NOTE_KIND (note) == NOTE_INSN_PROLOGUE_END)
+- break;
++ /* Scan forward looking for the PROLOGUE_END note. It should
++ be right at the beginning of the block, possibly with other
++ insn notes that got moved there. */
++ for (note = NEXT_INSN (last); ; note = NEXT_INSN (note))
++ {
++ if (NOTE_P (note)
++ && NOTE_KIND (note) == NOTE_INSN_PROLOGUE_END)
++ break;
++ }
+ }
+
+ /* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */
+@@ -5293,41 +5337,39 @@ reposition_prologue_and_epilogue_notes (
+ }
+ }
+
+- if ((len = VEC_length (int, epilogue)) > 0)
++ if (epilogue_insn_hash != NULL)
+ {
+- last = 0, note = 0;
++ edge_iterator ei;
++ edge e;
+
+- /* Scan from the end until we reach the first epilogue insn.
+- We apparently can't depend on basic_block_{head,end} after
+- reorg has run. */
+- for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
++ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ {
+- if (NOTE_P (insn))
+- {
+- if (NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
+- note = insn;
+- }
+- else if (contains (insn, &epilogue))
+- {
+- last = insn;
+- if (--len == 0)
+- break;
+- }
+- }
++ last = 0, note = 0;
++ bb = e->src;
+
+- if (last)
+- {
+- /* Find the epilogue-begin note if we haven't already, and
+- move it to just before the first epilogue insn. */
+- if (note == 0)
++ /* Scan from the beginning until we reach the first epilogue insn.
++ Take the cue for whether this is a plain or sibcall epilogue
++ from the kind of note we find first. */
++ FOR_BB_INSNS (bb, insn)
+ {
+- for (note = insn; (note = PREV_INSN (note));)
+- if (NOTE_P (note)
+- && NOTE_KIND (note) == NOTE_INSN_EPILOGUE_BEG)
+- break;
++ if (NOTE_P (insn))
++ {
++ if (NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
++ {
++ note = insn;
++ if (last)
++ break;
++ }
++ }
++ else if (contains (insn, epilogue_insn_hash))
++ {
++ last = insn;
++ if (note != NULL)
++ break;
++ }
+ }
+-
+- if (PREV_INSN (last) != note)
++
++ if (last && note && PREV_INSN (last) != note)
+ reorder_insns (note, note, PREV_INSN (last));
+ }
+ }
+--- gcc/emit-rtl.c.jj 2009-03-04 12:11:37.000000000 +0100
++++ gcc/emit-rtl.c 2009-06-09 08:58:04.000000000 +0200
+@@ -3343,6 +3343,10 @@ try_split (rtx pat, rtx trial, int last)
+ rtx insn_last, insn;
+ int njumps = 0;
+
++ /* We're not good at redistributing frame information. */
++ if (RTX_FRAME_RELATED_P (trial))
++ return trial;
++
+ if (any_condjump_p (trial)
+ && (note = find_reg_note (trial, REG_BR_PROB, 0)))
+ split_branch_probability = INTVAL (XEXP (note, 0));
+@@ -5058,6 +5062,9 @@ copy_insn_1 (rtx orig)
+ RTX_CODE code;
+ const char *format_ptr;
+
++ if (orig == NULL)
++ return NULL;
++
+ code = GET_CODE (orig);
+
+ switch (code)
+--- gcc/dwarf2out.h.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/dwarf2out.h 2009-06-09 08:58:04.000000000 +0200
+@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.
+
+ extern void dwarf2out_decl (tree);
+ extern void dwarf2out_frame_debug (rtx, bool);
++extern void dwarf2out_begin_epilogue (rtx);
++extern void dwarf2out_frame_debug_restore_state (void);
+
+ extern void debug_dwarf (void);
+ struct die_struct;
+--- gcc/final.c.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/final.c 2009-06-09 08:58:04.000000000 +0200
+@@ -1869,9 +1869,19 @@ final_scan_insn (rtx insn, FILE *file, i
+ break;
+
+ case NOTE_INSN_EPILOGUE_BEG:
++#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_epilogue)
++ if (dwarf2out_do_frame ())
++ dwarf2out_begin_epilogue (insn);
++#endif
+ targetm.asm_out.function_begin_epilogue (file);
+ break;
+
++ case NOTE_INSN_CFA_RESTORE_STATE:
++#if defined (DWARF2_UNWIND_INFO)
++ dwarf2out_frame_debug_restore_state ();
++#endif
++ break;
++
+ case NOTE_INSN_FUNCTION_BEG:
+ app_disable ();
+ (*debug_hooks->end_prologue) (last_linenum, last_filename);
+--- gcc/jump.c.jj 2009-03-04 12:10:22.000000000 +0100
++++ gcc/jump.c 2009-06-09 09:20:50.000000000 +0200
+@@ -869,18 +869,54 @@ returnjump_p_1 (rtx *loc, void *data ATT
+ {
+ rtx x = *loc;
+
+- return x && (GET_CODE (x) == RETURN
+- || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
++ if (x == NULL)
++ return false;
++
++ switch (GET_CODE (x))
++ {
++ case RETURN:
++ case EH_RETURN:
++ return true;
++
++ case SET:
++ return SET_IS_RETURN_P (x);
++
++ default:
++ return false;
++ }
+ }
+
++/* Return TRUE if INSN is a return jump. */
++
+ int
+ returnjump_p (rtx insn)
+ {
++ /* Handle delayed branches. */
++ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
++ insn = XVECEXP (PATTERN (insn), 0, 0);
++
+ if (!JUMP_P (insn))
+ return 0;
++
+ return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
+ }
+
++/* Return true if INSN is a (possibly conditional) return insn. */
++
++static int
++eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
++{
++ return *loc && GET_CODE (*loc) == EH_RETURN;
++}
++
++int
++eh_returnjump_p (rtx insn)
++{
++ if (!JUMP_P (insn))
++ return 0;
++ return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
++}
++
+ /* Return true if INSN is a jump that only transfers control and
+ nothing more. */
+
+--- gcc/recog.c.jj 2009-03-10 11:06:10.000000000 +0100
++++ gcc/recog.c 2009-06-09 09:08:21.000000000 +0200
+@@ -3026,6 +3026,26 @@ peep2_find_free_register (int from, int
+ return NULL_RTX;
+ }
+
++/* Forget all currently tracked instructions, only remember current
++ LIVE regset. */
++
++static void
++peep2_reinit_state (regset live)
++{
++ int i;
++
++ /* Indicate that all slots except the last holds invalid data. */
++ for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
++ peep2_insn_data[i].insn = NULL_RTX;
++ peep2_current_count = 0;
++
++ /* Indicate that the last slot contains live_after data. */
++ peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
++ peep2_current = MAX_INSNS_PER_PEEP2;
++
++ COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
++}
++
+ /* Perform the peephole2 optimization pass. */
+
+ static void
+@@ -3049,19 +3069,11 @@ peephole2_optimize (void)
+ FOR_EACH_BB_REVERSE (bb)
+ {
+ rtl_profile_for_bb (bb);
+- /* Indicate that all slots except the last holds invalid data. */
+- for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
+- peep2_insn_data[i].insn = NULL_RTX;
+- peep2_current_count = 0;
+-
+- /* Indicate that the last slot contains live_after data. */
+- peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+- peep2_current = MAX_INSNS_PER_PEEP2;
+
+ /* Start up propagation. */
+ bitmap_copy (live, DF_LR_OUT (bb));
+ df_simulate_initialize_backwards (bb, live);
+- bitmap_copy (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
++ peep2_reinit_state (live);
+
+ for (insn = BB_END (bb); ; insn = prev)
+ {
+@@ -3088,7 +3100,7 @@ peephole2_optimize (void)
+ /* If an insn has RTX_FRAME_RELATED_P set, peephole
+ substitution would lose the
+ REG_FRAME_RELATED_EXPR that is attached. */
+- peep2_current_count = 0;
++ peep2_reinit_state (live);
+ attempt = NULL;
+ }
+ else
+--- gcc/rtl.h.jj 2009-04-27 13:57:11.000000000 +0200
++++ gcc/rtl.h 2009-06-09 08:58:04.000000000 +0200
+@@ -2072,6 +2072,7 @@ extern rtx pc_set (const_rtx);
+ extern rtx condjump_label (const_rtx);
+ extern int simplejump_p (const_rtx);
+ extern int returnjump_p (rtx);
++extern int eh_returnjump_p (rtx);
+ extern int onlyjump_p (const_rtx);
+ extern int only_sets_cc0_p (const_rtx);
+ extern int sets_cc0_p (const_rtx);
+@@ -2185,6 +2186,7 @@ extern int prologue_epilogue_contains (c
+ extern int sibcall_epilogue_contains (const_rtx);
+ extern void mark_temp_addr_taken (rtx);
+ extern void update_temp_slot_address (rtx, rtx);
++extern void maybe_copy_epilogue_insn (rtx, rtx);
+
+ /* In stmt.c */
+ extern void expand_null_return (void);
+--- gcc/cfgrtl.c.jj 2009-06-09 08:16:10.000000000 +0200
++++ gcc/cfgrtl.c 2009-06-09 08:58:05.000000000 +0200
+@@ -87,8 +87,16 @@ static void rtl_make_forwarder_block (ed
+ static int
+ can_delete_note_p (const_rtx note)
+ {
+- return (NOTE_KIND (note) == NOTE_INSN_DELETED
+- || NOTE_KIND (note) == NOTE_INSN_BASIC_BLOCK);
++ switch (NOTE_KIND (note))
++ {
++ case NOTE_INSN_DELETED:
++ case NOTE_INSN_BASIC_BLOCK:
++ case NOTE_INSN_EPILOGUE_BEG:
++ return true;
++
++ default:
++ return false;
++ }
+ }
+
+ /* True if a given label can be deleted. */
diff --git a/gcc44-ix86-insn-length.patch b/gcc44-ix86-insn-length.patch
new file mode 100644
index 0000000..487f684
--- /dev/null
+++ b/gcc44-ix86-insn-length.patch
@@ -0,0 +1,4873 @@
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_decompose_address): Avoid useless
+ 0 displacement. Add 0 displacement if base is %[er]bp or %r13.
+
+ * config/i386/i386.md (prefix_data16, prefix_rep): Set to 0 for
+ TYPE_SSE{MULADD,4ARG,IADD1,CVT1} by default.
+ (prefix_rex): For UNIT_MMX don't imply the prefix by default
+ if MODE_DI.
+ (prefix_extra): Default to 2 for TYPE_SSE{MULADD,4ARG} and
+ to 1 for TYPE_SSE{IADD1,CVT1}.
+ (prefix_vex_imm8): Removed.
+ (length_vex): Only pass 1 as second argument to
+ ix86_attr_length_vex_default if prefix_extra is 0.
+ (modrm): For TYPE_INCDEC only set to 0 if not TARGET_64BIT.
+ (length): For prefix vex computation use length_immediate
+ attribute instead of prefix_vex_imm8.
+ (cmpqi_ext_3_insn, cmpqi_ext_3_insn_rex64,
+ addqi_ext_1, addqi_ext_1_rex64, *testqi_ext_0, andqi_ext_0,
+ *andqi_ext_0_cc, *iorqi_ext_0, *xorqi_ext_0, *xorqi_cc_ext_1,
+ *xorqi_cc_ext_1_rex64): Override modrm attribute to 1.
+ (extendsidi2_rex64, extendhidi2, extendqidi2, extendhisi2,
+ *extendhisi2_zext, extendqihi2, extendqisi2, *extendqisi2_zext): Emit
+ a space in between the operands.
+ (*anddi_1_rex64, *andsi_1): Likewise. Override prefix_rex to 1
+ if one operand is 0xff and the other one si, di, bp or sp.
+ (*andhi_1): Override prefix_rex to 1 if one operand is 0xff and the
+ other one si, di, bp or sp.
+ (*btsq, *btrq, *btcq, *btdi_rex64, *btsi): Add mode attribute.
+ (*ffssi_1, *ffsdi_1, ctzsi2, ctzdi2): Add
+ type and mode attributes.
+ (*bsr, *bsr_rex64, *bsrhi): Add type attribute.
+ (*cmpfp_i_mixed, *cmpfp_iu_mixed): For TYPE_SSECOMI, clear
+ prefix_rep attribute and set prefix_data16 attribute iff MODE_DF.
+ (*cmpfp_i_sse, *cmpfp_iu_sse): Clear prefix_rep attribute and set
+ prefix_data16 attribute iff MODE_DF.
+ (*movsi_1): For TYPE_SSEMOV MODE_SI set prefix_data16 attribute.
+ (fix_trunc<mode>di_sse): Set prefix_rex attribute.
+ (*adddi_4_rex64, *addsi_4): Use const128_operand instead of
+ constm128_operand in length_immediate computation.
+ (*addhi_4): Likewise. Fix mode attribute to MODE_HI.
+ (anddi_1_rex64): Use movzbl/movzwl instead of movzbq/movzwq.
+ (*avx_ashlti3, sse2_ashlti3, *avx_lshrti3, sse2_lshrti3): Set
+ length_immediate attribute to 1.
+ (x86_fnstsw_1, x86_fnstcw_1, x86_fldcw_1): Fix length attribute.
+ (*movdi_1_rex64): Override prefix_rex or prefix_data16 attributes
+ for certain alternatives.
+ (*movdf_nointeger, *movdf_integer_rex64, *movdf_integer): Override
+ prefix_data16 attribute if MODE_V1DF.
+ (*avx_setcc<mode>, *sse_setcc<mode>, *sse5_setcc<mode>): Set
+ length_immediate to 1.
+ (set_got_rex64, set_rip_rex64): Remove length attribute, set
+ length_address to 4, set mode attribute to MODE_DI.
+ (set_got_offset_rex64): Likewise. Set length_immediate to 0.
+ (fxam<mode>2_i387): Set length attribute to 4.
+ (*prefetch_sse, *prefetch_sse_rex, *prefetch_3dnow,
+ *prefetch_3dnow_rex): Override length_address attribute.
+ (sse4_2_crc32<mode>): Override prefix_data16 and prefix_rex
+ attributes.
+ * config/i386/predicates.md (ext_QIreg_nomode_operand): New predicate.
+ (constm128_operand): Removed.
+ * config/i386/i386.c (memory_address_length): For
+ disp && !index && !base in 64-bit mode account for SIB byte if
+ print_operand_address can't optimize disp32 into disp32(%rip)
+ and UNSPEC doesn't imply (%rip) addressing. Add 1 to length
+ for fs: or gs: segment.
+ (ix86_attr_length_immediate_default): When checking if shortform
+ is possible, truncate immediate to the length of the non-shortened
+ immediate.
+ (ix86_attr_length_address_default): Ignore MEM_P operands
+ with X constraint.
+ (ix86_attr_length_vex_default): Only check for DImode on
+ GENERAL_REG_P operands.
+ * config/i386/sse.md (<sse>_comi, <sse>_ucomi): Clear
+ prefix_rep attribute, set prefix_data16 attribute iff MODE_DF.
+ (sse_cvttps2pi): Clear prefix_rep attribute.
+ (sse2_cvttps2dq, *sse2_cvtpd2dq, sse2_cvtps2pd): Clear prefix_data16
+ attribute.
+ (*sse2_cvttpd2dq): Don't clear prefix_rep attribute.
+ (*avx_ashr<mode>3, ashr<mode>3, *avx_lshr<mode>3, lshr<mode>3,
+ *avx_ashl<mode>3, ashl<mode>3): Set length_immediate attribute to 1
+ iff operand 2 is const_int_operand.
+ (*vec_dupv4si, avx_shufpd256_1, *avx_shufpd_<mode>,
+ sse2_shufpd_<mode>): Set length_immediate attribute to 1.
+ (sse2_pshufd_1): Likewise. Set prefix attribute to maybe_vex
+ instead of vex.
+ (sse2_pshuflw_1, sse2_pshufhw_1): Set length_immediate to 1 and clear
+ prefix_data16.
+ (sse2_unpckhpd, sse2_unpcklpd, sse2_storehpd, *vec_concatv2df): Set
+ prefix_data16 attribute for movlpd and movhpd instructions.
+ (sse2_loadhpd, sse2_loadlpd, sse2_movsd): Likewise. Override
+ length_immediate for shufpd instruction.
+ (sse2_movntsi, sse3_lddqu): Clear prefix_data16 attribute.
+ (avx_cmpp<avxmodesuffixf2c><mode>3,
+ avx_cmps<ssemodesuffixf2c><mode>3, *avx_maskcmp<mode>3,
+ <sse>_maskcmp<mode>3, <sse>_vmmaskcmp<mode>3,
+ avx_shufps256_1, *avx_shufps_<mode>, sse_shufps_<mode>,
+ *vec_dupv4sf_avx, *vec_dupv4sf): Set
+ length_immediate attribute to 1.
+ (*avx_cvtsi2ssq, *avx_cvtsi2sdq): Set length_vex attribute to 4.
+ (sse_cvtsi2ssq, sse2_cvtsi2sdq): Set prefix_rex attribute to 1.
+ (sse2_cvtpi2pd, sse_loadlps, sse2_storelpd): Override
+ prefix_data16 attribute for the first alternative to 1.
+ (*avx_loadlps): Override length_immediate for the first alternative.
+ (*vec_concatv2sf_avx): Override length_immediate and prefix_extra
+ attributes for second alternative.
+ (*vec_concatv2sf_sse4_1): Override length_immediate and
+ prefix_data16 attributes for second alternative.
+ (*vec_setv4sf_avx, *avx_insertps, vec_extract_lo_<mode>,
+ vec_extract_hi_<mode>, vec_extract_lo_v16hi,
+ vec_extract_hi_v16hi, vec_extract_lo_v32qi,
+ vec_extract_hi_v32qi): Set prefix_extra and length_immediate to 1.
+ (*vec_setv4sf_sse4_1, sse4_1_insertps, *sse4_1_extractps): Set
+ prefix_data16 and length_immediate to 1.
+ (*avx_mulv2siv2di3, *avx_mulv4si3, sse4_2_gtv2di3): Set prefix_extra
+ to 1.
+ (*avx_<code><mode>3, *avx_eq<mode>3, *avx_gt<mode>3): Set
+ prefix_extra attribute for variants that don't have 0f prefix
+ alone.
+ (*avx_pinsr<ssevecsize>): Likewise. Set length_immediate to 1.
+ (*sse4_1_pinsrb, *sse2_pinsrw, *sse4_1_pinsrd, *sse4_1_pextrb,
+ *sse4_1_pextrb_memory, *sse2_pextrw, *sse4_1_pextrw_memory,
+ *sse4_1_pextrd): Set length_immediate to 1.
+ (*sse4_1_pinsrd): Likewise. Set prefix_extra to 1.
+ (*sse4_1_pinsrq, *sse4_1_pextrq): Set prefix_rex and length_immediate
+ to 1.
+ (*vec_extractv2di_1_rex64_avx, *vec_extractv2di_1_rex64,
+ *vec_extractv2di_1_avx, *vec_extractv2di_1_sse2): Override
+ length_immediate to 1 for second alternative.
+ (*vec_concatv2si_avx, *vec_concatv2di_rex64_avx): Override
+ prefix_extra and length_immediate attributes for the first
+ alternative.
+ (vec_concatv2si_sse4_1): Override length_immediate to 1 for the
+ first alternative.
+ (*vec_concatv2di_rex64_sse4_1): Likewise. Override prefix_rex
+ to 1 for the first and third alternative.
+ (*vec_concatv2di_rex64_sse): Override prefix_rex to 1 for the second
+ alternative.
+ (*sse2_maskmovdqu, *sse2_maskmovdqu_rex64): Override length_vex
+ attribute.
+ (*sse_sfence, sse2_mfence, sse2_lfence): Override length_address
+ attribute to 0.
+ (*avx_phaddwv8hi3, *avx_phadddv4si3, *avx_phaddswv8hi3,
+ *avx_phsubwv8hi3, *avx_phsubdv4si3, *avx_phsubswv8hi,
+ *avx_pmaddubsw128, *avx_pmulhrswv8hi3, *avx_pshufbv16qi3,
+ *avx_psign<mode>3): Set prefix_extra attribute to 1.
+ (ssse3_phaddwv4hi3, ssse3_phadddv2si3, ssse3_phaddswv4hi3,
+ ssse3_phsubwv4hi3, ssse3_phsubdv2si3, ssse3_phsubswv4hi3,
+ ssse3_pmaddubsw, *ssse3_pmulhrswv4hi, ssse3_pshufbv8qi3,
+ ssse3_psign<mode>3): Override prefix_rex attribute.
+ (*avx_palignrti): Override prefix_extra and length_immediate
+ to 1.
+ (ssse3_palignrti): Override length_immediate to 1.
+ (ssse3_palignrdi): Override length_immediate to 1, override
+ prefix_rex attribute.
+ (abs<mode>2): Override prefix_rep to 0, override prefix_rex
+ attribute.
+ (sse4a_extrqi): Override length_immediate to 2.
+ (sse4a_insertqi): Likewise. Override prefix_data16 to 0.
+ (sse4a_insertq): Override prefix_data16 to 0.
+ (avx_blendp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_blendvp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_dpp<avxmodesuffixf2c><avxmodesuffix>, *avx_mpsadbw,
+ *avx_pblendvb, *avx_pblendw, avx_roundp<avxmodesuffixf2c>256,
+ avx_rounds<avxmodesuffixf2c>256): Override prefix_extra
+ and length_immediate to 1.
+ (sse4_1_blendp<ssemodesuffixf2c>, sse4_1_dpp<ssemodesuffixf2c>,
+ sse4_2_pcmpestr, sse4_2_pcmpestri, sse4_2_pcmpestrm,
+ sse4_2_pcmpestr_cconly, sse4_2_pcmpistr, sse4_2_pcmpistri,
+ sse4_2_pcmpistrm, sse4_2_pcmpistr_cconly): Override prefix_data16
+ and length_immediate to 1.
+ (sse4_1_blendvp<ssemodesuffixf2c>): Override prefix_data16 to 1.
+ (sse4_1_mpsadbw, sse4_1_pblendw): Override length_immediate to 1.
+ (*avx_packusdw, avx_vtestp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_ptest256): Override prefix_extra to 1.
+ (sse4_1_roundp<ssemodesuffixf2c>, sse4_1_rounds<ssemodesuffixf2c>):
+ Override prefix_data16 and length_immediate to 1.
+ (sse5_pperm_zero_v16qi_v8hi, sse5_pperm_sign_v16qi_v8hi,
+ sse5_pperm_zero_v8hi_v4si, sse5_pperm_sign_v8hi_v4si,
+ sse5_pperm_zero_v4si_v2di, sse5_pperm_sign_v4si_v2di,
+ sse5_vrotl<mode>3, sse5_ashl<mode>3, sse5_lshl<mode>3): Override
+ prefix_data16 to 0 and prefix_extra to 2.
+ (sse5_rotl<mode>3, sse5_rotr<mode>3): Override length_immediate to 1.
+ (sse5_frcz<mode>2, sse5_vmfrcz<mode>2): Don't override prefix_extra
+ attribute.
+ (*sse5_vmmaskcmp<mode>3, sse5_com_tf<mode>3,
+ sse5_maskcmp<mode>3, sse5_maskcmp<mode>3, sse5_maskcmp_uns<mode>3):
+ Override prefix_data16 and prefix_rep to 0, length_immediate to 1
+ and prefix_extra to 2.
+ (sse5_maskcmp_uns2<mode>3, sse5_pcom_tf<mode>3): Override
+ prefix_data16 to 0, length_immediate to 1 and prefix_extra to 2.
+ (*avx_aesenc, *avx_aesenclast, *avx_aesdec, *avx_aesdeclast,
+ avx_vpermilvar<mode>3,
+ avx_vbroadcasts<avxmodesuffixf2c><avxmodesuffix>,
+ avx_vbroadcastss256, avx_vbroadcastf128_p<avxmodesuffixf2c>256,
+ avx_maskloadp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_maskstorep<avxmodesuffixf2c><avxmodesuffix>):
+ Override prefix_extra to 1.
+ (aeskeygenassist, pclmulqdq): Override length_immediate to 1.
+ (*vpclmulqdq, avx_vpermil<mode>, avx_vperm2f128<mode>3,
+ vec_set_lo_<mode>, vec_set_hi_<mode>, vec_set_lo_v16hi,
+ vec_set_hi_v16hi, vec_set_lo_v32qi, vec_set_hi_v32qi): Override
+ prefix_extra and length_immediate to 1.
+ (*avx_vzeroall, avx_vzeroupper, avx_vzeroupper_rex64): Override
+ modrm to 0.
+ (*vec_concat<mode>_avx): Override prefix_extra and length_immediate
+ to 1 for the first alternative.
+ * config/i386/mmx.md (*mov<mode>_internal_rex64): Override
+ prefix_rep, prefix_data16 and/or prefix_rex attributes in certain
+ cases.
+ (*mov<mode>_internal_avx, *movv2sf_internal_rex64,
+ *movv2sf_internal_avx, *movv2sf_internal): Override
+ prefix_rep attribute for certain alternatives.
+ (*mov<mode>_internal): Override prefix_rep or prefix_data16
+ attributes for certain alternatives.
+ (*movv2sf_internal_rex64_avx): Override prefix_rep and length_vex
+ attributes for certain alternatives.
+ (*mmx_addv2sf3, *mmx_subv2sf3, *mmx_mulv2sf3,
+ *mmx_<code>v2sf3_finite, *mmx_<code>v2sf3, mmx_rcpv2sf2,
+ mmx_rcpit1v2sf3, mmx_rcpit2v2sf3, mmx_rsqrtv2sf2, mmx_rsqit1v2sf3,
+ mmx_haddv2sf3, mmx_hsubv2sf3, mmx_addsubv2sf3,
+ *mmx_eqv2sf3, mmx_gtv2sf3, mmx_gev2sf3, mmx_pf2id, mmx_pf2iw,
+ mmx_pi2fw, mmx_floatv2si2, mmx_pswapdv2sf2, *mmx_pmulhrwv4hi3,
+ mmx_pswapdv2si2): Set prefix_extra attribute to 1.
+ (mmx_ashr<mode>3, mmx_lshr<mode>3, mmx_ashl<mode>3): Set
+ length_immediate to 1 if operand 2 is const_int_operand.
+ (*mmx_pinsrw, mmx_pextrw, mmx_pshufw_1, *vec_dupv4hi,
+ *vec_extractv2si_1): Set length_immediate
+ attribute to 1.
+ (*mmx_uavgv8qi3): Override prefix_extra attribute to 1 if
+ using old 3DNOW insn rather than SSE/3DNOW_A.
+ (mmx_emms, mmx_femms): Clear modrm attribute.
+
+2009-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (memory_address_length): Handle %r12
+ the same as %rsp and %r13 the same as %rbp. For %rsp and %rbp
+ also check REGNO.
+ (ix86_attr_length_address_default): For MODE_SI lea in 64-bit
+ mode look through optional ZERO_EXTEND and SUBREG.
+ * config/i386/i386.md (R12_REG): New define_constant.
+ (prefix_data16): For sse unit set also for MODE_TI insns.
+ (prefix_rex): For -m32 always return 0. For TYPE_IMOVX
+ insns set if operand 1 is ext_QIreg_operand.
+ (modrm): For TYPE_IMOV clear only if not MODE_DI. For
+ TYPE_{ALU{,1},ICMP,TEST} insn clear if there is non-shortened
+ immediate.
+ (*movdi_extzv_1, zero_extendhidi2, zero_extendqidi2): Change
+ mode from MODE_DI to MODE_SI.
+ (movdi_1_rex64): Override modrm and length_immediate attributes
+ only for movabs (TYPE_IMOV, alternative 2).
+ (zero_extendsidi2_rex64): Clear prefix_0f attribute if TYPE_IMOVX.
+ (*float<SSEMODEI24:mode><MODEF:mode>2_mixed_interunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_mixed_nointerunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_sse_interunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_sse_nointerunit): Set
+ prefix_rex attribute if DImode.
+ (*adddi_1_rex64, *adddi_2_rex64, *adddi_3_rex64, *adddi_5_rex64,
+ *addsi_1, *addsi_1_zext, *addsi_2, *addsi_2_zext, *addsi_3,
+ *addsi_3_zext, *addsi_5, *addhi_1_lea, *addhi_1, *addhi_2, *addhi_3,
+ *addhi_5, *addqi_1_lea, *addqi_1): Override length_immediate
+ attribute to 1 if TYPE_ALU and operand 2 is const128_operand.
+ (pro_epilogue_adjust_stack_1, pro_epilogue_adjust_stack_rex64):
+ Likewise. For TYPE_IMOV clear length_immediate attribute.
+ (*ashldi3_1_rex64, *ashldi3_cmp_rex64, *ashldi3_cconly_rex64,
+ *ashlsi3_1, *ashlsi3_1_zext, *ashlsi3_cmp, **ashlsi3_cconly,
+ *ashlsi3_cmp_zext, *ashlhi3_1_lea, *ashlhi3_1, *ashlhi3_cmp,
+ *ashlhi3_cconly, *ashlqi3_1_lea, *ashlqi3_1, *ashlqi3_cmp,
+ *ashlqi3_cconly): Override length_immediate attribute to 0 if TYPE_ALU
+ or one operand TYPE_ISHIFT.
+ (*ashrdi3_1_one_bit_rex64, *ashrdi3_one_bit_cmp_rex64,
+ *ashrdi3_one_bit_cconly_rex64, *ashrsi3_1_one_bit,
+ *ashrsi3_1_one_bit_zext, *ashrsi3_one_bit_cmp,
+ *ashrsi3_one_bit_cconly, *ashrsi3_one_bit_cmp_zext,
+ *ashrhi3_1_one_bit, *ashrhi3_one_bit_cmp, *ashrhi3_one_bit_cconly,
+ *ashrqi3_1_one_bit, *ashrqi3_1_one_bit_slp, *ashrqi3_one_bit_cmp,
+ *ashrqi3_one_bit_cconly, *lshrdi3_1_one_bit_rex64,
+ *lshrdi3_cmp_one_bit_rex64, *lshrdi3_cconly_one_bit_rex64,
+ *lshrsi3_1_one_bit, *lshrsi3_1_one_bit_zext, *lshrsi3_one_bit_cmp,
+ *lshrsi3_one_bit_cconly, *lshrsi3_cmp_one_bit_zext,
+ *lshrhi3_1_one_bit, *lshrhi3_one_bit_cmp, *lshrhi3_one_bit_cconly,
+ *lshrqi3_1_one_bit, *lshrqi3_1_one_bit_slp, *lshrqi2_one_bit_cmp,
+ *lshrqi2_one_bit_cconly, *rotlsi3_1_one_bit_rex64, *rotlsi3_1_one_bit,
+ *rotlsi3_1_one_bit_zext, *rotlhi3_1_one_bit, *rotlqi3_1_one_bit_slp,
+ *rotlqi3_1_one_bit, *rotrdi3_1_one_bit_rex64, *rotrsi3_1_one_bit,
+ *rotrsi3_1_one_bit_zext, *rotrhi3_one_bit, *rotrqi3_1_one_bit,
+ *rotrqi3_1_one_bit_slp): Override length_immediate attribute to 0,
+ set mode attribute, don't override length attribute.
+ (*btsq, *btrq, *btcq, *btdi_rex64, *btsi): Set prefix_0f attribute
+ to 1.
+ (return_internal_long): Set length attribute to 2 instead of 1.
+ (*strmovqi_rex_1, *strsetqi_rex_1, *rep_stosqi_rex64,
+ *cmpstrnqi_nz_rex_1, *cmpstrnqi_rex_1, *strlenqi_rex_1): Clear
+ prefix_rex attribute.
+ * config/i386/predicates.md (ext_QIreg_operand,
+ const128_operand): New predicates.
+ (memory_displacement_only_operand): Always return 0 for
+ TARGET_64BIT.
+
+2009-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.md (adddi_4_rex64, addsi_4, addhi_4): For
+ operand2 -128 override length_immediate attribute to 1.
+ * config/i386/predicates.md (constm128_operand): New predicate.
+
+2009-05-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/39942
+ * config/i386/i386.c (ix86_avoid_jump_misspredicts): Replace
+ gen_align with gen_pad.
+ (ix86_reorg): Check ASM_OUTPUT_MAX_SKIP_PAD instead of
+ #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN.
+
+ * config/i386/i386.h (ASM_OUTPUT_MAX_SKIP_PAD): New.
+ * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
+
+ * config/i386/i386.md (align): Renamed to ...
+ (pad): This. Replace ASM_OUTPUT_MAX_SKIP_ALIGN with
+ ASM_OUTPUT_MAX_SKIP_PAD.
+
+2009-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/39942
+ * final.c (label_to_max_skip): New function.
+ (label_to_alignment): Only use LABEL_TO_ALIGNMENT if
+ CODE_LABEL_NUMBER <= max_labelno.
+ * output.h (label_to_max_skip): New prototype.
+ * config/i386/i386.c (ix86_avoid_jump_misspredicts): Renamed to...
+ (ix86_avoid_jump_mispredicts): ... this. Don't define if
+ ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined. Update comment.
+ Handle CODE_LABELs with >= 16 byte alignment or with
+ max_skip == (1 << align) - 1.
+ (ix86_reorg): Don't call ix86_avoid_jump_mispredicts if
+ ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined.
+
+2009-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_reorg): Call optimize_function_for_speed_p
+ only once.
+
+--- gcc/final.c.jj 2009-06-09 10:21:18.000000000 +0200
++++ gcc/final.c 2009-06-09 10:46:09.000000000 +0200
+@@ -553,7 +553,17 @@ static int min_labelno, max_labelno;
+ int
+ label_to_alignment (rtx label)
+ {
+- return LABEL_TO_ALIGNMENT (label);
++ if (CODE_LABEL_NUMBER (label) <= max_labelno)
++ return LABEL_TO_ALIGNMENT (label);
++ return 0;
++}
++
++int
++label_to_max_skip (rtx label)
++{
++ if (CODE_LABEL_NUMBER (label) <= max_labelno)
++ return LABEL_TO_MAX_SKIP (label);
++ return 0;
+ }
+
+ #ifdef HAVE_ATTR_length
+--- gcc/config/i386/i386.c.jj 2009-06-09 10:24:35.000000000 +0200
++++ gcc/config/i386/i386.c 2009-06-09 12:10:01.000000000 +0200
+@@ -8884,6 +8884,10 @@ ix86_decompose_address (rtx addr, struct
+ base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
+ index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+
++ /* Avoid useless 0 displacement. */
++ if (disp == const0_rtx && (base || index))
++ disp = NULL_RTX;
++
+ /* Allow arg pointer and stack pointer as index if there is not scaling. */
+ if (base_reg && index_reg && scale == 1
+ && (index_reg == arg_pointer_rtx
+@@ -8895,10 +8899,16 @@ ix86_decompose_address (rtx addr, struct
+ tmp = base_reg, base_reg = index_reg, index_reg = tmp;
+ }
+
+- /* Special case: %ebp cannot be encoded as a base without a displacement. */
+- if ((base_reg == hard_frame_pointer_rtx
+- || base_reg == frame_pointer_rtx
+- || base_reg == arg_pointer_rtx) && !disp)
++ /* Special case: %ebp cannot be encoded as a base without a displacement.
++ Similarly %r13. */
++ if (!disp
++ && base_reg
++ && (base_reg == hard_frame_pointer_rtx
++ || base_reg == frame_pointer_rtx
++ || base_reg == arg_pointer_rtx
++ || (REG_P (base_reg)
++ && (REGNO (base_reg) == HARD_FRAME_POINTER_REGNUM
++ || REGNO (base_reg) == R13_REG))))
+ disp = const0_rtx;
+
+ /* Special case: on K6, [%esi] makes the instruction vector decoded.
+@@ -8912,7 +8922,7 @@ ix86_decompose_address (rtx addr, struct
+ disp = const0_rtx;
+
+ /* Special case: encode reg+reg instead of reg*2. */
+- if (!base && index && scale && scale == 2)
++ if (!base && index && scale == 2)
+ base = index, base_reg = index_reg, scale = 1;
+
+ /* Special case: scaling cannot be encoded without base or displacement. */
+@@ -19240,23 +19250,53 @@ memory_address_length (rtx addr)
+
+ /* Rule of thumb:
+ - esp as the base always wants an index,
+- - ebp as the base always wants a displacement. */
++ - ebp as the base always wants a displacement,
++ - r12 as the base always wants an index,
++ - r13 as the base always wants a displacement. */
+
+ /* Register Indirect. */
+ if (base && !index && !disp)
+ {
+ /* esp (for its index) and ebp (for its displacement) need
+- the two-byte modrm form. */
+- if (addr == stack_pointer_rtx
+- || addr == arg_pointer_rtx
+- || addr == frame_pointer_rtx
+- || addr == hard_frame_pointer_rtx)
++ the two-byte modrm form. Similarly for r12 and r13 in 64-bit
++ code. */
++ if (REG_P (addr)
++ && (addr == arg_pointer_rtx
++ || addr == frame_pointer_rtx
++ || REGNO (addr) == SP_REG
++ || REGNO (addr) == BP_REG
++ || REGNO (addr) == R12_REG
++ || REGNO (addr) == R13_REG))
+ len = 1;
+ }
+
+- /* Direct Addressing. */
++ /* Direct Addressing. In 64-bit mode mod 00 r/m 5
++ is not disp32, but disp32(%rip), so for disp32
++ SIB byte is needed, unless print_operand_address
++ optimizes it into disp32(%rip) or (%rip) is implied
++ by UNSPEC. */
+ else if (disp && !base && !index)
+- len = 4;
++ {
++ len = 4;
++ if (TARGET_64BIT)
++ {
++ rtx symbol = disp;
++
++ if (GET_CODE (disp) == CONST)
++ symbol = XEXP (disp, 0);
++ if (GET_CODE (symbol) == PLUS
++ && CONST_INT_P (XEXP (symbol, 1)))
++ symbol = XEXP (symbol, 0);
++
++ if (GET_CODE (symbol) != LABEL_REF
++ && (GET_CODE (symbol) != SYMBOL_REF
++ || SYMBOL_REF_TLS_MODEL (symbol) != 0)
++ && (GET_CODE (symbol) != UNSPEC
++ || (XINT (symbol, 1) != UNSPEC_GOTPCREL
++ && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
++ len += 1;
++ }
++ }
+
+ else
+ {
+@@ -19268,19 +19308,31 @@ memory_address_length (rtx addr)
+ else
+ len = 4;
+ }
+- /* ebp always wants a displacement. */
+- else if (base == hard_frame_pointer_rtx)
+- len = 1;
++ /* ebp always wants a displacement. Similarly r13. */
++ else if (REG_P (base)
++ && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
++ len = 1;
+
+ /* An index requires the two-byte modrm form.... */
+ if (index
+- /* ...like esp, which always wants an index. */
+- || base == stack_pointer_rtx
++ /* ...like esp (or r12), which always wants an index. */
+ || base == arg_pointer_rtx
+- || base == frame_pointer_rtx)
++ || base == frame_pointer_rtx
++ || (REG_P (base)
++ && (REGNO (base) == SP_REG || REGNO (base) == R12_REG)))
+ len += 1;
+ }
+
++ switch (parts.seg)
++ {
++ case SEG_FS:
++ case SEG_GS:
++ len += 1;
++ break;
++ default:
++ break;
++ }
++
+ return len;
+ }
+
+@@ -19295,30 +19347,50 @@ ix86_attr_length_immediate_default (rtx
+ for (i = recog_data.n_operands - 1; i >= 0; --i)
+ if (CONSTANT_P (recog_data.operand[i]))
+ {
++ enum attr_mode mode = get_attr_mode (insn);
++
+ gcc_assert (!len);
+- if (shortform && satisfies_constraint_K (recog_data.operand[i]))
+- len = 1;
+- else
++ if (shortform && CONST_INT_P (recog_data.operand[i]))
+ {
+- switch (get_attr_mode (insn))
++ HOST_WIDE_INT ival = INTVAL (recog_data.operand[i]);
++ switch (mode)
+ {
+- case MODE_QI:
+- len+=1;
+- break;
+- case MODE_HI:
+- len+=2;
+- break;
+- case MODE_SI:
+- len+=4;
+- break;
+- /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
+- case MODE_DI:
+- len+=4;
+- break;
+- default:
+- fatal_insn ("unknown insn mode", insn);
++ case MODE_QI:
++ len = 1;
++ continue;
++ case MODE_HI:
++ ival = trunc_int_for_mode (ival, HImode);
++ break;
++ case MODE_SI:
++ ival = trunc_int_for_mode (ival, SImode);
++ break;
++ default:
++ break;
++ }
++ if (IN_RANGE (ival, -128, 127))
++ {
++ len = 1;
++ continue;
+ }
+ }
++ switch (mode)
++ {
++ case MODE_QI:
++ len = 1;
++ break;
++ case MODE_HI:
++ len = 2;
++ break;
++ case MODE_SI:
++ len = 4;
++ break;
++ /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
++ case MODE_DI:
++ len = 4;
++ break;
++ default:
++ fatal_insn ("unknown insn mode", insn);
++ }
+ }
+ return len;
+ }
+@@ -19330,22 +19402,45 @@ ix86_attr_length_address_default (rtx in
+
+ if (get_attr_type (insn) == TYPE_LEA)
+ {
+- rtx set = PATTERN (insn);
++ rtx set = PATTERN (insn), addr;
+
+ if (GET_CODE (set) == PARALLEL)
+ set = XVECEXP (set, 0, 0);
+
+ gcc_assert (GET_CODE (set) == SET);
+
+- return memory_address_length (SET_SRC (set));
++ addr = SET_SRC (set);
++ if (TARGET_64BIT && get_attr_mode (insn) == MODE_SI)
++ {
++ if (GET_CODE (addr) == ZERO_EXTEND)
++ addr = XEXP (addr, 0);
++ if (GET_CODE (addr) == SUBREG)
++ addr = SUBREG_REG (addr);
++ }
++
++ return memory_address_length (addr);
+ }
+
+ extract_insn_cached (insn);
+ for (i = recog_data.n_operands - 1; i >= 0; --i)
+ if (MEM_P (recog_data.operand[i]))
+ {
++ constrain_operands_cached (reload_completed);
++ if (which_alternative != -1)
++ {
++ const char *constraints = recog_data.constraints[i];
++ int alt = which_alternative;
++
++ while (*constraints == '=' || *constraints == '+')
++ constraints++;
++ while (alt-- > 0)
++ while (*constraints++ != ',')
++ ;
++ /* Skip ignored operands. */
++ if (*constraints == 'X')
++ continue;
++ }
+ return memory_address_length (XEXP (recog_data.operand[i], 0));
+- break;
+ }
+ return 0;
+ }
+@@ -19374,7 +19469,8 @@ ix86_attr_length_vex_default (rtx insn,
+ if (REG_P (recog_data.operand[i]))
+ {
+ /* REX.W bit uses 3 byte VEX prefix. */
+- if (GET_MODE (recog_data.operand[i]) == DImode)
++ if (GET_MODE (recog_data.operand[i]) == DImode
++ && GENERAL_REG_P (recog_data.operand[i]))
+ return 3 + 1;
+ }
+ else
+@@ -27112,6 +27208,7 @@ x86_function_profiler (FILE *file, int l
+ }
+ }
+
++#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+ /* We don't have exact information about the insn sizes, but we may assume
+ quite safely that we are informed about all 1 byte insns and memory
+ address sizes. This is enough to eliminate unnecessary padding in
+@@ -27162,7 +27259,7 @@ min_insn_size (rtx insn)
+ window. */
+
+ static void
+-ix86_avoid_jump_misspredicts (void)
++ix86_avoid_jump_mispredicts (void)
+ {
+ rtx insn, start = get_insns ();
+ int nbytes = 0, njumps = 0;
+@@ -27176,15 +27273,52 @@ ix86_avoid_jump_misspredicts (void)
+
+ The smallest offset in the page INSN can start is the case where START
+ ends on the offset 0. Offset of INSN is then NBYTES - sizeof (INSN).
+- We add p2align to 16byte window with maxskip 17 - NBYTES + sizeof (INSN).
++ We add p2align to 16byte window with maxskip 15 - NBYTES + sizeof (INSN).
+ */
+- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
++ for (insn = start; insn; insn = NEXT_INSN (insn))
+ {
++ int min_size;
++
++ if (GET_CODE (insn) == CODE_LABEL)
++ {
++ int align = label_to_alignment (insn);
++ int max_skip = label_to_max_skip (insn);
+
+- nbytes += min_insn_size (insn);
++ if (max_skip > 15)
++ max_skip = 15;
++ /* If align > 3, only up to 16 - max_skip - 1 bytes can be
++ already in the current 16 byte page, because otherwise
++ ASM_OUTPUT_MAX_SKIP_ALIGN could skip max_skip or fewer
++ bytes to reach 16 byte boundary. */
++ if (align <= 0
++ || (align <= 3 && max_skip != (1 << align) - 1))
++ max_skip = 0;
++ if (dump_file)
++ fprintf (dump_file, "Label %i with max_skip %i\n",
++ INSN_UID (insn), max_skip);
++ if (max_skip)
++ {
++ while (nbytes + max_skip >= 16)
++ {
++ start = NEXT_INSN (start);
++ if ((JUMP_P (start)
++ && GET_CODE (PATTERN (start)) != ADDR_VEC
++ && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC)
++ || CALL_P (start))
++ njumps--, isjump = 1;
++ else
++ isjump = 0;
++ nbytes -= min_insn_size (start);
++ }
++ }
++ continue;
++ }
++
++ min_size = min_insn_size (insn);
++ nbytes += min_size;
+ if (dump_file)
+- fprintf(dump_file, "Insn %i estimated to %i bytes\n",
+- INSN_UID (insn), min_insn_size (insn));
++ fprintf (dump_file, "Insn %i estimated to %i bytes\n",
++ INSN_UID (insn), min_size);
+ if ((JUMP_P (insn)
+ && GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
+@@ -27208,7 +27342,7 @@ ix86_avoid_jump_misspredicts (void)
+ gcc_assert (njumps >= 0);
+ if (dump_file)
+ fprintf (dump_file, "Interval %i to %i has %i bytes\n",
+- INSN_UID (start), INSN_UID (insn), nbytes);
++ INSN_UID (start), INSN_UID (insn), nbytes);
+
+ if (njumps == 3 && isjump && nbytes < 16)
+ {
+@@ -27217,10 +27351,11 @@ ix86_avoid_jump_misspredicts (void)
+ if (dump_file)
+ fprintf (dump_file, "Padding insn %i by %i bytes!\n",
+ INSN_UID (insn), padsize);
+- emit_insn_before (gen_align (GEN_INT (padsize)), insn);
++ emit_insn_before (gen_pad (GEN_INT (padsize)), insn);
+ }
+ }
+ }
++#endif
+
+ /* AMD Athlon works faster
+ when RET is not destination of conditional jump or directly preceded
+@@ -27280,12 +27415,15 @@ ix86_pad_returns (void)
+ static void
+ ix86_reorg (void)
+ {
+- if (TARGET_PAD_RETURNS && optimize
+- && optimize_function_for_speed_p (cfun))
+- ix86_pad_returns ();
+- if (TARGET_FOUR_JUMP_LIMIT && optimize
+- && optimize_function_for_speed_p (cfun))
+- ix86_avoid_jump_misspredicts ();
++ if (optimize && optimize_function_for_speed_p (cfun))
++ {
++ if (TARGET_PAD_RETURNS)
++ ix86_pad_returns ();
++#ifdef ASM_OUTPUT_MAX_SKIP_PAD
++ if (TARGET_FOUR_JUMP_LIMIT)
++ ix86_avoid_jump_mispredicts ();
++#endif
++ }
+ }
+
+ /* Return nonzero when QImode register that must be represented via REX prefix
+--- gcc/config/i386/predicates.md.jj 2009-03-13 15:50:39.000000000 +0100
++++ gcc/config/i386/predicates.md 2009-06-09 11:46:52.000000000 +0200
+@@ -76,6 +76,20 @@ (define_predicate "flags_reg_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == FLAGS_REG")))
+
++;; Return true if op is a QImode register operand other than
++;; %[abcd][hl].
++(define_predicate "ext_QIreg_operand"
++ (and (match_code "reg")
++ (match_test "TARGET_64BIT
++ && GET_MODE (op) == QImode
++ && REGNO (op) > BX_REG")))
++
++;; Similarly, but don't check mode of the operand.
++(define_predicate "ext_QIreg_nomode_operand"
++ (and (match_code "reg")
++ (match_test "TARGET_64BIT
++ && REGNO (op) > BX_REG")))
++
+ ;; Return true if op is not xmm0 register.
+ (define_predicate "reg_not_xmm0_operand"
+ (and (match_operand 0 "register_operand")
+@@ -574,6 +588,11 @@ (define_predicate "const8_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 8")))
+
++;; Match exactly 128.
++(define_predicate "const128_operand"
++ (and (match_code "const_int")
++ (match_test "INTVAL (op) == 128")))
++
+ ;; Match 2, 4, or 8. Used for leal multiplicands.
+ (define_predicate "const248_operand"
+ (match_code "const_int")
+@@ -878,6 +897,9 @@ (define_predicate "memory_displacement_o
+ struct ix86_address parts;
+ int ok;
+
++ if (TARGET_64BIT)
++ return 0;
++
+ ok = ix86_decompose_address (XEXP (op, 0), &parts);
+ gcc_assert (ok);
+
+--- gcc/config/i386/mmx.md.jj 2009-03-04 12:12:58.000000000 +0100
++++ gcc/config/i386/mmx.md 2009-06-09 11:46:52.000000000 +0200
+@@ -1,5 +1,5 @@
+ ;; GCC machine description for MMX and 3dNOW! instructions
+-;; Copyright (C) 2005, 2007, 2008
++;; Copyright (C) 2005, 2007, 2008, 2009
+ ;; Free Software Foundation, Inc.
+ ;;
+ ;; This file is part of GCC.
+@@ -85,6 +85,12 @@ (define_insn "*mov<mode>_internal_rex64"
+ %vmovq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,1,*,*,*")
++ (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,1,1,1")
++ (set (attr "prefix_rex")
++ (if_then_else (eq_attr "alternative" "8,9")
++ (symbol_ref "x86_extended_reg_mentioned_p (insn)")
++ (const_string "*")))
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "7,8,9,10,11")
+ (const_string "maybe_vex")
+@@ -111,6 +117,7 @@ (define_insn "*mov<mode>_internal_avx"
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "5,6,7")
+ (const_string "vex")
+@@ -141,6 +148,8 @@ (define_insn "*mov<mode>_internal"
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,1,1,*,1,*,*,*,*,*,*,*")
++ (set_attr "prefix_data16" "*,*,*,*,*,*,*,1,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+ (define_expand "movv2sf"
+@@ -175,6 +184,8 @@ (define_insn "*movv2sf_internal_rex64_av
+ vmovq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
++ (set_attr "length_vex" "*,*,*,*,*,*,*,*,*,*,*,4,4")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "7,8,9,10,11,12")
+ (const_string "vex")
+@@ -204,6 +215,7 @@ (define_insn "*movv2sf_internal_rex64"
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+ (define_insn "*movv2sf_internal_avx"
+@@ -227,6 +239,7 @@ (define_insn "*movv2sf_internal_avx"
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "5,6,7,8")
+ (const_string "vex")
+@@ -254,6 +267,7 @@ (define_insn "*movv2sf_internal"
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
++ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+ ;; %%% This multiword shite has got to go.
+@@ -313,6 +327,7 @@ (define_insn "*mmx_addv2sf3"
+ "TARGET_3DNOW && ix86_binary_operator_ok (PLUS, V2SFmode, operands)"
+ "pfadd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_expand "mmx_subv2sf3"
+@@ -338,6 +353,7 @@ (define_insn "*mmx_subv2sf3"
+ pfsub\t{%2, %0|%0, %2}
+ pfsubr\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_expand "mmx_mulv2sf3"
+@@ -354,6 +370,7 @@ (define_insn "*mmx_mulv2sf3"
+ "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V2SFmode, operands)"
+ "pfmul\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ ;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
+@@ -381,6 +398,7 @@ (define_insn "*mmx_<code>v2sf3_finite"
+ && ix86_binary_operator_ok (<CODE>, V2SFmode, operands)"
+ "pf<maxminfprefix>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "*mmx_<code>v2sf3"
+@@ -391,6 +409,7 @@ (define_insn "*mmx_<code>v2sf3"
+ "TARGET_3DNOW"
+ "pf<maxminfprefix>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_rcpv2sf2"
+@@ -400,6 +419,7 @@ (define_insn "mmx_rcpv2sf2"
+ "TARGET_3DNOW"
+ "pfrcp\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmx")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_rcpit1v2sf3"
+@@ -410,6 +430,7 @@ (define_insn "mmx_rcpit1v2sf3"
+ "TARGET_3DNOW"
+ "pfrcpit1\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_rcpit2v2sf3"
+@@ -420,6 +441,7 @@ (define_insn "mmx_rcpit2v2sf3"
+ "TARGET_3DNOW"
+ "pfrcpit2\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_rsqrtv2sf2"
+@@ -429,6 +451,7 @@ (define_insn "mmx_rsqrtv2sf2"
+ "TARGET_3DNOW"
+ "pfrsqrt\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmx")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_rsqit1v2sf3"
+@@ -439,6 +462,7 @@ (define_insn "mmx_rsqit1v2sf3"
+ "TARGET_3DNOW"
+ "pfrsqit1\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_haddv2sf3"
+@@ -457,6 +481,7 @@ (define_insn "mmx_haddv2sf3"
+ "TARGET_3DNOW"
+ "pfacc\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_hsubv2sf3"
+@@ -475,6 +500,7 @@ (define_insn "mmx_hsubv2sf3"
+ "TARGET_3DNOW_A"
+ "pfnacc\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_addsubv2sf3"
+@@ -488,6 +514,7 @@ (define_insn "mmx_addsubv2sf3"
+ "TARGET_3DNOW_A"
+ "pfpnacc\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -510,6 +537,7 @@ (define_insn "*mmx_eqv2sf3"
+ "TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
+ "pfcmpeq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_gtv2sf3"
+@@ -519,6 +547,7 @@ (define_insn "mmx_gtv2sf3"
+ "TARGET_3DNOW"
+ "pfcmpgt\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_gev2sf3"
+@@ -528,6 +557,7 @@ (define_insn "mmx_gev2sf3"
+ "TARGET_3DNOW"
+ "pfcmpge\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -542,6 +572,7 @@ (define_insn "mmx_pf2id"
+ "TARGET_3DNOW"
+ "pf2id\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_pf2iw"
+@@ -553,6 +584,7 @@ (define_insn "mmx_pf2iw"
+ "TARGET_3DNOW_A"
+ "pf2iw\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_pi2fw"
+@@ -564,6 +596,7 @@ (define_insn "mmx_pi2fw"
+ "TARGET_3DNOW_A"
+ "pi2fw\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "mmx_floatv2si2"
+@@ -572,6 +605,7 @@ (define_insn "mmx_floatv2si2"
+ "TARGET_3DNOW"
+ "pi2fd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -587,6 +621,7 @@ (define_insn "mmx_pswapdv2sf2"
+ "TARGET_3DNOW_A"
+ "pswapd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "V2SF")])
+
+ (define_insn "*vec_dupv2sf"
+@@ -887,6 +922,7 @@ (define_insn "*mmx_pmulhrwv4hi3"
+ "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmulhrw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "DI")])
+
+ (define_expand "sse2_umulv1siv1di3"
+@@ -965,6 +1001,10 @@ (define_insn "mmx_ashr<mode>3"
+ "TARGET_MMX"
+ "psra<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "mmx_lshr<mode>3"
+@@ -975,6 +1015,10 @@ (define_insn "mmx_lshr<mode>3"
+ "TARGET_MMX"
+ "psrl<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "mmx_ashl<mode>3"
+@@ -985,6 +1029,10 @@ (define_insn "mmx_ashl<mode>3"
+ "TARGET_MMX"
+ "psll<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "DI")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -1205,6 +1253,7 @@ (define_insn "*mmx_pinsrw"
+ return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+ }
+ [(set_attr "type" "mmxcvt")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "DI")])
+
+ (define_insn "mmx_pextrw"
+@@ -1216,6 +1265,7 @@ (define_insn "mmx_pextrw"
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "pextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "DI")])
+
+ (define_expand "mmx_pshufw"
+@@ -1253,6 +1303,7 @@ (define_insn "mmx_pshufw_1"
+ return "pshufw\t{%2, %1, %0|%0, %1, %2}";
+ }
+ [(set_attr "type" "mmxcvt")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "DI")])
+
+ (define_insn "mmx_pswapdv2si2"
+@@ -1263,6 +1314,7 @@ (define_insn "mmx_pswapdv2si2"
+ "TARGET_3DNOW_A"
+ "pswapd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "DI")])
+
+ (define_insn "*vec_dupv4hi"
+@@ -1273,6 +1325,7 @@ (define_insn "*vec_dupv4hi"
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "pshufw\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "mmxcvt")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "DI")])
+
+ (define_insn "*vec_dupv2si"
+@@ -1345,6 +1398,7 @@ (define_insn "*vec_extractv2si_1"
+ #
+ #"
+ [(set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,mmxmov,ssemov,imov")
++ (set_attr "length_immediate" "*,*,1,*,*,*,*")
+ (set_attr "mode" "DI,TI,TI,V4SF,SI,SI,SI")])
+
+ (define_split
+@@ -1492,6 +1546,11 @@ (define_insn "*mmx_uavgv8qi3"
+ return "pavgusb\t{%2, %0|%0, %2}";
+ }
+ [(set_attr "type" "mmxshft")
++ (set (attr "prefix_extra")
++ (if_then_else
++ (eq (symbol_ref "(TARGET_SSE || TARGET_3DNOW_A)") (const_int 0))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_expand "mmx_uavgv4hi3"
+@@ -1602,6 +1661,7 @@ (define_insn "mmx_emms"
+ "TARGET_MMX"
+ "emms"
+ [(set_attr "type" "mmx")
++ (set_attr "modrm" "0")
+ (set_attr "memory" "unknown")])
+
+ (define_insn "mmx_femms"
+@@ -1625,4 +1685,5 @@ (define_insn "mmx_femms"
+ "TARGET_3DNOW"
+ "femms"
+ [(set_attr "type" "mmx")
++ (set_attr "modrm" "0")
+ (set_attr "memory" "none")])
+--- gcc/config/i386/sse.md.jj 2009-06-09 10:21:38.000000000 +0200
++++ gcc/config/i386/sse.md 2009-06-09 11:46:53.000000000 +0200
+@@ -439,6 +439,7 @@ (define_insn "sse2_movntsi"
+ "TARGET_SSE2"
+ "movnti\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_data16" "0")
+ (set_attr "mode" "V2DF")])
+
+ (define_insn "avx_lddqu<avxmodesuffix>"
+@@ -461,6 +462,7 @@ (define_insn "sse3_lddqu"
+ "lddqu\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "movu" "1")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "1")
+ (set_attr "mode" "TI")])
+
+@@ -1409,6 +1411,7 @@ (define_insn "avx_cmpp<avxmodesuffixf2c>
+ "TARGET_AVX"
+ "vcmpp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -1425,6 +1428,7 @@ (define_insn "avx_cmps<ssemodesuffixf2c>
+ "TARGET_AVX"
+ "vcmps<ssemodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<ssescalarmode>")])
+
+@@ -1439,6 +1443,7 @@ (define_insn "*avx_maskcmp<mode>3"
+ "vcmp%D3p<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "prefix" "vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<avxvecmode>")])
+
+ (define_insn "<sse>_maskcmp<mode>3"
+@@ -1450,6 +1455,7 @@ (define_insn "<sse>_maskcmp<mode>3"
+ && !TARGET_SSE5"
+ "cmp%D3<ssemodesuffixf4>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "<sse>_vmmaskcmp<mode>3"
+@@ -1463,6 +1469,7 @@ (define_insn "<sse>_vmmaskcmp<mode>3"
+ "SSE_VEC_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5"
+ "cmp%D3s<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<ssescalarmode>")])
+
+ (define_insn "<sse>_comi"
+@@ -1478,6 +1485,11 @@ (define_insn "<sse>_comi"
+ "%vcomis<ssemodefsuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "prefix_rep" "0")
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "DF")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "<sse>_ucomi"
+@@ -1493,6 +1505,11 @@ (define_insn "<sse>_ucomi"
+ "%vucomis<ssemodefsuffix>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "prefix_rep" "0")
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "DF")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "<MODE>")])
+
+ (define_expand "vcond<mode>"
+@@ -2224,6 +2241,7 @@ (define_insn "sse_cvttps2pi"
+ "cvttps2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx")
++ (set_attr "prefix_rep" "0")
+ (set_attr "mode" "SF")])
+
+ (define_insn "*avx_cvtsi2ss"
+@@ -2263,6 +2281,7 @@ (define_insn "*avx_cvtsi2ssq"
+ "TARGET_AVX && TARGET_64BIT"
+ "vcvtsi2ssq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseicvt")
++ (set_attr "length_vex" "4")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "SF")])
+
+@@ -2276,6 +2295,7 @@ (define_insn "sse_cvtsi2ssq"
+ "TARGET_SSE && TARGET_64BIT"
+ "cvtsi2ssq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
++ (set_attr "prefix_rex" "1")
+ (set_attr "athlon_decode" "vector,double")
+ (set_attr "amdfam10_decode" "vector,double")
+ (set_attr "mode" "SF")])
+@@ -2422,6 +2442,7 @@ (define_insn "sse2_cvttps2dq"
+ "cvttps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix_rep" "1")
++ (set_attr "prefix_data16" "0")
+ (set_attr "mode" "TI")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -2437,6 +2458,7 @@ (define_insn "sse2_cvtpi2pd"
+ "cvtpi2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx,*")
++ (set_attr "prefix_data16" "1,*")
+ (set_attr "mode" "V2DF")])
+
+ (define_insn "sse2_cvtpd2pi"
+@@ -2497,6 +2519,7 @@ (define_insn "*avx_cvtsi2sdq"
+ "TARGET_AVX && TARGET_64BIT"
+ "vcvtsi2sdq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseicvt")
++ (set_attr "length_vex" "4")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "DF")])
+
+@@ -2510,6 +2533,7 @@ (define_insn "sse2_cvtsi2sdq"
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsi2sdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
++ (set_attr "prefix_rex" "1")
+ (set_attr "mode" "DF")
+ (set_attr "athlon_decode" "double,direct")
+ (set_attr "amdfam10_decode" "vector,double")])
+@@ -2651,6 +2675,7 @@ (define_insn "*sse2_cvtpd2dq"
+ : \"cvtpd2dq\t{%1, %0|%0, %1}\";"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix_rep" "1")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")
+ (set_attr "amdfam10_decode" "double")])
+@@ -2681,7 +2706,6 @@ (define_insn "*sse2_cvttpd2dq"
+ "* return TARGET_AVX ? \"vcvttpd2dq{x}\t{%1, %0|%0, %1}\"
+ : \"cvttpd2dq\t{%1, %0|%0, %1}\";"
+ [(set_attr "type" "ssecvt")
+- (set_attr "prefix_rep" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")
+ (set_attr "amdfam10_decode" "double")])
+@@ -2800,6 +2824,7 @@ (define_insn "sse2_cvtps2pd"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "V2DF")
++ (set_attr "prefix_data16" "0")
+ (set_attr "amdfam10_decode" "direct")])
+
+ (define_expand "vec_unpacks_hi_v4sf"
+@@ -3270,6 +3295,7 @@ (define_insn "avx_shufps256_1"
+ return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -3311,6 +3337,7 @@ (define_insn "*avx_shufps_<mode>"
+ return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+@@ -3336,6 +3363,7 @@ (define_insn "sse_shufps_<mode>"
+ return "shufps\t{%3, %2, %0|%0, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V4SF")])
+
+ (define_insn "sse_storehps"
+@@ -3443,6 +3471,7 @@ (define_insn "*avx_loadlps"
+ vmovlps\t{%2, %1, %0|%0, %1, %2}
+ vmovlps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
++ (set_attr "length_immediate" "1,*,*")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF,V2SF,V2SF")])
+
+@@ -3459,6 +3488,7 @@ (define_insn "sse_loadlps"
+ movlps\t{%2, %0|%0, %2}
+ movlps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
++ (set_attr "length_immediate" "1,*,*")
+ (set_attr "mode" "V4SF,V2SF,V2SF")])
+
+ (define_insn "*avx_movss"
+@@ -3491,6 +3521,7 @@ (define_insn "*vec_dupv4sf_avx"
+ "TARGET_AVX"
+ "vshufps\t{$0, %1, %1, %0|%0, %1, %1, 0}"
+ [(set_attr "type" "sselog1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+@@ -3501,6 +3532,7 @@ (define_insn "*vec_dupv4sf"
+ "TARGET_SSE"
+ "shufps\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "sselog1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V4SF")])
+
+ (define_insn "*vec_concatv2sf_avx"
+@@ -3516,6 +3548,8 @@ (define_insn "*vec_concatv2sf_avx"
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
++ (set_attr "length_immediate" "*,1,*,*,*")
++ (set_attr "prefix_extra" "*,1,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "3,4")
+ (const_string "orig")
+@@ -3537,7 +3571,9 @@ (define_insn "*vec_concatv2sf_sse4_1"
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
++ (set_attr "prefix_data16" "*,1,*,*,*")
+ (set_attr "prefix_extra" "*,1,*,*,*")
++ (set_attr "length_immediate" "*,1,*,*,*")
+ (set_attr "mode" "V4SF,V4SF,SF,DI,DI")])
+
+ ;; ??? In theory we can match memory for the MMX alternative, but allowing
+@@ -3638,6 +3674,8 @@ (define_insn "*vec_setv4sf_avx"
+ return "vinsertps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+@@ -3654,7 +3692,9 @@ (define_insn "*vec_setv4sf_sse4_1"
+ return "insertps\t{%3, %2, %0|%0, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V4SF")])
+
+ (define_insn "*avx_insertps"
+@@ -3667,6 +3707,8 @@ (define_insn "*avx_insertps"
+ "vinsertps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ [(set_attr "type" "sselog")
+ (set_attr "prefix" "vex")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V4SF")])
+
+ (define_insn "sse4_1_insertps"
+@@ -3678,7 +3720,9 @@ (define_insn "sse4_1_insertps"
+ "TARGET_SSE4_1"
+ "insertps\t{%3, %2, %0|%0, %2, %3}";
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V4SF")])
+
+ (define_split
+@@ -3753,6 +3797,8 @@ (define_insn "vec_extract_lo_<mode>"
+ "TARGET_AVX"
+ "vextractf128\t{$0x0, %1, %0|%0, %1, 0x0}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3765,6 +3811,8 @@ (define_insn "vec_extract_hi_<mode>"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3778,6 +3826,8 @@ (define_insn "vec_extract_lo_<mode>"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3791,6 +3841,8 @@ (define_insn "vec_extract_hi_<mode>"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3806,6 +3858,8 @@ (define_insn "vec_extract_lo_v16hi"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3821,6 +3875,8 @@ (define_insn "vec_extract_hi_v16hi"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3840,6 +3896,8 @@ (define_insn "vec_extract_lo_v32qi"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3859,6 +3917,8 @@ (define_insn "vec_extract_hi_v32qi"
+ "TARGET_AVX"
+ "vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,store")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+@@ -3871,7 +3931,9 @@ (define_insn "*sse4_1_extractps"
+ "TARGET_SSE4_1"
+ "%vextractps\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "V4SF")])
+
+@@ -3964,6 +4026,7 @@ (define_insn "sse2_unpckhpd"
+ movlpd\t{%H1, %0|%0, %H1}
+ movhpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
++ (set_attr "prefix_data16" "*,1,1")
+ (set_attr "mode" "V2DF,V1DF,V1DF")])
+
+ (define_insn "avx_movddup256"
+@@ -4084,6 +4147,7 @@ (define_insn "sse2_unpcklpd"
+ movhpd\t{%2, %0|%0, %2}
+ movlpd\t{%2, %H0|%H0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
++ (set_attr "prefix_data16" "*,1,1")
+ (set_attr "mode" "V2DF,V1DF,V1DF")])
+
+ (define_expand "avx_shufpd256"
+@@ -4124,6 +4188,7 @@ (define_insn "avx_shufpd256_1"
+ return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4DF")])
+
+@@ -4260,6 +4325,7 @@ (define_insn "*avx_shufpd_<mode>"
+ return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V2DF")])
+
+@@ -4281,6 +4347,7 @@ (define_insn "sse2_shufpd_<mode>"
+ return "shufpd\t{%3, %2, %0|%0, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "V2DF")])
+
+ ;; Avoid combining registers from different units in a single alternative,
+@@ -4314,6 +4381,7 @@ (define_insn "sse2_storehpd"
+ #
+ #"
+ [(set_attr "type" "ssemov,sselog1,ssemov,fmov,imov")
++ (set_attr "prefix_data16" "1,*,*,*,*")
+ (set_attr "mode" "V1DF,V2DF,DF,DF,DF")])
+
+ (define_split
+@@ -4342,6 +4410,7 @@ (define_insn "sse2_storelpd"
+ #
+ #"
+ [(set_attr "type" "ssemov,ssemov,ssemov,fmov,imov")
++ (set_attr "prefix_data16" "1,*,*,*,*")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "V1DF,DF,DF,DF,DF")])
+
+@@ -4408,6 +4477,8 @@ (define_insn "sse2_loadhpd"
+ #
+ #"
+ [(set_attr "type" "ssemov,sselog,sselog,ssemov,fmov,imov")
++ (set_attr "prefix_data16" "1,*,*,*,*,*")
++ (set_attr "length_immediate" "*,*,1,*,*,*")
+ (set_attr "mode" "V1DF,V2DF,V2DF,DF,DF,DF")])
+
+ (define_split
+@@ -4471,6 +4542,8 @@ (define_insn "sse2_loadlpd"
+ #
+ #"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov,fmov,imov")
++ (set_attr "prefix_data16" "*,1,*,*,1,*,*,*")
++ (set_attr "length_immediate" "*,*,*,1,*,*,*,*")
+ (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,DF,DF,DF")])
+
+ (define_split
+@@ -4546,6 +4619,8 @@ (define_insn "sse2_movsd"
+ movhps\t{%H1, %0|%0, %H1}
+ movhps\t{%1, %H0|%H0, %1}"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
++ (set_attr "prefix_data16" "*,1,1,*,*,*")
++ (set_attr "length_immediate" "*,*,*,1,*,*")
+ (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,V1DF")])
+
+ (define_insn "*vec_dupv2df_sse3"
+@@ -4605,6 +4680,7 @@ (define_insn "*vec_concatv2df"
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov,ssemov,ssemov")
++ (set_attr "prefix_data16" "*,1,*,*,*")
+ (set_attr "mode" "V2DF,V1DF,DF,V4SF,V2SF")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -4953,6 +5029,7 @@ (define_insn "*avx_mulv2siv2di3"
+ "TARGET_AVX && ix86_binary_operator_ok (MULT, V4SImode, operands)"
+ "vpmuldq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseimul")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -5099,6 +5176,7 @@ (define_insn "*avx_mulv4si3"
+ "TARGET_AVX && ix86_binary_operator_ok (MULT, V4SImode, operands)"
+ "vpmulld\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseimul")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -5494,6 +5572,10 @@ (define_insn "*avx_ashr<mode>3"
+ "vpsra<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix" "vex")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_insn "ashr<mode>3"
+@@ -5505,6 +5587,10 @@ (define_insn "ashr<mode>3"
+ "psra<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "1")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_insn "*avx_lshr<mode>3"
+@@ -5516,6 +5602,10 @@ (define_insn "*avx_lshr<mode>3"
+ "vpsrl<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix" "vex")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_insn "lshr<mode>3"
+@@ -5527,6 +5617,10 @@ (define_insn "lshr<mode>3"
+ "psrl<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "1")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_insn "*avx_ashl<mode>3"
+@@ -5538,6 +5632,10 @@ (define_insn "*avx_ashl<mode>3"
+ "vpsll<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix" "vex")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_insn "ashl<mode>3"
+@@ -5549,6 +5647,10 @@ (define_insn "ashl<mode>3"
+ "psll<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "1")
++ (set (attr "length_immediate")
++ (if_then_else (match_operand 2 "const_int_operand" "")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "mode" "TI")])
+
+ (define_expand "vec_shl_<mode>"
+@@ -5579,6 +5681,12 @@ (define_insn "*avx_<code><mode>3"
+ "TARGET_AVX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+ "vp<maxminiprefix><ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set (attr "prefix_extra")
++ (if_then_else
++ (ne (symbol_ref "<MODE>mode != ((<CODE> == SMAX || <CODE> == SMIN) ? V8HImode : V16QImode)")
++ (const_int 0))
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -5783,6 +5891,10 @@ (define_insn "*avx_eq<mode>3"
+ "TARGET_AVX && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+ "vpcmpeq<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
++ (set (attr "prefix_extra")
++ (if_then_else (match_operand:V2DI 0 "" "")
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -5825,6 +5937,10 @@ (define_insn "*avx_gt<mode>3"
+ "TARGET_AVX"
+ "vpcmpgt<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecmp")
++ (set (attr "prefix_extra")
++ (if_then_else (match_operand:V2DI 0 "" "")
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -5847,6 +5963,7 @@ (define_insn "sse4_2_gtv2di3"
+ "TARGET_SSE4_2"
+ "pcmpgtq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "vcond<mode>"
+@@ -6605,6 +6722,11 @@ (define_insn "*avx_pinsr<avxmodesuffixs>
+ return "vpinsr<avxmodesuffixs>\t{%3, %k2, %1, %0|%0, %1, %k2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set (attr "prefix_extra")
++ (if_then_else (match_operand:V8HI 0 "register_operand" "")
++ (const_string "0")
++ (const_string "1")))
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -6622,6 +6744,7 @@ (define_insn "*sse4_1_pinsrb"
+ }
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*sse2_pinsrw"
+@@ -6638,6 +6761,7 @@ (define_insn "*sse2_pinsrw"
+ }
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ ;; It must come before sse2_loadld since it is preferred.
+@@ -6655,6 +6779,7 @@ (define_insn "*sse4_1_pinsrd"
+ }
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*avx_pinsrq"
+@@ -6670,6 +6795,8 @@ (define_insn "*avx_pinsrq"
+ return "vpinsrq\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -6686,7 +6813,9 @@ (define_insn "*sse4_1_pinsrq"
+ return "pinsrq\t{%3, %2, %0|%0, %2, %3}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_rex" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*sse4_1_pextrb"
+@@ -6699,6 +6828,7 @@ (define_insn "*sse4_1_pextrb"
+ "%vpextrb\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6711,6 +6841,7 @@ (define_insn "*sse4_1_pextrb_memory"
+ "%vpextrb\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6724,6 +6855,7 @@ (define_insn "*sse2_pextrw"
+ "%vpextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6736,6 +6868,7 @@ (define_insn "*sse4_1_pextrw_memory"
+ "%vpextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6748,6 +6881,7 @@ (define_insn "*sse4_1_pextrd"
+ "%vpextrd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6760,7 +6894,9 @@ (define_insn "*sse4_1_pextrq"
+ "TARGET_SSE4_1 && TARGET_64BIT"
+ "%vpextrq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_rex" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -6800,7 +6936,8 @@ (define_insn "sse2_pshufd_1"
+ }
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_data16" "1")
+- (set_attr "prefix" "vex")
++ (set_attr "prefix" "maybe_vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "sse2_pshuflw"
+@@ -6842,8 +6979,10 @@ (define_insn "sse2_pshuflw_1"
+ return "%vpshuflw\t{%2, %1, %0|%0, %1, %2}";
+ }
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "1")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "sse2_pshufhw"
+@@ -6886,7 +7025,9 @@ (define_insn "sse2_pshufhw_1"
+ }
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_rep" "1")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "sse2_loadd"
+@@ -7022,6 +7163,7 @@ (define_insn "*vec_extractv2di_1_rex64_a
+ vmovq\t{%H1, %0|%0, %H1}
+ vmov{q}\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov,sseishft,ssemov,imov")
++ (set_attr "length_immediate" "*,1,*,*")
+ (set_attr "memory" "*,none,*,*")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V2SF,TI,TI,DI")])
+@@ -7038,6 +7180,7 @@ (define_insn "*vec_extractv2di_1_rex64"
+ movq\t{%H1, %0|%0, %H1}
+ mov{q}\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov,sseishft,ssemov,imov")
++ (set_attr "length_immediate" "*,1,*,*")
+ (set_attr "atom_unit" "*,sishuf,*,*")
+ (set_attr "memory" "*,none,*,*")
+ (set_attr "mode" "V2SF,TI,TI,DI")])
+@@ -7055,6 +7198,7 @@ (define_insn "*vec_extractv2di_1_avx"
+ vpsrldq\t{$8, %1, %0|%0, %1, 8}
+ vmovq\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov,sseishft,ssemov")
++ (set_attr "length_immediate" "*,1,*")
+ (set_attr "memory" "*,none,*")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V2SF,TI,TI")])
+@@ -7071,6 +7215,7 @@ (define_insn "*vec_extractv2di_1_sse2"
+ psrldq\t{$8, %0|%0, 8}
+ movq\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov,sseishft,ssemov")
++ (set_attr "length_immediate" "*,1,*")
+ (set_attr "atom_unit" "*,sishuf,*")
+ (set_attr "memory" "*,none,*")
+ (set_attr "mode" "V2SF,TI,TI")])
+@@ -7100,6 +7245,7 @@ (define_insn "*vec_dupv4si"
+ shufps\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix" "maybe_vex,orig")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI,V4SF")])
+
+ (define_insn "*vec_dupv2di_avx"
+@@ -7136,6 +7282,8 @@ (define_insn "*vec_concatv2si_avx"
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
++ (set_attr "prefix_extra" "1,*,*,*,*")
++ (set_attr "length_immediate" "1,*,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "3,4")
+ (const_string "orig")
+@@ -7156,6 +7304,7 @@ (define_insn "*vec_concatv2si_sse4_1"
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "prefix_extra" "1,*,*,*,*")
++ (set_attr "length_immediate" "1,*,*,*,*")
+ (set_attr "mode" "TI,TI,TI,DI,DI")])
+
+ ;; ??? In theory we can match memory for the MMX alternative, but allowing
+@@ -7262,6 +7411,8 @@ (define_insn "*vec_concatv2di_rex64_avx"
+ vpunpcklqdq\t{%2, %1, %0|%0, %1, %2}
+ vmovhps\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov")
++ (set_attr "prefix_extra" "1,*,*,*,*,*")
++ (set_attr "length_immediate" "1,*,*,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "3")
+ (const_string "orig")
+@@ -7283,7 +7434,9 @@ (define_insn "*vec_concatv2di_rex64_sse4
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
++ (set_attr "prefix_rex" "1,*,1,*,*,*,*")
+ (set_attr "prefix_extra" "1,*,*,*,*,*,*")
++ (set_attr "length_immediate" "1,*,*,*,*,*,*")
+ (set_attr "mode" "TI,TI,TI,TI,TI,V4SF,V2SF")])
+
+ (define_insn "*vec_concatv2di_rex64_sse"
+@@ -7300,6 +7453,7 @@ (define_insn "*vec_concatv2di_rex64_sse"
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
++ (set_attr "prefix_rex" "*,1,*,*,*,*")
+ (set_attr "mode" "TI,TI,TI,TI,V4SF,V2SF")])
+
+ (define_expand "vec_unpacku_hi_v16qi"
+@@ -7686,6 +7840,8 @@ (define_insn "*sse2_maskmovdqu"
+ "%vmaskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_data16" "1")
++ ;; The implicit %rdi operand confuses default length_vex computation.
++ (set_attr "length_vex" "3")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -7700,6 +7856,9 @@ (define_insn "*sse2_maskmovdqu_rex64"
+ "%vmaskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_data16" "1")
++ ;; The implicit %rdi operand confuses default length_vex computation.
++ (set (attr "length_vex")
++ (symbol_ref ("REGNO (operands[2]) >= FIRST_REX_SSE_REG ? 3 + 1 : 2 + 1")))
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -7738,6 +7897,7 @@ (define_insn "*sse_sfence"
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "sfence"
+ [(set_attr "type" "sse")
++ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "fence")
+ (set_attr "memory" "unknown")])
+
+@@ -7765,6 +7925,7 @@ (define_insn "*sse2_mfence"
+ "TARGET_64BIT || TARGET_SSE2"
+ "mfence"
+ [(set_attr "type" "sse")
++ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "fence")
+ (set_attr "memory" "unknown")])
+
+@@ -7783,6 +7944,7 @@ (define_insn "*sse2_lfence"
+ "TARGET_SSE2"
+ "lfence"
+ [(set_attr "type" "sse")
++ (set_attr "length_address" "0")
+ (set_attr "atom_sse_attr" "lfence")
+ (set_attr "memory" "unknown")])
+
+@@ -7864,6 +8026,7 @@ (define_insn "*avx_phaddwv8hi3"
+ "TARGET_AVX"
+ "vphaddw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -7938,6 +8101,7 @@ (define_insn "ssse3_phaddwv4hi3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_phadddv4si3"
+@@ -7964,6 +8128,7 @@ (define_insn "*avx_phadddv4si3"
+ "TARGET_AVX"
+ "vphaddd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8014,6 +8179,7 @@ (define_insn "ssse3_phadddv2si3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_phaddswv8hi3"
+@@ -8056,6 +8222,7 @@ (define_insn "*avx_phaddswv8hi3"
+ "TARGET_AVX"
+ "vphaddsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8130,6 +8297,7 @@ (define_insn "ssse3_phaddswv4hi3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_phsubwv8hi3"
+@@ -8172,6 +8340,7 @@ (define_insn "*avx_phsubwv8hi3"
+ "TARGET_AVX"
+ "vphsubw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8246,6 +8415,7 @@ (define_insn "ssse3_phsubwv4hi3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_phsubdv4si3"
+@@ -8272,6 +8442,7 @@ (define_insn "*avx_phsubdv4si3"
+ "TARGET_AVX"
+ "vphsubd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8322,6 +8493,7 @@ (define_insn "ssse3_phsubdv2si3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_phsubswv8hi3"
+@@ -8364,6 +8536,7 @@ (define_insn "*avx_phsubswv8hi3"
+ "TARGET_AVX"
+ "vphsubsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8438,6 +8611,7 @@ (define_insn "ssse3_phsubswv4hi3"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "complex")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_pmaddubsw128"
+@@ -8490,6 +8664,7 @@ (define_insn "*avx_pmaddubsw128"
+ "TARGET_AVX"
+ "vpmaddubsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseiadd")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8584,6 +8759,7 @@ (define_insn "ssse3_pmaddubsw"
+ [(set_attr "type" "sseiadd")
+ (set_attr "atom_unit" "simul")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_expand "ssse3_pmulhrswv8hi3"
+@@ -8626,6 +8802,7 @@ (define_insn "*avx_pmulhrswv8hi3"
+ "TARGET_AVX && ix86_binary_operator_ok (MULT, V8HImode, operands)"
+ "vpmulhrsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseimul")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8690,6 +8867,7 @@ (define_insn "*ssse3_pmulhrswv4hi3"
+ "pmulhrsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_pshufbv16qi3"
+@@ -8700,6 +8878,7 @@ (define_insn "*avx_pshufbv16qi3"
+ "TARGET_AVX"
+ "vpshufb\t{%2, %1, %0|%0, %1, %2}";
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8724,6 +8903,7 @@ (define_insn "ssse3_pshufbv8qi3"
+ "pshufb\t{%2, %0|%0, %2}";
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_psign<mode>3"
+@@ -8735,6 +8915,7 @@ (define_insn "*avx_psign<mode>3"
+ "TARGET_AVX"
+ "vpsign<ssevecsize>\t{%2, %1, %0|%0, %1, %2}";
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8761,6 +8942,7 @@ (define_insn "ssse3_psign<mode>3"
+ "psign<mmxvecsize>\t{%2, %0|%0, %2}";
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*avx_palignrti"
+@@ -8775,6 +8957,8 @@ (define_insn "*avx_palignrti"
+ return "vpalignr\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ }
+ [(set_attr "type" "sseishft")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -8793,6 +8977,7 @@ (define_insn "ssse3_palignrti"
+ (set_attr "atom_unit" "sishuf")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "ssse3_palignrdi"
+@@ -8809,6 +8994,8 @@ (define_insn "ssse3_palignrdi"
+ [(set_attr "type" "sseishft")
+ (set_attr "atom_unit" "sishuf")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ (define_insn "abs<mode>2"
+@@ -8828,7 +9015,9 @@ (define_insn "abs<mode>2"
+ "TARGET_SSSE3"
+ "pabs<mmxvecsize>\t{%1, %0|%0, %1}";
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
+ (set_attr "mode" "DI")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -8869,6 +9058,7 @@ (define_insn "sse4a_extrqi"
+ "extrq\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sse")
+ (set_attr "prefix_data16" "1")
++ (set_attr "length_immediate" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse4a_extrq"
+@@ -8892,7 +9082,9 @@ (define_insn "sse4a_insertqi"
+ "TARGET_SSE4A"
+ "insertq\t{%4, %3, %2, %0|%0, %2, %3, %4}"
+ [(set_attr "type" "sseins")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "1")
++ (set_attr "length_immediate" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse4a_insertq"
+@@ -8903,6 +9095,7 @@ (define_insn "sse4a_insertq"
+ "TARGET_SSE4A"
+ "insertq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseins")
++ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "1")
+ (set_attr "mode" "TI")])
+
+@@ -8921,6 +9114,8 @@ (define_insn "avx_blendp<avxmodesuffixf2
+ "TARGET_AVX"
+ "vblendp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<avxvecmode>")])
+
+@@ -8934,6 +9129,8 @@ (define_insn "avx_blendvp<avxmodesuffixf
+ "TARGET_AVX"
+ "vblendvp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<avxvecmode>")])
+
+@@ -8946,7 +9143,9 @@ (define_insn "sse4_1_blendp<ssemodesuffi
+ "TARGET_SSE4_1"
+ "blendp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "sse4_1_blendvp<ssemodesuffixf2c>"
+@@ -8959,6 +9158,7 @@ (define_insn "sse4_1_blendvp<ssemodesuff
+ "TARGET_SSE4_1"
+ "blendvp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
+ (set_attr "mode" "<MODE>")])
+
+@@ -8973,6 +9173,8 @@ (define_insn "avx_dpp<avxmodesuffixf2c><
+ "vdpp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssemul")
+ (set_attr "prefix" "vex")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<avxvecmode>")])
+
+ (define_insn "sse4_1_dpp<ssemodesuffixf2c>"
+@@ -8985,7 +9187,9 @@ (define_insn "sse4_1_dpp<ssemodesuffixf2
+ "TARGET_SSE4_1"
+ "dpp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssemul")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "sse4_1_movntdqa"
+@@ -9009,6 +9213,8 @@ (define_insn "*avx_mpsadbw"
+ "vmpsadbw\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix" "vex")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse4_1_mpsadbw"
+@@ -9021,6 +9227,7 @@ (define_insn "sse4_1_mpsadbw"
+ "mpsadbw\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*avx_packusdw"
+@@ -9033,6 +9240,7 @@ (define_insn "*avx_packusdw"
+ "TARGET_AVX"
+ "vpackusdw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -9058,6 +9266,8 @@ (define_insn "*avx_pblendvb"
+ "TARGET_AVX"
+ "vpblendvb\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -9083,6 +9293,8 @@ (define_insn "*avx_pblendw"
+ "vpblendw\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix" "vex")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse4_1_pblendw"
+@@ -9095,6 +9307,7 @@ (define_insn "sse4_1_pblendw"
+ "pblendw\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse4_1_phminposuw"
+@@ -9506,6 +9719,7 @@ (define_insn "avx_vtestp<avxmodesuffixf2
+ "TARGET_AVX"
+ "vtestp<avxmodesuffixf2c>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -9519,6 +9733,7 @@ (define_insn "avx_ptest256"
+ "TARGET_AVX"
+ "vptest\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+
+@@ -9543,6 +9758,8 @@ (define_insn "avx_roundp<avxmodesuffixf2
+ "TARGET_AVX"
+ "vroundp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -9555,7 +9772,9 @@ (define_insn "sse4_1_roundp<ssemodesuffi
+ "TARGET_ROUND"
+ "%vroundp<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "ssecvt")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -9571,6 +9790,8 @@ (define_insn "*avx_rounds<ssemodesuffixf
+ "TARGET_AVX"
+ "vrounds<ssemodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "ssecvt")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -9586,7 +9807,9 @@ (define_insn "sse4_1_rounds<ssemodesuffi
+ "TARGET_ROUND"
+ "rounds<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecvt")
++ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+@@ -9648,6 +9871,7 @@ (define_insn_and_split "sse4_2_pcmpestr"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+
+@@ -9674,6 +9898,7 @@ (define_insn "sse4_2_pcmpestri"
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+
+@@ -9699,6 +9924,7 @@ (define_insn "sse4_2_pcmpestrm"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+@@ -9723,6 +9949,7 @@ (define_insn "sse4_2_pcmpestr_cconly"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,load,none,load")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+@@ -9771,6 +9998,7 @@ (define_insn_and_split "sse4_2_pcmpistr"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+
+@@ -9792,6 +10020,7 @@ (define_insn "sse4_2_pcmpistri"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+@@ -9814,6 +10043,7 @@ (define_insn "sse4_2_pcmpistrm"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "memory" "none,load")
+ (set_attr "mode" "TI")])
+@@ -9836,6 +10066,7 @@ (define_insn "sse4_2_pcmpistr_cconly"
+ [(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "memory" "none,load,none,load")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+@@ -10834,6 +11065,8 @@ (define_insn "sse5_pperm_zero_v16qi_v8hi
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_pperm_sign_v16qi_v8hi"
+@@ -10848,6 +11081,8 @@ (define_insn "sse5_pperm_sign_v16qi_v8hi
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_pperm_zero_v8hi_v4si"
+@@ -10862,6 +11097,8 @@ (define_insn "sse5_pperm_zero_v8hi_v4si"
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_pperm_sign_v8hi_v4si"
+@@ -10876,6 +11113,8 @@ (define_insn "sse5_pperm_sign_v8hi_v4si"
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_pperm_zero_v4si_v2di"
+@@ -10890,6 +11129,8 @@ (define_insn "sse5_pperm_zero_v4si_v2di"
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_pperm_sign_v4si_v2di"
+@@ -10904,6 +11145,8 @@ (define_insn "sse5_pperm_sign_v4si_v2di"
+ || register_operand (operands[2], V16QImode))"
+ "pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
+ [(set_attr "type" "sseadd")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ ;; SSE5 pack instructions that combine two vectors into a smaller vector
+@@ -11032,6 +11275,7 @@ (define_insn "sse5_rotl<mode>3"
+ "TARGET_SSE5"
+ "prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_rotr<mode>3"
+@@ -11045,6 +11289,7 @@ (define_insn "sse5_rotr<mode>3"
+ return \"prot<ssevecsize>\t{%3, %1, %0|%0, %1, %3}\";
+ }
+ [(set_attr "type" "sseishft")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "vrotr<mode>3"
+@@ -11084,6 +11329,8 @@ (define_insn "sse5_vrotl<mode>3"
+ "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
+ "prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ ;; SSE5 packed shift instructions.
+@@ -11137,6 +11384,8 @@ (define_insn "sse5_ashl<mode>3"
+ "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
+ "psha<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_lshl<mode>3"
+@@ -11154,6 +11403,8 @@ (define_insn "sse5_lshl<mode>3"
+ "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
+ "pshl<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sseishft")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
+ (set_attr "mode" "TI")])
+
+ ;; SSE2 doesn't have some shift varients, so define versions for SSE5
+@@ -11267,7 +11518,6 @@ (define_insn "sse5_frcz<mode>2"
+ "TARGET_SSE5"
+ "frcz<ssemodesuffixf4>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt1")
+- (set_attr "prefix_extra" "1")
+ (set_attr "mode" "<MODE>")])
+
+ ;; scalar insns
+@@ -11282,7 +11532,6 @@ (define_insn "sse5_vmfrcz<mode>2"
+ "TARGET_SSE5"
+ "frcz<ssemodesuffixf2s>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt1")
+- (set_attr "prefix_extra" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "sse5_cvtph2ps"
+@@ -11331,6 +11580,10 @@ (define_insn "*sse5_vmmaskcmp<mode>3"
+ "TARGET_SSE5"
+ "com%Y1<ssemodesuffixf2s>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sse4arg")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_rep" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<ssescalarmode>")])
+
+ ;; We don't have a comparison operator that always returns true/false, so
+@@ -11371,6 +11624,10 @@ (define_insn "sse5_com_tf<mode>3"
+ return ret;
+ }
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_rep" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "sse5_maskcmp<mode>3"
+@@ -11381,6 +11638,10 @@ (define_insn "sse5_maskcmp<mode>3"
+ "TARGET_SSE5"
+ "com%Y1<ssemodesuffixf4>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_rep" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "sse5_maskcmp<mode>3"
+@@ -11391,6 +11652,10 @@ (define_insn "sse5_maskcmp<mode>3"
+ "TARGET_SSE5"
+ "pcom%Y1<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sse4arg")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_rep" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse5_maskcmp_uns<mode>3"
+@@ -11401,6 +11666,10 @@ (define_insn "sse5_maskcmp_uns<mode>3"
+ "TARGET_SSE5"
+ "pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_rep" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ ;; Version of pcom*u* that is called from the intrinsics that allows pcomequ*
+@@ -11416,6 +11685,9 @@ (define_insn "sse5_maskcmp_uns2<mode>3"
+ "TARGET_SSE5"
+ "pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ ;; Pcomtrue and pcomfalse support. These are useless instructions, but are
+@@ -11434,6 +11706,9 @@ (define_insn "sse5_pcom_tf<mode>3"
+ : "pcomfalse<ssevecsize>\t{%2, %1, %0|%0, %1, %2}");
+ }
+ [(set_attr "type" "ssecmp")
++ (set_attr "prefix_data16" "0")
++ (set_attr "prefix_extra" "2")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*avx_aesenc"
+@@ -11444,6 +11719,7 @@ (define_insn "*avx_aesenc"
+ "TARGET_AES && TARGET_AVX"
+ "vaesenc\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -11466,6 +11742,7 @@ (define_insn "*avx_aesenclast"
+ "TARGET_AES && TARGET_AVX"
+ "vaesenclast\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -11488,6 +11765,7 @@ (define_insn "*avx_aesdec"
+ "TARGET_AES && TARGET_AVX"
+ "vaesdec\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -11510,6 +11788,7 @@ (define_insn "*avx_aesdeclast"
+ "TARGET_AES && TARGET_AVX"
+ "vaesdeclast\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -11544,6 +11823,7 @@ (define_insn "aeskeygenassist"
+ "%vaeskeygenassist\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "TI")])
+
+@@ -11556,6 +11836,8 @@ (define_insn "*vpclmulqdq"
+ "TARGET_PCLMUL && TARGET_AVX"
+ "vpclmulqdq\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "TI")])
+
+@@ -11569,6 +11851,7 @@ (define_insn "pclmulqdq"
+ "pclmulqdq\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_expand "avx_vzeroall"
+@@ -11599,6 +11882,7 @@ (define_insn "*avx_vzeroall"
+ "TARGET_AVX"
+ "vzeroall"
+ [(set_attr "type" "sse")
++ (set_attr "modrm" "0")
+ (set_attr "memory" "none")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+@@ -11617,6 +11901,7 @@ (define_insn "avx_vzeroupper"
+ "TARGET_AVX && !TARGET_64BIT"
+ "vzeroupper"
+ [(set_attr "type" "sse")
++ (set_attr "modrm" "0")
+ (set_attr "memory" "none")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+@@ -11642,6 +11927,7 @@ (define_insn "avx_vzeroupper_rex64"
+ "TARGET_AVX && TARGET_64BIT"
+ "vzeroupper"
+ [(set_attr "type" "sse")
++ (set_attr "modrm" "0")
+ (set_attr "memory" "none")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+@@ -11655,6 +11941,8 @@ (define_insn "avx_vpermil<mode>"
+ "TARGET_AVX"
+ "vpermilp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -11667,6 +11955,7 @@ (define_insn "avx_vpermilvar<mode>3"
+ "TARGET_AVX"
+ "vpermilp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -11680,6 +11969,8 @@ (define_insn "avx_vperm2f128<mode>3"
+ "TARGET_AVX"
+ "vperm2f128\t{%3, %2, %1, %0|%0, %1, %2, %3}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11695,6 +11986,7 @@ (define_insn "avx_vbroadcasts<avxmodesuf
+ "TARGET_AVX"
+ "vbroadcasts<avxmodesuffixf2c>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<avxscalarmode>")])
+
+@@ -11718,6 +12010,7 @@ (define_insn "avx_vbroadcastss256"
+ "TARGET_AVX"
+ "vbroadcastss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "SF")])
+
+@@ -11729,6 +12022,7 @@ (define_insn "avx_vbroadcastf128_p<avxmo
+ "TARGET_AVX"
+ "vbroadcastf128\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V4SF")])
+
+@@ -11765,6 +12059,8 @@ (define_insn "vec_set_lo_<mode>"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11778,6 +12074,8 @@ (define_insn "vec_set_hi_<mode>"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11792,6 +12090,8 @@ (define_insn "vec_set_lo_<mode>"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11806,6 +12106,8 @@ (define_insn "vec_set_hi_<mode>"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11822,6 +12124,8 @@ (define_insn "vec_set_lo_v16hi"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11838,6 +12142,8 @@ (define_insn "vec_set_hi_v16hi"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11858,6 +12164,8 @@ (define_insn "vec_set_lo_v32qi"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11878,6 +12186,8 @@ (define_insn "vec_set_hi_v32qi"
+ "TARGET_AVX"
+ "vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
+ [(set_attr "type" "sselog")
++ (set_attr "prefix_extra" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "V8SF")])
+
+@@ -11891,6 +12201,7 @@ (define_insn "avx_maskloadp<avxmodesuffi
+ "TARGET_AVX"
+ "vmaskmovp<avxmodesuffixf2c>\t{%1, %2, %0|%0, %2, %1}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -11904,6 +12215,7 @@ (define_insn "avx_maskstorep<avxmodesuff
+ "TARGET_AVX"
+ "vmaskmovp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog1")
++ (set_attr "prefix_extra" "1")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<MODE>")])
+
+@@ -12014,5 +12326,7 @@ (define_insn "*vec_concat<mode>_avx"
+ }
+ }
+ [(set_attr "type" "sselog,ssemov")
++ (set_attr "prefix_extra" "1,*")
++ (set_attr "length_immediate" "1,*")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "<avxvecmode>")])
+--- gcc/config/i386/i386.md.jj 2009-06-09 11:20:00.000000000 +0200
++++ gcc/config/i386/i386.md 2009-06-09 11:59:17.000000000 +0200
+@@ -295,6 +295,7 @@ (define_constants
+ (R9_REG 38)
+ (R10_REG 39)
+ (R11_REG 40)
++ (R12_REG 41)
+ (R13_REG 42)
+ (XMM8_REG 45)
+ (XMM9_REG 46)
+@@ -398,16 +399,23 @@ (define_attr "length_address" ""
+
+ ;; Set when length prefix is used.
+ (define_attr "prefix_data16" ""
+- (if_then_else (ior (eq_attr "mode" "HI")
+- (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF")))
+- (const_int 1)
+- (const_int 0)))
++ (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1")
++ (const_int 0)
++ (eq_attr "mode" "HI")
++ (const_int 1)
++ (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF,TI"))
++ (const_int 1)
++ ]
++ (const_int 0)))
+
+ ;; Set when string REP prefix is used.
+ (define_attr "prefix_rep" ""
+- (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
+- (const_int 1)
+- (const_int 0)))
++ (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1")
++ (const_int 0)
++ (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
++ (const_int 1)
++ ]
++ (const_int 0)))
+
+ ;; Set when 0f opcode prefix is used.
+ (define_attr "prefix_0f" ""
+@@ -419,8 +427,11 @@ (define_attr "prefix_0f" ""
+
+ ;; Set when REX opcode prefix is used.
+ (define_attr "prefix_rex" ""
+- (cond [(and (eq_attr "mode" "DI")
+- (eq_attr "type" "!push,pop,call,callv,leave,ibr"))
++ (cond [(ne (symbol_ref "!TARGET_64BIT") (const_int 0))
++ (const_int 0)
++ (and (eq_attr "mode" "DI")
++ (and (eq_attr "type" "!push,pop,call,callv,leave,ibr")
++ (eq_attr "unit" "!mmx")))
+ (const_int 1)
+ (and (eq_attr "mode" "QI")
+ (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)")
+@@ -429,11 +440,23 @@ (define_attr "prefix_rex" ""
+ (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)")
+ (const_int 0))
+ (const_int 1)
++ (and (eq_attr "type" "imovx")
++ (match_operand:QI 1 "ext_QIreg_operand" ""))
++ (const_int 1)
+ ]
+ (const_int 0)))
+
+-;; There are also additional prefixes in SSSE3.
+-(define_attr "prefix_extra" "" (const_int 0))
++;; There are also additional prefixes in 3DNOW, SSSE3 or SSE5.
++;; ssemuladd,sse4arg default to 0f24/0f25 and DREX byte,
++;; sseiadd1,ssecvt1 to 0f7a with no DREX byte.
++;; 3DNOW has 0f0f prefix, SSSE3 and SSE4_{1,2} 0f38/0f3a.
++(define_attr "prefix_extra" ""
++ (cond [(eq_attr "type" "ssemuladd,sse4arg")
++ (const_int 2)
++ (eq_attr "type" "sseiadd1,ssecvt1")
++ (const_int 1)
++ ]
++ (const_int 0)))
+
+ ;; Prefix used: original, VEX or maybe VEX.
+ (define_attr "prefix" "orig,vex,maybe_vex"
+@@ -441,15 +464,16 @@ (define_attr "prefix" "orig,vex,maybe_ve
+ (const_string "vex")
+ (const_string "orig")))
+
+-;; There is a 8bit immediate for VEX.
+-(define_attr "prefix_vex_imm8" "" (const_int 0))
+-
+ ;; VEX W bit is used.
+ (define_attr "prefix_vex_w" "" (const_int 0))
+
+ ;; The length of VEX prefix
++;; Only instructions with 0f prefix can have 2 byte VEX prefix,
++;; 0f38/0f3a prefixes can't. In i386.md 0f3[8a] is
++;; still prefix_0f 1, with prefix_extra 1.
+ (define_attr "length_vex" ""
+- (if_then_else (eq_attr "prefix_0f" "1")
++ (if_then_else (and (eq_attr "prefix_0f" "1")
++ (eq_attr "prefix_extra" "0"))
+ (if_then_else (eq_attr "prefix_vex_w" "1")
+ (symbol_ref "ix86_attr_length_vex_default (insn, 1, 1)")
+ (symbol_ref "ix86_attr_length_vex_default (insn, 1, 0)"))
+@@ -464,8 +488,9 @@ (define_attr "modrm" ""
+ (eq_attr "unit" "i387")
+ (const_int 0)
+ (and (eq_attr "type" "incdec")
+- (ior (match_operand:SI 1 "register_operand" "")
+- (match_operand:HI 1 "register_operand" "")))
++ (and (eq (symbol_ref "TARGET_64BIT") (const_int 0))
++ (ior (match_operand:SI 1 "register_operand" "")
++ (match_operand:HI 1 "register_operand" ""))))
+ (const_int 0)
+ (and (eq_attr "type" "push")
+ (not (match_operand 1 "memory_operand" "")))
+@@ -474,12 +499,13 @@ (define_attr "modrm" ""
+ (not (match_operand 0 "memory_operand" "")))
+ (const_int 0)
+ (and (eq_attr "type" "imov")
+- (ior (and (match_operand 0 "register_operand" "")
+- (match_operand 1 "immediate_operand" ""))
+- (ior (and (match_operand 0 "ax_reg_operand" "")
+- (match_operand 1 "memory_displacement_only_operand" ""))
+- (and (match_operand 0 "memory_displacement_only_operand" "")
+- (match_operand 1 "ax_reg_operand" "")))))
++ (and (not (eq_attr "mode" "DI"))
++ (ior (and (match_operand 0 "register_operand" "")
++ (match_operand 1 "immediate_operand" ""))
++ (ior (and (match_operand 0 "ax_reg_operand" "")
++ (match_operand 1 "memory_displacement_only_operand" ""))
++ (and (match_operand 0 "memory_displacement_only_operand" "")
++ (match_operand 1 "ax_reg_operand" ""))))))
+ (const_int 0)
+ (and (eq_attr "type" "call")
+ (match_operand 0 "constant_call_address_operand" ""))
+@@ -487,6 +513,9 @@ (define_attr "modrm" ""
+ (and (eq_attr "type" "callv")
+ (match_operand 1 "constant_call_address_operand" ""))
+ (const_int 0)
++ (and (eq_attr "type" "alu,alu1,icmp,test")
++ (match_operand 0 "ax_reg_operand" ""))
++ (symbol_ref "(get_attr_length_immediate (insn) <= (get_attr_mode (insn) != MODE_QI))")
+ ]
+ (const_int 1)))
+
+@@ -507,7 +536,7 @@ (define_attr "length" ""
+ (and (eq_attr "prefix" "maybe_vex")
+ (ne (symbol_ref "TARGET_AVX") (const_int 0))))
+ (plus (attr "length_vex")
+- (plus (attr "prefix_vex_imm8")
++ (plus (attr "length_immediate")
+ (plus (attr "modrm")
+ (attr "length_address"))))]
+ (plus (plus (attr "modrm")
+@@ -1022,6 +1051,7 @@ (define_insn "cmpqi_ext_3_insn"
+ "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
+ "cmp{b}\t{%1, %h0|%h0, %1}"
+ [(set_attr "type" "icmp")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "cmpqi_ext_3_insn_rex64"
+@@ -1036,6 +1066,7 @@ (define_insn "cmpqi_ext_3_insn_rex64"
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
+ "cmp{b}\t{%1, %h0|%h0, %1}"
+ [(set_attr "type" "icmp")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*cmpqi_ext_4"
+@@ -1308,7 +1339,7 @@ (define_insn "x86_fnstsw_1"
+ (unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
+ "TARGET_80387"
+ "fnstsw\t%0"
+- [(set_attr "length" "2")
++ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
+ (set_attr "mode" "SI")
+ (set_attr "unit" "i387")])
+
+@@ -1348,6 +1379,17 @@ (define_insn "*cmpfp_i_mixed"
+ (if_then_else (match_operand:SF 1 "" "")
+ (const_string "SF")
+ (const_string "DF")))
++ (set (attr "prefix_rep")
++ (if_then_else (eq_attr "type" "ssecomi")
++ (const_string "0")
++ (const_string "*")))
++ (set (attr "prefix_data16")
++ (cond [(eq_attr "type" "fcmp")
++ (const_string "*")
++ (eq_attr "mode" "DF")
++ (const_string "1")
++ ]
++ (const_string "0")))
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "direct")])
+
+@@ -1365,6 +1407,11 @@ (define_insn "*cmpfp_i_sse"
+ (if_then_else (match_operand:SF 1 "" "")
+ (const_string "SF")
+ (const_string "DF")))
++ (set_attr "prefix_rep" "0")
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "DF")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "direct")])
+
+@@ -1402,6 +1449,17 @@ (define_insn "*cmpfp_iu_mixed"
+ (if_then_else (match_operand:SF 1 "" "")
+ (const_string "SF")
+ (const_string "DF")))
++ (set (attr "prefix_rep")
++ (if_then_else (eq_attr "type" "ssecomi")
++ (const_string "0")
++ (const_string "*")))
++ (set (attr "prefix_data16")
++ (cond [(eq_attr "type" "fcmp")
++ (const_string "*")
++ (eq_attr "mode" "DF")
++ (const_string "1")
++ ]
++ (const_string "0")))
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "direct")])
+
+@@ -1419,6 +1477,11 @@ (define_insn "*cmpfp_iu_sse"
+ (if_then_else (match_operand:SF 1 "" "")
+ (const_string "SF")
+ (const_string "DF")))
++ (set_attr "prefix_rep" "0")
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "DF")
++ (const_string "1")
++ (const_string "0")))
+ (set_attr "athlon_decode" "vector")
+ (set_attr "amdfam10_decode" "direct")])
+
+@@ -1594,6 +1657,10 @@ (define_insn "*movsi_1"
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
+ (const_string "orig")
+ (const_string "maybe_vex")))
++ (set (attr "prefix_data16")
++ (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
++ (const_string "1")
++ (const_string "*")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "2,3")
+ (const_string "DI")
+@@ -2085,7 +2152,7 @@ (define_insn "*movdi_extzv_1"
+ "TARGET_64BIT"
+ "movz{bl|x}\t{%h1, %k0|%k0, %h1}"
+ [(set_attr "type" "imovx")
+- (set_attr "mode" "DI")])
++ (set_attr "mode" "SI")])
+
+ (define_insn "*movsi_extzv_1"
+ [(set (match_operand:SI 0 "register_operand" "=R")
+@@ -2433,8 +2500,18 @@ (define_insn "*movdi_1_rex64"
+ (const_string "lea")
+ ]
+ (const_string "imov")))
+- (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
+- (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
++ (set (attr "modrm")
++ (if_then_else
++ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
++ (const_string "0")
++ (const_string "*")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
++ (const_string "8")
++ (const_string "*")))
++ (set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
++ (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
+ (const_string "maybe_vex")
+@@ -3019,6 +3096,10 @@ (define_insn "*movdf_nointeger"
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4")
+ (const_string "orig")
+ (const_string "maybe_vex")))
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "V1DF")
++ (const_string "1")
++ (const_string "*")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "DF")
+@@ -3153,6 +3234,10 @@ (define_insn "*movdf_integer_rex64"
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4")
+ (const_string "orig")
+ (const_string "maybe_vex")))
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "V1DF")
++ (const_string "1")
++ (const_string "*")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "DF")
+@@ -3273,6 +3358,10 @@ (define_insn "*movdf_integer"
+ }
+ }
+ [(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
++ (set (attr "prefix_data16")
++ (if_then_else (eq_attr "mode" "V1DF")
++ (const_string "1")
++ (const_string "*")))
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "0,1,2")
+ (const_string "DF")
+@@ -3903,6 +3992,7 @@ (define_insn "zero_extendsidi2_rex64"
+ %vmovd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov")
+ (set_attr "prefix" "orig,*,orig,orig,maybe_vex,maybe_vex")
++ (set_attr "prefix_0f" "0,*,*,*,*,*")
+ (set_attr "mode" "SI,DI,DI,DI,TI,TI")])
+
+ (define_split
+@@ -3937,7 +4027,7 @@ (define_insn "zero_extendhidi2"
+ "TARGET_64BIT"
+ "movz{wl|x}\t{%1, %k0|%k0, %1}"
+ [(set_attr "type" "imovx")
+- (set_attr "mode" "DI")])
++ (set_attr "mode" "SI")])
+
+ (define_insn "zero_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -3945,7 +4035,7 @@ (define_insn "zero_extendqidi2"
+ "TARGET_64BIT"
+ "movz{bl|x}\t{%1, %k0|%k0, %1}"
+ [(set_attr "type" "imovx")
+- (set_attr "mode" "DI")])
++ (set_attr "mode" "SI")])
+ \f
+ ;; Sign extension instructions
+
+@@ -3977,7 +4067,7 @@ (define_insn "extendsidi2_rex64"
+ "TARGET_64BIT"
+ "@
+ {cltq|cdqe}
+- movs{lq|x}\t{%1,%0|%0, %1}"
++ movs{lq|x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "DI")
+ (set_attr "prefix_0f" "0")
+@@ -3987,7 +4077,7 @@ (define_insn "extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+ "TARGET_64BIT"
+- "movs{wq|x}\t{%1,%0|%0, %1}"
++ "movs{wq|x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "DI")])
+
+@@ -3995,7 +4085,7 @@ (define_insn "extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ "TARGET_64BIT"
+- "movs{bq|x}\t{%1,%0|%0, %1}"
++ "movs{bq|x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "DI")])
+
+@@ -4083,7 +4173,7 @@ (define_insn "extendhisi2"
+ case 0:
+ return "{cwtl|cwde}";
+ default:
+- return "movs{wl|x}\t{%1,%0|%0, %1}";
++ return "movs{wl|x}\t{%1, %0|%0, %1}";
+ }
+ }
+ [(set_attr "type" "imovx")
+@@ -4110,7 +4200,7 @@ (define_insn "*extendhisi2_zext"
+ case 0:
+ return "{cwtl|cwde}";
+ default:
+- return "movs{wl|x}\t{%1,%k0|%k0, %1}";
++ return "movs{wl|x}\t{%1, %k0|%k0, %1}";
+ }
+ }
+ [(set_attr "type" "imovx")
+@@ -4136,7 +4226,7 @@ (define_insn "extendqihi2"
+ case 0:
+ return "{cbtw|cbw}";
+ default:
+- return "movs{bw|x}\t{%1,%0|%0, %1}";
++ return "movs{bw|x}\t{%1, %0|%0, %1}";
+ }
+ }
+ [(set_attr "type" "imovx")
+@@ -4156,7 +4246,7 @@ (define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ ""
+- "movs{bl|x}\t{%1,%0|%0, %1}"
++ "movs{bl|x}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "SI")])
+
+@@ -4165,7 +4255,7 @@ (define_insn "*extendqisi2_zext"
+ (zero_extend:DI
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
+ "TARGET_64BIT"
+- "movs{bl|x}\t{%1,%k0|%k0, %1}"
++ "movs{bl|x}\t{%1, %k0|%k0, %1}"
+ [(set_attr "type" "imovx")
+ (set_attr "mode" "SI")])
+ \f
+@@ -4773,6 +4863,7 @@ (define_insn "fix_trunc<mode>di_sse"
+ "%vcvtts<ssemodefsuffix>2si{q}\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "maybe_vex")
++ (set_attr "prefix_rex" "1")
+ (set_attr "mode" "<MODE>")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "amdfam10_decode" "double,double")])
+@@ -5047,7 +5138,7 @@ (define_insn "x86_fnstcw_1"
+ (unspec:HI [(reg:HI FPCR_REG)] UNSPEC_FSTCW))]
+ "TARGET_80387"
+ "fnstcw\t%0"
+- [(set_attr "length" "2")
++ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
+ (set_attr "mode" "HI")
+ (set_attr "unit" "i387")])
+
+@@ -5056,7 +5147,7 @@ (define_insn "x86_fldcw_1"
+ (unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
+ "TARGET_80387"
+ "fldcw\t%0"
+- [(set_attr "length" "2")
++ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
+ (set_attr "mode" "HI")
+ (set_attr "unit" "i387")
+ (set_attr "athlon_decode" "vector")
+@@ -5271,6 +5362,12 @@ (define_insn "*float<SSEMODEI24:mode><MO
+ [(set_attr "type" "fmov,sseicvt,sseicvt")
+ (set_attr "prefix" "orig,maybe_vex,maybe_vex")
+ (set_attr "mode" "<MODEF:MODE>")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "prefix" "maybe_vex")
++ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "unit" "i387,*,*")
+ (set_attr "athlon_decode" "*,double,direct")
+ (set_attr "amdfam10_decode" "*,vector,double")
+@@ -5289,6 +5386,12 @@ (define_insn "*float<SSEMODEI24:mode><MO
+ [(set_attr "type" "fmov,sseicvt")
+ (set_attr "prefix" "orig,maybe_vex")
+ (set_attr "mode" "<MODEF:MODE>")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "prefix" "maybe_vex")
++ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "athlon_decode" "*,direct")
+ (set_attr "amdfam10_decode" "*,double")
+ (set_attr "fp_int_src" "true")])
+@@ -5465,6 +5568,12 @@ (define_insn "*float<SSEMODEI24:mode><MO
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODEF:MODE>")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "prefix" "maybe_vex")
++ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "athlon_decode" "double,direct")
+ (set_attr "amdfam10_decode" "vector,double")
+ (set_attr "fp_int_src" "true")])
+@@ -5494,6 +5603,12 @@ (define_insn "*float<SSEMODEI24:mode><MO
+ [(set_attr "type" "sseicvt")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "mode" "<MODEF:MODE>")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "prefix" "maybe_vex")
++ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "athlon_decode" "direct")
+ (set_attr "amdfam10_decode" "double")
+ (set_attr "fp_int_src" "true")])
+@@ -6200,6 +6315,11 @@ (define_insn "*adddi_1_rex64"
+ (const_string "incdec")
+ ]
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -6264,6 +6384,11 @@ (define_insn "*adddi_2_rex64"
+ (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*adddi_3_rex64"
+@@ -6313,6 +6438,11 @@ (define_insn "*adddi_3_rex64"
+ (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ ; For comparisons against 1, -1 and 128, we may generate better code
+@@ -6360,6 +6490,11 @@ (define_insn "*adddi_4_rex64"
+ (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*adddi_5_rex64"
+@@ -6409,6 +6544,11 @@ (define_insn "*adddi_5_rex64"
+ (if_then_else (match_operand:DI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+
+@@ -6469,6 +6609,11 @@ (define_insn "*addsi_1"
+ (const_string "incdec")
+ ]
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -6549,6 +6694,11 @@ (define_insn "addsi_1_zext"
+ (const_string "incdec")
+ ]
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -6612,6 +6762,11 @@ (define_insn "*addsi_2"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; See comment for addsi_1_zext why we do use nonimmediate_operand
+@@ -6658,6 +6813,11 @@ (define_insn "*addsi_2_zext"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "*addsi_3"
+@@ -6702,6 +6862,11 @@ (define_insn "*addsi_3"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; See comment for addsi_1_zext why we do use nonimmediate_operand
+@@ -6746,6 +6911,11 @@ (define_insn "*addsi_3_zext"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ; For comparisons against 1, -1 and 128, we may generate better code
+@@ -6791,6 +6961,11 @@ (define_insn "*addsi_4"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "*addsi_5"
+@@ -6837,6 +7012,11 @@ (define_insn "*addsi_5"
+ (if_then_else (match_operand:SI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_expand "addhi3"
+@@ -6891,6 +7071,11 @@ (define_insn "*addhi_1_lea"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu"))))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI,HI,SI")])
+
+ (define_insn "*addhi_1"
+@@ -6930,6 +7115,11 @@ (define_insn "*addhi_1"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ (define_insn "*addhi_2"
+@@ -6972,6 +7162,11 @@ (define_insn "*addhi_2"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ (define_insn "*addhi_3"
+@@ -7011,6 +7206,11 @@ (define_insn "*addhi_3"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ ; See comments above addsi_4 for details.
+@@ -7049,7 +7249,12 @@ (define_insn "*addhi_4"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
+- (set_attr "mode" "SI")])
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
++ (set_attr "mode" "HI")])
+
+
+ (define_insn "*addhi_5"
+@@ -7091,6 +7296,11 @@ (define_insn "*addhi_5"
+ (if_then_else (match_operand:HI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ (define_expand "addqi3"
+@@ -7149,6 +7359,11 @@ (define_insn "*addqi_1_lea"
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu"))))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "QI,QI,SI,SI")])
+
+ (define_insn "*addqi_1"
+@@ -7195,6 +7410,11 @@ (define_insn "*addqi_1"
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "QI,QI,SI")])
+
+ (define_insn "*addqi_1_slp"
+@@ -7430,6 +7650,7 @@ (define_insn "addqi_ext_1"
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*addqi_ext_1_rex64"
+@@ -7466,6 +7687,7 @@ (define_insn "*addqi_ext_1_rex64"
+ (if_then_else (match_operand:QI 2 "incdec_operand" "")
+ (const_string "incdec")
+ (const_string "alu")))
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*addqi_ext_2"
+@@ -8925,6 +9147,7 @@ (define_insn "*testqi_ext_0"
+ [(set_attr "type" "test")
+ (set_attr "mode" "QI")
+ (set_attr "length_immediate" "1")
++ (set_attr "modrm" "1")
+ (set_attr "pent_pair" "np")])
+
+ (define_insn "*testqi_ext_1"
+@@ -9151,9 +9374,9 @@ (define_insn "*anddi_1_rex64"
+
+ operands[1] = gen_lowpart (mode, operands[1]);
+ if (mode == QImode)
+- return "movz{bq|x}\t{%1,%0|%0, %1}";
++ return "movz{bl|x}\t{%1, %k0|%k0, %1}";
+ else
+- return "movz{wq|x}\t{%1,%0|%0, %1}";
++ return "movz{wl|x}\t{%1, %k0|%k0, %1}";
+ }
+
+ default:
+@@ -9166,7 +9389,14 @@ (define_insn "*anddi_1_rex64"
+ }
+ [(set_attr "type" "alu,alu,alu,imovx")
+ (set_attr "length_immediate" "*,*,*,0")
+- (set_attr "mode" "SI,DI,DI,DI")])
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "type" "imovx")
++ (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0))
++ (match_operand 1 "ext_QIreg_nomode_operand" "")))
++ (const_string "1")
++ (const_string "*")))
++ (set_attr "mode" "SI,DI,DI,SI")])
+
+ (define_insn "*anddi_2"
+ [(set (reg FLAGS_REG)
+@@ -9215,9 +9445,9 @@ (define_insn "*andsi_1"
+
+ operands[1] = gen_lowpart (mode, operands[1]);
+ if (mode == QImode)
+- return "movz{bl|x}\t{%1,%0|%0, %1}";
++ return "movz{bl|x}\t{%1, %0|%0, %1}";
+ else
+- return "movz{wl|x}\t{%1,%0|%0, %1}";
++ return "movz{wl|x}\t{%1, %0|%0, %1}";
+ }
+
+ default:
+@@ -9226,6 +9456,13 @@ (define_insn "*andsi_1"
+ }
+ }
+ [(set_attr "type" "alu,alu,imovx")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "type" "imovx")
++ (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0))
++ (match_operand 1 "ext_QIreg_nomode_operand" "")))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "length_immediate" "*,*,0")
+ (set_attr "mode" "SI")])
+
+@@ -9334,6 +9571,12 @@ (define_insn "*andhi_1"
+ }
+ [(set_attr "type" "alu,alu,imovx")
+ (set_attr "length_immediate" "*,*,0")
++ (set (attr "prefix_rex")
++ (if_then_else
++ (and (eq_attr "type" "imovx")
++ (match_operand 1 "ext_QIreg_nomode_operand" ""))
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "HI,HI,SI")])
+
+ (define_insn "*andhi_2"
+@@ -9453,6 +9696,7 @@ (define_insn "andqi_ext_0"
+ "and{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ ;; Generated by peephole translating test to and. This shows up
+@@ -9481,6 +9725,7 @@ (define_insn "*andqi_ext_0_cc"
+ "and{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*andqi_ext_1"
+@@ -9855,6 +10100,7 @@ (define_insn "*iorqi_ext_0"
+ "or{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*iorqi_ext_1"
+@@ -10185,6 +10431,7 @@ (define_insn "*xorqi_ext_0"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "length_immediate" "1")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*xorqi_ext_1"
+@@ -10303,6 +10550,7 @@ (define_insn "*xorqi_cc_ext_1"
+ "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_insn "*xorqi_cc_ext_1_rex64"
+@@ -10324,6 +10572,7 @@ (define_insn "*xorqi_cc_ext_1_rex64"
+ "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+ "xor{b}\t{%2, %h0|%h0, %2}"
+ [(set_attr "type" "alu")
++ (set_attr "modrm" "1")
+ (set_attr "mode" "QI")])
+
+ (define_expand "xorqi_cc_ext_1"
+@@ -11126,6 +11375,7 @@ (define_insn "*avx_ashlti3"
+ }
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix" "vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse2_ashlti3"
+@@ -11139,6 +11389,7 @@ (define_insn "sse2_ashlti3"
+ }
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*ashlti3_1"
+@@ -11278,6 +11529,15 @@ (define_insn "*ashldi3_1_rex64"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -11337,6 +11597,15 @@ (define_insn "*ashldi3_cmp_rex64"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*ashldi3_cconly_rex64"
+@@ -11379,6 +11648,15 @@ (define_insn "*ashldi3_cconly_rex64"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "*ashldi3_1"
+@@ -11518,6 +11796,15 @@ (define_insn "*ashlsi3_1"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -11602,6 +11889,15 @@ (define_insn "*ashlsi3_1_zext"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ ;; Convert lea to the lea pattern to avoid flags dependency.
+@@ -11663,6 +11959,15 @@ (define_insn "*ashlsi3_cmp"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "*ashlsi3_cconly"
+@@ -11704,6 +12009,15 @@ (define_insn "*ashlsi3_cconly"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "*ashlsi3_cmp_zext"
+@@ -11746,6 +12060,15 @@ (define_insn "*ashlsi3_cmp_zext"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_expand "ashlhi3"
+@@ -11791,6 +12114,15 @@ (define_insn "*ashlhi3_1_lea"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "HI,SI")])
+
+ (define_insn "*ashlhi3_1"
+@@ -11825,6 +12157,15 @@ (define_insn "*ashlhi3_1"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+@@ -11870,6 +12211,15 @@ (define_insn "*ashlhi3_cmp"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ (define_insn "*ashlhi3_cconly"
+@@ -11911,6 +12261,15 @@ (define_insn "*ashlhi3_cconly"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "HI")])
+
+ (define_expand "ashlqi3"
+@@ -11976,6 +12335,15 @@ (define_insn "*ashlqi3_1_lea"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "QI,SI,SI")])
+
+ (define_insn "*ashlqi3_1"
+@@ -12028,6 +12396,15 @@ (define_insn "*ashlqi3_1"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "QI,SI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+@@ -12073,6 +12450,15 @@ (define_insn "*ashlqi3_cmp"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "QI")])
+
+ (define_insn "*ashlqi3_cconly"
+@@ -12114,6 +12500,15 @@ (define_insn "*ashlqi3_cconly"
+ (const_string "alu")
+ ]
+ (const_string "ishift")))
++ (set (attr "length_immediate")
++ (if_then_else
++ (ior (eq_attr "type" "alu")
++ (and (eq_attr "type" "ishift")
++ (and (match_operand 2 "const1_operand" "")
++ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
++ (const_int 0)))))
++ (const_string "0")
++ (const_string "*")))
+ (set_attr "mode" "QI")])
+
+ ;; See comment above `ashldi3' about how this works.
+@@ -12232,10 +12627,8 @@ (define_insn "*ashrdi3_1_one_bit_rex64"
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ "sar{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*ashrdi3_1_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+@@ -12266,10 +12659,8 @@ (define_insn "*ashrdi3_one_bit_cmp_rex64
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ "sar{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*ashrdi3_one_bit_cconly_rex64"
+ [(set (reg FLAGS_REG)
+@@ -12284,7 +12675,8 @@ (define_insn "*ashrdi3_one_bit_cconly_re
+ && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+ "sar{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -12452,10 +12844,8 @@ (define_insn "*ashrsi3_1_one_bit"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*ashrsi3_1_one_bit_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -12467,7 +12857,8 @@ (define_insn "*ashrsi3_1_one_bit_zext"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%k0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*ashrsi3_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+@@ -12509,10 +12900,8 @@ (define_insn "*ashrsi3_one_bit_cmp"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*ashrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -12526,7 +12915,8 @@ (define_insn "*ashrsi3_one_bit_cconly"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*ashrsi3_one_bit_cmp_zext"
+ [(set (reg FLAGS_REG)
+@@ -12542,7 +12932,8 @@ (define_insn "*ashrsi3_one_bit_cmp_zext"
+ && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+ "sar{l}\t%k0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -12608,10 +12999,8 @@ (define_insn "*ashrhi3_1_one_bit"
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ "sar{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*ashrhi3_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+@@ -12641,10 +13030,8 @@ (define_insn "*ashrhi3_one_bit_cmp"
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ "sar{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*ashrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -12658,7 +13045,8 @@ (define_insn "*ashrhi3_one_bit_cconly"
+ && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
+ "sar{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -12708,10 +13096,8 @@ (define_insn "*ashrqi3_1_one_bit"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*ashrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+@@ -12723,10 +13109,8 @@ (define_insn "*ashrqi3_1_one_bit_slp"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift1")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*ashrqi3_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
+@@ -12769,10 +13153,8 @@ (define_insn "*ashrqi3_one_bit_cmp"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*ashrqi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -12786,7 +13168,8 @@ (define_insn "*ashrqi3_one_bit_cconly"
+ && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
+ "sar{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -12846,6 +13229,7 @@ (define_insn "*avx_lshrti3"
+ }
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix" "vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "sse2_lshrti3"
+@@ -12859,6 +13243,7 @@ (define_insn "sse2_lshrti3"
+ }
+ [(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "1")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "TI")])
+
+ (define_insn "*lshrti3_1"
+@@ -12908,10 +13293,8 @@ (define_insn "*lshrdi3_1_one_bit_rex64"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*lshrdi3_1_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+@@ -12942,10 +13325,8 @@ (define_insn "*lshrdi3_cmp_one_bit_rex64
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*lshrdi3_cconly_one_bit_rex64"
+ [(set (reg FLAGS_REG)
+@@ -12960,7 +13341,8 @@ (define_insn "*lshrdi3_cconly_one_bit_re
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{q}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -13045,10 +13427,8 @@ (define_insn "*lshrsi3_1_one_bit"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*lshrsi3_1_one_bit_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -13060,7 +13440,8 @@ (define_insn "*lshrsi3_1_one_bit_zext"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%k0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*lshrsi3_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13103,10 +13484,8 @@ (define_insn "*lshrsi3_one_bit_cmp"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*lshrsi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -13120,7 +13499,8 @@ (define_insn "*lshrsi3_one_bit_cconly"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*lshrsi3_cmp_one_bit_zext"
+ [(set (reg FLAGS_REG)
+@@ -13136,7 +13516,8 @@ (define_insn "*lshrsi3_cmp_one_bit_zext"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{l}\t%k0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -13202,10 +13583,8 @@ (define_insn "*lshrhi3_1_one_bit"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*lshrhi3_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13235,10 +13614,8 @@ (define_insn "*lshrhi3_one_bit_cmp"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*lshrhi3_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -13252,7 +13629,8 @@ (define_insn "*lshrhi3_one_bit_cconly"
+ && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+ "shr{w}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -13302,10 +13680,8 @@ (define_insn "*lshrqi3_1_one_bit"
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*lshrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+@@ -13316,10 +13692,8 @@ (define_insn "*lshrqi3_1_one_bit_slp"
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift1")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*lshrqi3_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
+@@ -13362,10 +13736,8 @@ (define_insn "*lshrqi2_one_bit_cmp"
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*lshrqi2_one_bit_cconly"
+ [(set (reg FLAGS_REG)
+@@ -13379,7 +13751,8 @@ (define_insn "*lshrqi2_one_bit_cconly"
+ && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
+ "shr{b}\t%0"
+ [(set_attr "type" "ishift")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ ;; This pattern can't accept a variable shift count, since shifts by
+ ;; zero don't affect the flags. We assume that shifts by constant
+@@ -13468,10 +13841,8 @@ (define_insn "*rotlsi3_1_one_bit_rex64"
+ && ix86_binary_operator_ok (ROTATE, DImode, operands)"
+ "rol{q}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*rotldi3_1_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13501,10 +13872,8 @@ (define_insn "*rotlsi3_1_one_bit"
+ && ix86_binary_operator_ok (ROTATE, SImode, operands)"
+ "rol{l}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*rotlsi3_1_one_bit_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -13517,7 +13886,8 @@ (define_insn "*rotlsi3_1_one_bit_zext"
+ && ix86_binary_operator_ok (ROTATE, SImode, operands)"
+ "rol{l}\t%k0"
+ [(set_attr "type" "rotate")
+- (set_attr "length" "2")])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*rotlsi3_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13560,10 +13930,8 @@ (define_insn "*rotlhi3_1_one_bit"
+ && ix86_binary_operator_ok (ROTATE, HImode, operands)"
+ "rol{w}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*rotlhi3_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13603,10 +13971,8 @@ (define_insn "*rotlqi3_1_one_bit_slp"
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
+ "rol{b}\t%0"
+ [(set_attr "type" "rotate1")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*rotlqi3_1_one_bit"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+@@ -13617,10 +13983,8 @@ (define_insn "*rotlqi3_1_one_bit"
+ && ix86_binary_operator_ok (ROTATE, QImode, operands)"
+ "rol{b}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*rotlqi3_1_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+@@ -13700,10 +14064,8 @@ (define_insn "*rotrdi3_1_one_bit_rex64"
+ && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
+ "ror{q}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand:DI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*rotrdi3_1_rex64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13733,10 +14095,8 @@ (define_insn "*rotrsi3_1_one_bit"
+ && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
+ "ror{l}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*rotrsi3_1_one_bit_zext"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -13749,10 +14109,8 @@ (define_insn "*rotrsi3_1_one_bit_zext"
+ && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
+ "ror{l}\t%k0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand:SI 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "SI")])
+
+ (define_insn "*rotrsi3_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13795,10 +14153,8 @@ (define_insn "*rotrhi3_one_bit"
+ && ix86_binary_operator_ok (ROTATERT, HImode, operands)"
+ "ror{w}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "HI")])
+
+ (define_insn "*rotrhi3_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
+@@ -13838,10 +14194,8 @@ (define_insn "*rotrqi3_1_one_bit"
+ && ix86_binary_operator_ok (ROTATERT, QImode, operands)"
+ "ror{b}\t%0"
+ [(set_attr "type" "rotate")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*rotrqi3_1_one_bit_slp"
+ [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
+@@ -13852,10 +14206,8 @@ (define_insn "*rotrqi3_1_one_bit_slp"
+ && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
+ "ror{b}\t%0"
+ [(set_attr "type" "rotate1")
+- (set (attr "length")
+- (if_then_else (match_operand 0 "register_operand" "")
+- (const_string "2")
+- (const_string "*")))])
++ (set_attr "length_immediate" "0")
++ (set_attr "mode" "QI")])
+
+ (define_insn "*rotrqi3_1"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
+@@ -13963,7 +14315,9 @@ (define_insn "*btsq"
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "bts{q}\t{%1, %0|%0, %1}"
+- [(set_attr "type" "alu1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*btrq"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
+@@ -13973,7 +14327,9 @@ (define_insn "*btrq"
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "btr{q}\t{%1, %0|%0, %1}"
+- [(set_attr "type" "alu1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*btcq"
+ [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
+@@ -13983,7 +14339,9 @@ (define_insn "*btcq"
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
+ "btc{q}\t{%1, %0|%0, %1}"
+- [(set_attr "type" "alu1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ ;; Allow Nocona to avoid these instructions if a register is available.
+
+@@ -14094,7 +14452,9 @@ (define_insn "*btdi_rex64"
+ (const_int 0)))]
+ "TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))"
+ "bt{q}\t{%1, %0|%0, %1}"
+- [(set_attr "type" "alu1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ (define_insn "*btsi"
+ [(set (reg:CCC FLAGS_REG)
+@@ -14106,7 +14466,9 @@ (define_insn "*btsi"
+ (const_int 0)))]
+ "TARGET_USE_BT || optimize_function_for_size_p (cfun)"
+ "bt{l}\t{%1, %0|%0, %1}"
+- [(set_attr "type" "alu1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "SI")])
+ \f
+ ;; Store-flag instructions.
+
+@@ -14231,6 +14593,7 @@ (define_insn "*avx_setcc<mode>"
+ "vcmp%D1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "prefix" "vex")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "*sse_setcc<mode>"
+@@ -14241,6 +14604,7 @@ (define_insn "*sse_setcc<mode>"
+ "SSE_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5"
+ "cmp%D1s<ssemodefsuffix>\t{%3, %0|%0, %3}"
+ [(set_attr "type" "ssecmp")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ (define_insn "*sse5_setcc<mode>"
+@@ -14251,6 +14615,7 @@ (define_insn "*sse5_setcc<mode>"
+ "TARGET_SSE5"
+ "com%Y1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
+ [(set_attr "type" "sse4arg")
++ (set_attr "length_immediate" "1")
+ (set_attr "mode" "<MODE>")])
+
+ \f
+@@ -15285,7 +15650,7 @@ (define_insn "return_internal_long"
+ (unspec [(const_int 0)] UNSPEC_REP)]
+ "reload_completed"
+ "rep\;ret"
+- [(set_attr "length" "1")
++ [(set_attr "length" "2")
+ (set_attr "atom_unit" "jeu")
+ (set_attr "length_immediate" "0")
+ (set_attr "prefix_rep" "1")
+@@ -15367,7 +15732,8 @@ (define_insn "set_got_rex64"
+ "TARGET_64BIT"
+ "lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}"
+ [(set_attr "type" "lea")
+- (set_attr "length" "6")])
++ (set_attr "length_address" "4")
++ (set_attr "mode" "DI")])
+
+ (define_insn "set_rip_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -15375,7 +15741,8 @@ (define_insn "set_rip_rex64"
+ "TARGET_64BIT"
+ "lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}"
+ [(set_attr "type" "lea")
+- (set_attr "length" "6")])
++ (set_attr "length_address" "4")
++ (set_attr "mode" "DI")])
+
+ (define_insn "set_got_offset_rex64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -15385,7 +15752,9 @@ (define_insn "set_got_offset_rex64"
+ "TARGET_64BIT"
+ "movabs{q}\t{$_GLOBAL_OFFSET_TABLE_-%l1, %0|%0, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_-%l1}"
+ [(set_attr "type" "imov")
+- (set_attr "length" "11")])
++ (set_attr "length_immediate" "0")
++ (set_attr "length_address" "8")
++ (set_attr "mode" "DI")])
+
+ (define_expand "epilogue"
+ [(const_int 0)]
+@@ -15508,7 +15877,9 @@ (define_insn "*ffssi_1"
+ (ctz:SI (match_dup 1)))]
+ ""
+ "bsf{l}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "SI")])
+
+ (define_expand "ffsdi2"
+ [(set (match_dup 2) (const_int -1))
+@@ -15534,7 +15905,9 @@ (define_insn "*ffsdi_1"
+ (ctz:DI (match_dup 1)))]
+ "TARGET_64BIT"
+ "bsf{q}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ (define_insn "ctzsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+@@ -15542,7 +15915,9 @@ (define_insn "ctzsi2"
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "bsf{l}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "SI")])
+
+ (define_insn "ctzdi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+@@ -15550,7 +15925,9 @@ (define_insn "ctzdi2"
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "bsf{q}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")])
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
++ (set_attr "mode" "DI")])
+
+ (define_expand "clzsi2"
+ [(parallel
+@@ -15587,7 +15964,8 @@ (define_insn "*bsr"
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "bsr{l}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "SI")])
+
+ (define_insn "popcount<mode>2"
+@@ -15771,7 +16149,8 @@ (define_insn "*bsr_rex64"
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "bsr{q}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
+
+ (define_expand "clzhi2"
+@@ -15809,7 +16188,8 @@ (define_insn "*bsrhi"
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "bsr{w}\t{%1, %0|%0, %1}"
+- [(set_attr "prefix_0f" "1")
++ [(set_attr "type" "alu1")
++ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "HI")])
+
+ (define_expand "paritydi2"
+@@ -18901,6 +19281,7 @@ (define_insn "fxam<mode>2_i387"
+ "TARGET_USE_FANCY_MATH_387"
+ "fxam\n\tfnstsw\t%0"
+ [(set_attr "type" "multi")
++ (set_attr "length" "4")
+ (set_attr "unit" "i387")
+ (set_attr "mode" "<MODE>")])
+
+@@ -19190,6 +19571,7 @@ (define_insn "*strmovqi_rex_1"
+ "movsb"
+ [(set_attr "type" "str")
+ (set_attr "memory" "both")
++ (set_attr "prefix_rex" "0")
+ (set_attr "mode" "QI")])
+
+ (define_expand "rep_mov"
+@@ -19446,6 +19828,7 @@ (define_insn "*strsetqi_rex_1"
+ "stosb"
+ [(set_attr "type" "str")
+ (set_attr "memory" "store")
++ (set_attr "prefix_rex" "0")
+ (set_attr "mode" "QI")])
+
+ (define_expand "rep_stos"
+@@ -19539,6 +19922,7 @@ (define_insn "*rep_stosqi_rex64"
+ [(set_attr "type" "str")
+ (set_attr "prefix_rep" "1")
+ (set_attr "memory" "store")
++ (set_attr "prefix_rex" "0")
+ (set_attr "mode" "QI")])
+
+ (define_expand "cmpstrnsi"
+@@ -19665,6 +20049,7 @@ (define_insn "*cmpstrnqi_nz_rex_1"
+ "repz cmpsb"
+ [(set_attr "type" "str")
+ (set_attr "mode" "QI")
++ (set_attr "prefix_rex" "0")
+ (set_attr "prefix_rep" "1")])
+
+ ;; The same, but the count is not known to not be zero.
+@@ -19718,6 +20103,7 @@ (define_insn "*cmpstrnqi_rex_1"
+ "repz cmpsb"
+ [(set_attr "type" "str")
+ (set_attr "mode" "QI")
++ (set_attr "prefix_rex" "0")
+ (set_attr "prefix_rep" "1")])
+
+ (define_expand "strlensi"
+@@ -19779,6 +20165,7 @@ (define_insn "*strlenqi_rex_1"
+ "repnz scasb"
+ [(set_attr "type" "str")
+ (set_attr "mode" "QI")
++ (set_attr "prefix_rex" "0")
+ (set_attr "prefix_rep" "1")])
+
+ ;; Peephole optimizations to clean up after cmpstrn*. This should be
+@@ -20299,6 +20686,14 @@ (define_insn "pro_epilogue_adjust_stack_
+ (const_string "imov")
+ ]
+ (const_string "lea")))
++ (set (attr "length_immediate")
++ (cond [(eq_attr "type" "imov")
++ (const_string "0")
++ (and (eq_attr "type" "alu")
++ (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ ]
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "pro_epilogue_adjust_stack_rex64"
+@@ -20343,6 +20738,14 @@ (define_insn "pro_epilogue_adjust_stack_
+ (const_string "imov")
+ ]
+ (const_string "lea")))
++ (set (attr "length_immediate")
++ (cond [(eq_attr "type" "imov")
++ (const_string "0")
++ (and (eq_attr "type" "alu")
++ (match_operand 2 "const128_operand" ""))
++ (const_string "1")
++ ]
++ (const_string "*")))
+ (set_attr "mode" "DI")])
+
+ (define_insn "pro_epilogue_adjust_stack_rex64_2"
+@@ -21830,6 +22233,7 @@ (define_insn "*prefetch_sse"
+ }
+ [(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "prefetch")
++ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set_attr "memory" "none")])
+
+ (define_insn "*prefetch_sse_rex"
+@@ -21849,6 +22253,7 @@ (define_insn "*prefetch_sse_rex"
+ }
+ [(set_attr "type" "sse")
+ (set_attr "atom_sse_attr" "prefetch")
++ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set_attr "memory" "none")])
+
+ (define_insn "*prefetch_3dnow"
+@@ -21863,6 +22268,7 @@ (define_insn "*prefetch_3dnow"
+ return "prefetchw\t%a0";
+ }
+ [(set_attr "type" "mmx")
++ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set_attr "memory" "none")])
+
+ (define_insn "*prefetch_3dnow_rex"
+@@ -21877,6 +22283,7 @@ (define_insn "*prefetch_3dnow_rex"
+ return "prefetchw\t%a0";
+ }
+ [(set_attr "type" "mmx")
++ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
+ (set_attr "memory" "none")])
+
+ (define_expand "stack_protect_set"
+@@ -22035,6 +22442,14 @@ (define_insn "sse4_2_crc32<mode>"
+ [(set_attr "type" "sselog1")
+ (set_attr "prefix_rep" "1")
+ (set_attr "prefix_extra" "1")
++ (set (attr "prefix_data16")
++ (if_then_else (match_operand:HI 2 "" "")
++ (const_string "1")
++ (const_string "*")))
++ (set (attr "prefix_rex")
++ (if_then_else (match_operand:QI 2 "ext_QIreg_operand" "")
++ (const_string "1")
++ (const_string "*")))
+ (set_attr "mode" "SI")])
+
+ (define_insn "sse4_2_crc32di"
+--- gcc/output.h.jj 2009-01-14 12:06:29.000000000 +0100
++++ gcc/output.h 2009-06-09 10:46:09.000000000 +0200
+@@ -1,7 +1,7 @@
+ /* Declarations for insn-output.c. These functions are defined in recog.c,
+ final.c, and varasm.c.
+ Copyright (C) 1987, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
+- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
++ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+@@ -94,6 +94,10 @@ extern int insn_current_reference_addres
+ Defined in final.c. */
+ extern int label_to_alignment (rtx);
+
++/* Find the alignment maximum skip associated with a CODE_LABEL.
++ Defined in final.c. */
++extern int label_to_max_skip (rtx);
++
+ /* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
+ extern void output_asm_label (rtx);
+
diff --git a/gcc44-pr39856.patch b/gcc44-pr39856.patch
deleted file mode 100644
index 5bc88fe..0000000
--- a/gcc44-pr39856.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-2009-04-24 Vladimir Makarov <vmakarov@redhat.com>
-
- PR target/39856
- * reg-stack.c (subst_stack_regs_pat): Remove gcc_assert for note
- for clobber.
-
---- gcc/reg-stack.c (revision 146648)
-+++ gcc/reg-stack.c (working copy)
-@@ -1371,21 +1371,23 @@ subst_stack_regs_pat (rtx insn, stack re
-
- if (pat != PATTERN (insn))
- {
-- /* The fix_truncdi_1 pattern wants to be able to allocate
-- its own scratch register. It does this by clobbering
-- an fp reg so that it is assured of an empty reg-stack
-- register. If the register is live, kill it now.
-- Remove the DEAD/UNUSED note so we don't try to kill it
-- later too. */
-+ /* The fix_truncdi_1 pattern wants to be able to
-+ allocate its own scratch register. It does this by
-+ clobbering an fp reg so that it is assured of an
-+ empty reg-stack register. If the register is live,
-+ kill it now. Remove the DEAD/UNUSED note so we
-+ don't try to kill it later too.
-+
-+ In reality the UNUSED note can be absent in some
-+ complicated cases when the register is reused for
-+ partially set variable. */
-
- if (note)
- emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
- else
-- {
-- note = find_reg_note (insn, REG_UNUSED, *dest);
-- gcc_assert (note);
-- }
-- remove_note (insn, note);
-+ note = find_reg_note (insn, REG_UNUSED, *dest);
-+ if (note)
-+ remove_note (insn, note);
- replace_reg (dest, FIRST_STACK_REG + 1);
- }
- else
diff --git a/gcc44-pr39942.patch b/gcc44-pr39942.patch
deleted file mode 100644
index eb77eb6..0000000
--- a/gcc44-pr39942.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-2009-05-05 Jakub Jelinek <jakub@redhat.com>
-
- PR target/39942
- * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Don't emit second
- .p2align 3 if MAX_SKIP is smaller than 7.
- * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
-
---- gcc/config/i386/x86-64.h.jj 2009-05-05 08:33:20.000000000 +0200
-+++ gcc/config/i386/x86-64.h 2009-05-05 16:37:13.000000000 +0200
-@@ -74,7 +74,9 @@ see the files COPYING3 and COPYING.RUNTI
- fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
- /* Make sure that we have at least 8 byte alignment if > 8 byte \
- alignment is preferred. */ \
-- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
-+ if ((LOG) > 3 \
-+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
-+ && (MAX_SKIP) >= 7) \
- fprintf ((FILE), "\t.p2align 3\n"); \
- } \
- } \
---- gcc/config/i386/linux.h.jj 2009-05-05 08:33:20.000000000 +0200
-+++ gcc/config/i386/linux.h 2009-05-05 16:37:13.000000000 +0200
-@@ -153,7 +153,9 @@ along with GCC; see the file COPYING3.
- fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
- /* Make sure that we have at least 8 byte alignment if > 8 byte \
- alignment is preferred. */ \
-- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
-+ if ((LOG) > 3 \
-+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
-+ && (MAX_SKIP) >= 7) \
- fprintf ((FILE), "\t.p2align 3\n"); \
- } \
- } \
diff --git a/gcc44-unwind-debug-hook.patch b/gcc44-unwind-debug-hook.patch
new file mode 100644
index 0000000..e084be5
--- /dev/null
+++ b/gcc44-unwind-debug-hook.patch
@@ -0,0 +1,46 @@
+2009-05-27 Tom Tromey <tromey@redhat.com>
+
+ * unwind-dw2.c (_Unwind_DebugHook): New function.
+ (uw_install_context): Call _Unwind_DebugHook.
+
+--- gcc/unwind-dw2.c (revision 147933)
++++ gcc/unwind-dw2.c (revision 147934)
+@@ -1473,18 +1473,31 @@ uw_init_context_1 (struct _Unwind_Contex
+ context->ra = __builtin_extract_return_addr (outer_ra);
+ }
+
++static void _Unwind_DebugHook (void *, void *) __attribute__ ((__noinline__));
++
++/* This function is called during unwinding. It is intended as a hook
++ for a debugger to intercept exceptions. CFA is the CFA of the
++ target frame. HANDLER is the PC to which control will be
++ transferred. */
++static void
++_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
++ void *handler __attribute__ ((__unused__)))
++{
++ asm ("");
++}
+
+ /* Install TARGET into CURRENT so that we can return to it. This is a
+ macro because __builtin_eh_return must be invoked in the context of
+ our caller. */
+
+-#define uw_install_context(CURRENT, TARGET) \
+- do \
+- { \
+- long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
+- void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
+- __builtin_eh_return (offset, handler); \
+- } \
++#define uw_install_context(CURRENT, TARGET) \
++ do \
++ { \
++ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
++ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
++ _Unwind_DebugHook ((TARGET)->cfa, handler); \
++ __builtin_eh_return (offset, handler); \
++ } \
+ while (0)
+
+ static long
diff --git a/sources b/sources
index 5d45dc9..e0a400b 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
2659f09c2e43ef8b7d4406321753f1b2 fastjar-0.97.tar.gz
-271340a1883a595c5c8b4fe1007389fa gcc-4.4.0-20090514.tar.bz2
+aa85080477b7f1f5b6c526d2ad48bbf7 gcc-4.4.0-20090609.tar.bz2
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [rpms/gcc] rhel-f41-base: 4.4.0-7
@ 2026-06-29 12:24 Jakub Jelinek
0 siblings, 0 replies; 2+ messages in thread
From: Jakub Jelinek @ 2026-06-29 12:24 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/gcc
Branch : rhel-f41-base
Commit : eddb3f2c3a6469dac43f7466879fe4043e7ea457
Author : Jakub Jelinek <jakub@fedoraproject.org>
Date : 2009-06-09T16:09:51+00:00
Stats : +97/-20 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/gcc/c/eddb3f2c3a6469dac43f7466879fe4043e7ea457?branch=rhel-f41-base
Log:
4.4.0-7
---
diff --git a/gcc44-ix86-insn-length.patch b/gcc44-ix86-insn-length.patch
index 487f684..56490c8 100644
--- a/gcc44-ix86-insn-length.patch
+++ b/gcc44-ix86-insn-length.patch
@@ -359,6 +359,49 @@
}
#ifdef HAVE_ATTR_length
+--- gcc/config/i386/i386.h.jj 2009-06-09 17:54:57.000000000 +0200
++++ gcc/config/i386/i386.h 2009-06-09 11:20:00.000000000 +0200
+@@ -2209,6 +2210,22 @@ do { \
+ #define ASM_OUTPUT_OPCODE(STREAM, PTR) \
+ ASM_OUTPUT_AVX_PREFIX ((STREAM), (PTR))
+
++/* A C statement to output to the stdio stream FILE an assembler
++ command to pad the location counter to a multiple of 1<<LOG
++ bytes if it is within MAX_SKIP bytes. */
++
++#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
++#undef ASM_OUTPUT_MAX_SKIP_PAD
++#define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP) \
++ if ((LOG) != 0) \
++ { \
++ if ((MAX_SKIP) == 0) \
++ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
++ else \
++ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
++ }
++#endif
++
+ /* Under some conditions we need jump tables in the text section,
+ because the assembler cannot handle label differences between
+ sections. This is the case for x86_64 on Mach-O for example. */
+--- gcc/config/i386/x86-64.h (revision 147670)
++++ gcc/config/i386/x86-64.h (revision 147671)
+@@ -81,6 +81,15 @@ see the files COPYING3 and COPYING.RUNTI
+ } \
+ } \
+ } while (0)
++#undef ASM_OUTPUT_MAX_SKIP_PAD
++#define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP) \
++ if ((LOG) != 0) \
++ { \
++ if ((MAX_SKIP) == 0) \
++ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
++ else \
++ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
++ }
+ #endif
+
+
--- gcc/config/i386/i386.c.jj 2009-06-09 10:24:35.000000000 +0200
+++ gcc/config/i386/i386.c 2009-06-09 12:10:01.000000000 +0200
@@ -8884,6 +8884,10 @@ ix86_decompose_address (rtx addr, struct
@@ -4611,6 +4654,27 @@
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "prefix_rep" "1")
+@@ -15317,16 +15682,16 @@ (define_insn "nop"
+ (set_attr "length_immediate" "0")
+ (set_attr "modrm" "0")])
+
+-;; Align to 16-byte boundary, max skip in op0. Used to avoid
++;; Pad to 16-byte boundary, max skip in op0. Used to avoid
+ ;; branch prediction penalty for the third jump in a 16-byte
+ ;; block on K8.
+
+-(define_insn "align"
++(define_insn "pad"
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
+ ""
+ {
+-#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
+- ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
++#ifdef ASM_OUTPUT_MAX_SKIP_PAD
++ ASM_OUTPUT_MAX_SKIP_PAD (asm_out_file, 4, (int)INTVAL (operands[0]));
+ #else
+ /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
+ The align insn is used to avoid 3 jump instructions in the row to improve
@@ -15367,7 +15732,8 @@ (define_insn "set_got_rex64"
"TARGET_64BIT"
"lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}"
diff --git a/gcc44-power7.patch b/gcc44-power7.patch
index e4078de..2f00006 100644
--- a/gcc44-power7.patch
+++ b/gcc44-power7.patch
@@ -3434,7 +3434,7 @@
+ "du2_power7,VSU_power7")
--- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 145777)
+++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 146027)
-@@ -105,11 +105,14 @@ altivec_categorize_keyword (const cpp_to
+@@ -106,14 +106,17 @@ altivec_categorize_keyword (const cpp_to
if (ident == C_CPP_HASHNODE (vector_keyword))
return C_CPP_HASHNODE (__vector_keyword);
@@ -3449,11 +3449,16 @@
- return C_CPP_HASHNODE (__bool_keyword);
+ if (ident == C_CPP_HASHNODE (bool_keyword))
+ return C_CPP_HASHNODE (__bool_keyword);
+
+- if (ident == C_CPP_HASHNODE (_Bool_keyword))
+- return C_CPP_HASHNODE (__bool_keyword);
++ if (ident == C_CPP_HASHNODE (_Bool_keyword))
++ return C_CPP_HASHNODE (__bool_keyword);
+ }
return ident;
}
-@@ -127,20 +130,23 @@ init_vector_keywords (void)
+@@ -131,23 +134,26 @@ init_vector_keywords (void)
__vector_keyword = get_identifier ("__vector");
C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
@@ -3475,19 +3480,24 @@
+
+ __bool_keyword = get_identifier ("__bool");
+ C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
-+
-+ pixel_keyword = get_identifier ("pixel");
-+ C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL;
- bool_keyword = get_identifier ("bool");
- C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
++ pixel_keyword = get_identifier ("pixel");
++ C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL;
+
+- _Bool_keyword = get_identifier ("_Bool");
+- C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
+ bool_keyword = get_identifier ("bool");
+ C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
++
++ _Bool_keyword = get_identifier ("_Bool");
++ C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
+ }
}
/* Called to decide whether a conditional macro should be expanded.
-@@ -207,7 +213,8 @@ rs6000_macro_to_expand (cpp_reader *pfil
+@@ -214,7 +220,8 @@ rs6000_macro_to_expand (cpp_reader *pfil
if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
|| rid_code == RID_SHORT || rid_code == RID_SIGNED
|| rid_code == RID_INT || rid_code == RID_CHAR
@@ -3497,7 +3507,7 @@
{
expand_this = C_CPP_HASHNODE (__vector_keyword);
/* If the next keyword is bool or pixel, it
-@@ -277,13 +284,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+@@ -284,13 +291,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
builtin_define ("_ARCH_PWR6X");
if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
builtin_define ("_ARCH_COM");
@@ -3513,13 +3523,16 @@
builtin_define ("__pixel=__attribute__((altivec(pixel__))) unsigned short");
builtin_define ("__bool=__attribute__((altivec(bool__))) unsigned");
-@@ -292,9 +300,18 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+@@ -298,11 +306,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ {
/* Define this when supporting context-sensitive keywords. */
builtin_define ("__APPLE_ALTIVEC__");
-
+-
- builtin_define ("vector=vector");
++
builtin_define ("pixel=pixel");
builtin_define ("bool=bool");
+ builtin_define ("_Bool=_Bool");
+ }
+ }
+ if (TARGET_ALTIVEC || TARGET_VSX)
@@ -3533,7 +3546,7 @@
init_vector_keywords ();
/* Enable context-sensitive macros. */
-@@ -318,6 +335,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+@@ -326,6 +343,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
/* Used by libstdc++. */
if (TARGET_NO_LWSYNC)
builtin_define ("__NO_LWSYNC__");
@@ -3542,7 +3555,7 @@
/* May be overridden by target configuration. */
RS6000_CPU_CPP_ENDIAN_BUILTINS();
-@@ -496,6 +515,8 @@ const struct altivec_builtin_types altiv
+@@ -504,6 +523,8 @@ const struct altivec_builtin_types altiv
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
@@ -3551,7 +3564,7 @@
{ ALTIVEC_BUILTIN_VEC_VADDFP, ALTIVEC_BUILTIN_VADDFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
-@@ -639,6 +660,12 @@ const struct altivec_builtin_types altiv
+@@ -647,6 +668,12 @@ const struct altivec_builtin_types altiv
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
@@ -3564,7 +3577,7 @@
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
-@@ -687,6 +714,12 @@ const struct altivec_builtin_types altiv
+@@ -695,6 +722,12 @@ const struct altivec_builtin_types altiv
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
@@ -3577,7 +3590,7 @@
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
-@@ -1190,6 +1223,8 @@ const struct altivec_builtin_types altiv
+@@ -1198,6 +1231,8 @@ const struct altivec_builtin_types altiv
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
@@ -3586,7 +3599,7 @@
{ ALTIVEC_BUILTIN_VEC_VMAXFP, ALTIVEC_BUILTIN_VMAXFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
-@@ -1366,6 +1401,8 @@ const struct altivec_builtin_types altiv
+@@ -1374,6 +1409,8 @@ const struct altivec_builtin_types altiv
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
@@ -3595,7 +3608,7 @@
{ ALTIVEC_BUILTIN_VEC_VMINFP, ALTIVEC_BUILTIN_VMINFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
-@@ -1451,6 +1488,8 @@ const struct altivec_builtin_types altiv
+@@ -1459,6 +1496,8 @@ const struct altivec_builtin_types altiv
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
@@ -3604,7 +3617,7 @@
RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
-@@ -1475,6 +1514,12 @@ const struct altivec_builtin_types altiv
+@@ -1483,6 +1522,12 @@ const struct altivec_builtin_types altiv
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
@@ -3617,7 +3630,7 @@
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
-@@ -1932,6 +1977,8 @@ const struct altivec_builtin_types altiv
+@@ -1940,6 +1985,8 @@ const struct altivec_builtin_types altiv
RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
@@ -3626,7 +3639,7 @@
{ ALTIVEC_BUILTIN_VEC_VSUBFP, ALTIVEC_BUILTIN_VSUBFP,
RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
-@@ -2091,6 +2138,12 @@ const struct altivec_builtin_types altiv
+@@ -2099,6 +2146,12 @@ const struct altivec_builtin_types altiv
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
@@ -3639,7 +3652,7 @@
RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
{ ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
-@@ -2981,8 +3034,10 @@ altivec_resolve_overloaded_builtin (tree
+@@ -2989,8 +3042,10 @@ altivec_resolve_overloaded_builtin (tree
const struct altivec_builtin_types *desc;
int n;
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-29 12:24 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-29 12:24 [rpms/gcc] rhel-f41-base: 4.4.0-7 Jakub Jelinek
2026-06-29 12:24 Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox