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 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 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 + + * 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 + Uros Bizjak + + * 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 + + * 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 + + * 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 + + * jump.c (returnjump_p): Handle delayed branches. Add missing + function comment. + +2009-06-05 Nathan Froyd + + * config/rs6000/ppc-asm.h: Protect auto-host.h inclusion and + CFI_* definitions with IN_GCC. + +2009-06-04 Jakub Jelinek + + * 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 + + * 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 + + * 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 + + 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 + + * 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_, + 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_" +- [(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 + + #define FASTCALL_PREFIX '@' + ++/* 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; + + /* 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; + } + +-/* 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 + + * 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_truncdi_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, *sse_setcc, *sse5_setcc): 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. + (fxam2_i387): Set length attribute to 4. + (*prefetch_sse, *prefetch_sse_rex, *prefetch_3dnow, + *prefetch_3dnow_rex): Override length_address attribute. + (sse4_2_crc32): 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 (_comi, _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_ashr3, ashr3, *avx_lshr3, lshr3, + *avx_ashl3, ashl3): Set length_immediate attribute to 1 + iff operand 2 is const_int_operand. + (*vec_dupv4si, avx_shufpd256_1, *avx_shufpd_, + sse2_shufpd_): 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_cmpp3, + avx_cmps3, *avx_maskcmp3, + _maskcmp3, _vmmaskcmp3, + avx_shufps256_1, *avx_shufps_, sse_shufps_, + *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_, + vec_extract_hi_, 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_3, *avx_eq3, *avx_gt3): Set + prefix_extra attribute for variants that don't have 0f prefix + alone. + (*avx_pinsr): 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_psign3): 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_psign3): 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. + (abs2): 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, + avx_blendvp, + avx_dpp, *avx_mpsadbw, + *avx_pblendvb, *avx_pblendw, avx_roundp256, + avx_rounds256): Override prefix_extra + and length_immediate to 1. + (sse4_1_blendp, sse4_1_dpp, + 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): Override prefix_data16 to 1. + (sse4_1_mpsadbw, sse4_1_pblendw): Override length_immediate to 1. + (*avx_packusdw, avx_vtestp, + avx_ptest256): Override prefix_extra to 1. + (sse4_1_roundp, sse4_1_rounds): + 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_vrotl3, sse5_ashl3, sse5_lshl3): Override + prefix_data16 to 0 and prefix_extra to 2. + (sse5_rotl3, sse5_rotr3): Override length_immediate to 1. + (sse5_frcz2, sse5_vmfrcz2): Don't override prefix_extra + attribute. + (*sse5_vmmaskcmp3, sse5_com_tf3, + sse5_maskcmp3, sse5_maskcmp3, sse5_maskcmp_uns3): + Override prefix_data16 and prefix_rep to 0, length_immediate to 1 + and prefix_extra to 2. + (sse5_maskcmp_uns23, sse5_pcom_tf3): Override + prefix_data16 to 0, length_immediate to 1 and prefix_extra to 2. + (*avx_aesenc, *avx_aesenclast, *avx_aesdec, *avx_aesdeclast, + avx_vpermilvar3, + avx_vbroadcasts, + avx_vbroadcastss256, avx_vbroadcastf128_p256, + avx_maskloadp, + avx_maskstorep): + Override prefix_extra to 1. + (aeskeygenassist, pclmulqdq): Override length_immediate to 1. + (*vpclmulqdq, avx_vpermil, avx_vperm2f1283, + vec_set_lo_, vec_set_hi_, 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_avx): Override prefix_extra and length_immediate + to 1 for the first alternative. + * config/i386/mmx.md (*mov_internal_rex64): Override + prefix_rep, prefix_data16 and/or prefix_rex attributes in certain + cases. + (*mov_internal_avx, *movv2sf_internal_rex64, + *movv2sf_internal_avx, *movv2sf_internal): Override + prefix_rep attribute for certain alternatives. + (*mov_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_v2sf3_finite, *mmx_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_ashr3, mmx_lshr3, mmx_ashl3): 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 + + * 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. + (*float2_mixed_interunit, + *float2_mixed_nointerunit, + *float2_sse_interunit, + *float2_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 + + * 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 + + 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 + + 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 + + * 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_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_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_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_v2sf3_finite" + && ix86_binary_operator_ok (, V2SFmode, operands)" + "pf\t{%2, %0|%0, %2}" + [(set_attr "type" "mmxadd") ++ (set_attr "prefix_extra" "1") + (set_attr "mode" "V2SF")]) + + (define_insn "*mmx_v2sf3" +@@ -391,6 +409,7 @@ (define_insn "*mmx_v2sf3" + "TARGET_3DNOW" + "pf\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_ashr3" + "TARGET_MMX" + "psra\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_lshr3" +@@ -975,6 +1015,10 @@ (define_insn "mmx_lshr3" + "TARGET_MMX" + "psrl\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_ashl3" +@@ -985,6 +1029,10 @@ (define_insn "mmx_ashl3" + "TARGET_MMX" + "psll\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" +@@ -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 + "TARGET_AVX" + "vcmpp\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" "")]) + +@@ -1425,6 +1428,7 @@ (define_insn "avx_cmps + "TARGET_AVX" + "vcmps\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" "")]) + +@@ -1439,6 +1443,7 @@ (define_insn "*avx_maskcmp3" + "vcmp%D3p\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "ssecmp") + (set_attr "prefix" "vex") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + (define_insn "_maskcmp3" +@@ -1450,6 +1455,7 @@ (define_insn "_maskcmp3" + && !TARGET_SSE5" + "cmp%D3\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecmp") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + (define_insn "_vmmaskcmp3" +@@ -1463,6 +1469,7 @@ (define_insn "_vmmaskcmp3" + "SSE_VEC_FLOAT_MODE_P (mode) && !TARGET_SSE5" + "cmp%D3s\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecmp") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + (define_insn "_comi" +@@ -1478,6 +1485,11 @@ (define_insn "_comi" + "%vcomis\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" "")]) + + (define_insn "_ucomi" +@@ -1493,6 +1505,11 @@ (define_insn "_ucomi" + "%vucomis\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" "")]) + + (define_expand "vcond" +@@ -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_" + 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_" + 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_" + "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_" + "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_" + "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_" + "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_" + 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_" + 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_ashr3" + "vpsra\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 "ashr3" +@@ -5505,6 +5587,10 @@ (define_insn "ashr3" + "psra\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_lshr3" +@@ -5516,6 +5602,10 @@ (define_insn "*avx_lshr3" + "vpsrl\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 "lshr3" +@@ -5527,6 +5617,10 @@ (define_insn "lshr3" + "psrl\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_ashl3" +@@ -5538,6 +5632,10 @@ (define_insn "*avx_ashl3" + "vpsll\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 "ashl3" +@@ -5549,6 +5647,10 @@ (define_insn "ashl3" + "psll\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_" +@@ -5579,6 +5681,12 @@ (define_insn "*avx_3" + "TARGET_AVX && ix86_binary_operator_ok (, mode, operands)" + "vp\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sseiadd") ++ (set (attr "prefix_extra") ++ (if_then_else ++ (ne (symbol_ref "mode != (( == SMAX || == 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_eq3" + "TARGET_AVX && ix86_binary_operator_ok (EQ, mode, operands)" + "vpcmpeq\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_gt3" + "TARGET_AVX" + "vpcmpgt\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" +@@ -6605,6 +6722,11 @@ (define_insn "*avx_pinsr + return "vpinsr\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_psign3" +@@ -8735,6 +8915,7 @@ (define_insn "*avx_psign3" + "TARGET_AVX" + "vpsign\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_psign3" + "psign\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 "abs2" +@@ -8828,7 +9015,9 @@ (define_insn "abs2" + "TARGET_SSSE3" + "pabs\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\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" "")]) + +@@ -8934,6 +9129,8 @@ (define_insn "avx_blendvp\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" "")]) + +@@ -8946,7 +9143,9 @@ (define_insn "sse4_1_blendp\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" "")]) + + (define_insn "sse4_1_blendvp" +@@ -8959,6 +9158,7 @@ (define_insn "sse4_1_blendvp\t{%3, %2, %0|%0, %2, %3}" + [(set_attr "type" "ssemov") ++ (set_attr "prefix_data16" "1") + (set_attr "prefix_extra" "1") + (set_attr "mode" "")]) + +@@ -8973,6 +9173,8 @@ (define_insn "avx_dpp< + "vdpp\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" "")]) + + (define_insn "sse4_1_dpp" +@@ -8985,7 +9187,9 @@ (define_insn "sse4_1_dpp\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" "")]) + + (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\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecomi") ++ (set_attr "prefix_extra" "1") + (set_attr "prefix" "vex") + (set_attr "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\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" "")]) + +@@ -9555,7 +9772,9 @@ (define_insn "sse4_1_roundp\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" "")]) + +@@ -9571,6 +9790,8 @@ (define_insn "*avx_rounds\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" "")]) + +@@ -9586,7 +9807,9 @@ (define_insn "sse4_1_rounds\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" "")]) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +@@ -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_rotl3" + "TARGET_SSE5" + "prot\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sseishft") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "TI")]) + + (define_insn "sse5_rotr3" +@@ -11045,6 +11289,7 @@ (define_insn "sse5_rotr3" + return \"prot\t{%3, %1, %0|%0, %1, %3}\"; + } + [(set_attr "type" "sseishft") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "TI")]) + + (define_expand "vrotr3" +@@ -11084,6 +11329,8 @@ (define_insn "sse5_vrotl3" + "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)" + "prot\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_ashl3" + "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)" + "psha\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_lshl3" +@@ -11154,6 +11403,8 @@ (define_insn "sse5_lshl3" + "TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)" + "pshl\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_frcz2" + "TARGET_SSE5" + "frcz\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt1") +- (set_attr "prefix_extra" "1") + (set_attr "mode" "")]) + + ;; scalar insns +@@ -11282,7 +11532,6 @@ (define_insn "sse5_vmfrcz2" + "TARGET_SSE5" + "frcz\t{%2, %0|%0, %2}" + [(set_attr "type" "ssecvt1") +- (set_attr "prefix_extra" "1") + (set_attr "mode" "")]) + + (define_insn "sse5_cvtph2ps" +@@ -11331,6 +11580,10 @@ (define_insn "*sse5_vmmaskcmp3" + "TARGET_SSE5" + "com%Y1\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" "")]) + + ;; We don't have a comparison operator that always returns true/false, so +@@ -11371,6 +11624,10 @@ (define_insn "sse5_com_tf3" + 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" "")]) + + (define_insn "sse5_maskcmp3" +@@ -11381,6 +11638,10 @@ (define_insn "sse5_maskcmp3" + "TARGET_SSE5" + "com%Y1\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" "")]) + + (define_insn "sse5_maskcmp3" +@@ -11391,6 +11652,10 @@ (define_insn "sse5_maskcmp3" + "TARGET_SSE5" + "pcom%Y1\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_uns3" +@@ -11401,6 +11666,10 @@ (define_insn "sse5_maskcmp_uns3" + "TARGET_SSE5" + "pcom%Y1u\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_uns23" + "TARGET_SSE5" + "pcom%Y1u\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_tf3" + : "pcomfalse\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" + "TARGET_AVX" + "vpermilp\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" "")]) + +@@ -11667,6 +11955,7 @@ (define_insn "avx_vpermilvar3" + "TARGET_AVX" + "vpermilp\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") ++ (set_attr "prefix_extra" "1") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) + +@@ -11680,6 +11969,8 @@ (define_insn "avx_vperm2f1283" + "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\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") ++ (set_attr "prefix_extra" "1") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) + +@@ -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" + "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_" + "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_" + "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_" + "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\t{%1, %2, %0|%0, %2, %1}" + [(set_attr "type" "sselog1") ++ (set_attr "prefix_extra" "1") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) + +@@ -11904,6 +12215,7 @@ (define_insn "avx_maskstorep\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog1") ++ (set_attr "prefix_extra" "1") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) + +@@ -12014,5 +12326,7 @@ (define_insn "*vec_concat_avx" + } + } + [(set_attr "type" "sselog,ssemov") ++ (set_attr "prefix_extra" "1,*") ++ (set_attr "length_immediate" "1,*") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) +--- 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")]) + + ;; 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")]) + +@@ -4773,6 +4863,7 @@ (define_insn "fix_truncdi_sse" + "%vcvtts2si{q}\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "maybe_vex") ++ (set_attr "prefix_rex" "1") + (set_attr "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") ++ (set (attr "prefix_rex") ++ (if_then_else ++ (and (eq_attr "prefix" "maybe_vex") ++ (ne (symbol_ref "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") ++ (set (attr "prefix_rex") ++ (if_then_else ++ (and (eq_attr "prefix" "maybe_vex") ++ (ne (symbol_ref "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") ++ (set (attr "prefix_rex") ++ (if_then_else ++ (and (eq_attr "prefix" "maybe_vex") ++ (ne (symbol_ref "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") ++ (set (attr "prefix_rex") ++ (if_then_else ++ (and (eq_attr "prefix" "maybe_vex") ++ (ne (symbol_ref "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")]) + + ;; Store-flag instructions. + +@@ -14231,6 +14593,7 @@ (define_insn "*avx_setcc" + "vcmp%D1s\t{%3, %2, %0|%0, %2, %3}" + [(set_attr "type" "ssecmp") + (set_attr "prefix" "vex") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + (define_insn "*sse_setcc" +@@ -14241,6 +14604,7 @@ (define_insn "*sse_setcc" + "SSE_FLOAT_MODE_P (mode) && !TARGET_SSE5" + "cmp%D1s\t{%3, %0|%0, %3}" + [(set_attr "type" "ssecmp") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + (define_insn "*sse5_setcc" +@@ -14251,6 +14615,7 @@ (define_insn "*sse5_setcc" + "TARGET_SSE5" + "com%Y1s\t{%3, %2, %0|%0, %2, %3}" + [(set_attr "type" "sse4arg") ++ (set_attr "length_immediate" "1") + (set_attr "mode" "")]) + + +@@ -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 "popcount2" +@@ -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 "fxam2_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" "")]) + +@@ -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" + [(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 - - 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 - - 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 + + * 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