gcc-4.5: Apply linaro updates and upstream updates
authorKhem Raj <raj.khem@gmail.com>
Sat, 4 Dec 2010 07:17:10 +0000 (23:17 -0800)
committerKhem Raj <raj.khem@gmail.com>
Sat, 4 Dec 2010 07:17:10 +0000 (23:17 -0800)
Signed-off-by: Khem Raj <raj.khem@gmail.com>
recipes/gcc/gcc-4.5.inc
recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99416.patch [moved from recipes/gcc/gcc-4.5/gcc-linaro-fix-lp-653316.patch with 83% similarity]
recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99417.patch [new file with mode: 0644]
recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99418.patch [new file with mode: 0644]
recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch [new file with mode: 0644]
recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99420.patch [moved from recipes/gcc/gcc-4.5/gcc-vmovl-PR45805.patch with 55% similarity]

index 3089980..8118b85 100644 (file)
@@ -8,9 +8,9 @@ DEPENDS = "mpfr gmp libmpc libelf"
 NATIVEDEPS = "mpfr-native gmp-native libmpc-native"
 
 
-INC_PR = "r20"
+INC_PR = "r21"
 
-SRCREV = "166342"
+SRCREV = "167449"
 PV = "4.5"
 # BINV should be incremented after updating to a revision
 # after a minor gcc release (e.g. 4.5.1 or 4.5.2) has been made
@@ -131,9 +131,12 @@ SRC_URI = "svn://gcc.gnu.org/svn/gcc/branches;module=${BRANCH} \
           file://linaro/gcc-4.5-linaro-r99413.patch \
           file://linaro/gcc-4.5-linaro-r99414.patch \
           file://linaro/gcc-4.5-linaro-r99415.patch \
-          file://gcc-vmovl-PR45805.patch \
+          file://linaro/gcc-4.5-linaro-r99416.patch \
+          file://linaro/gcc-4.5-linaro-r99417.patch \
+          file://linaro/gcc-4.5-linaro-r99418.patch \
+          file://linaro/gcc-4.5-linaro-r99419.patch \
+          file://linaro/gcc-4.5-linaro-r99420.patch \
           file://gcc-scalar-widening-pr45847.patch \
-          file://gcc-linaro-fix-lp-653316.patch \
          "
 
 SRC_URI_append_mips64 = " file://mips64-nomultilib.patch "
        * gcc.dg/20101010-1.c: New testcase.
 
 === modified file 'gcc/ifcvt.c'
-Index: gcc-4.5/gcc/ifcvt.c
-===================================================================
---- gcc-4.5.orig/gcc/ifcvt.c
-+++ gcc-4.5/gcc/ifcvt.c
-@@ -88,6 +88,8 @@ static int count_bb_insns (const_basic_b
+--- a/gcc/ifcvt.c      2010-10-04 00:50:43 +0000
++++ b/gcc/ifcvt.c      2010-10-15 10:01:07 +0000
+@@ -88,6 +88,8 @@
  static bool cheap_bb_rtx_cost_p (const_basic_block, int);
  static rtx first_active_insn (basic_block);
  static rtx last_active_insn (basic_block, int);
@@ -27,7 +25,7 @@ Index: gcc-4.5/gcc/ifcvt.c
  static basic_block block_fallthru (basic_block);
  static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
  static rtx cond_exec_get_condition (rtx);
-@@ -230,6 +232,48 @@ last_active_insn (basic_block bb, int sk
+@@ -230,6 +232,48 @@
    return insn;
  }
  
@@ -76,7 +74,7 @@ Index: gcc-4.5/gcc/ifcvt.c
  /* Return the basic block reached by falling though the basic block BB.  */
  
  static basic_block
-@@ -448,9 +492,9 @@ cond_exec_process_if_block (ce_if_block_
+@@ -448,9 +492,9 @@
        if (n_matching > 0)
        {
          if (then_end)
@@ -88,7 +86,7 @@ Index: gcc-4.5/gcc/ifcvt.c
          n_insns -= 2 * n_matching;
        }
  
-@@ -488,9 +532,9 @@ cond_exec_process_if_block (ce_if_block_
+@@ -488,9 +532,9 @@
          if (n_matching > 0)
            {
              if (then_start)
@@ -100,7 +98,7 @@ Index: gcc-4.5/gcc/ifcvt.c
              n_insns -= 2 * n_matching;
            }
        }
-@@ -646,7 +690,7 @@ cond_exec_process_if_block (ce_if_block_
+@@ -646,7 +690,7 @@
      {
        rtx from = then_first_tail;
        if (!INSN_P (from))
@@ -109,10 +107,10 @@ Index: gcc-4.5/gcc/ifcvt.c
        delete_insn_chain (from, BB_END (then_bb), false);
      }
    if (else_last_head)
-Index: gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
-===================================================================
---- /dev/null
-+++ gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
+
+=== added file 'gcc/testsuite/gcc.dg/20101010-1.c'
+--- a/gcc/testsuite/gcc.dg/20101010-1.c        1970-01-01 00:00:00 +0000
++++ b/gcc/testsuite/gcc.dg/20101010-1.c        2010-10-15 10:01:07 +0000
 @@ -0,0 +1,14 @@
 +/* { dg-do compile } */
 +/* { dg-options "-O2 -fno-crossjumping" } */
@@ -128,3 +126,4 @@ Index: gcc-4.5/gcc/testsuite/gcc.dg/20101010-1.c
 +    }
 +  return -1;
 +}
+
diff --git a/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99417.patch b/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99417.patch
new file mode 100644 (file)
index 0000000..6df93a0
--- /dev/null
@@ -0,0 +1,52 @@
+2010-10-15  Jie Zhang  <jie@codesourcery.com>
+
+       Backport from mainline:
+
+       gcc/testsuite/
+       2010-10-15  Jie Zhang  <jie@codesourcery.com>
+
+       * lib/lto.exp (lto-link-and-maybe-run): Use the default linker
+       script when relocatable linking.
+
+=== modified file 'gcc/testsuite/lib/lto.exp'
+--- a/gcc/testsuite/lib/lto.exp        2010-06-29 15:35:54 +0000
++++ b/gcc/testsuite/lib/lto.exp        2010-10-15 16:08:25 +0000
+@@ -156,6 +156,7 @@
+     global testcase
+     global tool
+     global compile_type
++    global board_info
+     # Check that all of the objects were built successfully.
+     foreach obj [split $objlist] {
+@@ -170,10 +171,29 @@
+     set options ""
+     lappend options "additional_flags=$optall $optfile"
++    set target_board [target_info name]
++    set relocatable 0
++
++    # Some LTO tests do relocatable linking. Some target boards set
++    # a linker script which can't be used for relocatable linking.
++    # Use the default linker script instead.
++    if { [lsearch -exact [split "$optall $optfile"] "-r"] >= 0 } {
++      set relocatable 1
++    }
++
++    if { $relocatable } {
++      set saved_ldscript [board_info $target_board ldscript]
++      set board_info($target_board,ldscript) ""
++    }
++
+     # Link the objects into an executable.
+     set comp_output [${tool}_target_compile "$objlist" $dest executable \
+                    "$options"]
++    if { $relocatable } {
++      set board_info($target_board,ldscript) $saved_ldscript
++    }
++
+     # Prune unimportant visibility warnings before checking output.
+     set comp_output [lto_prune_warns $comp_output]
+
diff --git a/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99418.patch b/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99418.patch
new file mode 100644 (file)
index 0000000..ebda1cd
--- /dev/null
@@ -0,0 +1,24 @@
+2010-10-20  Yao Qi  <yao@codesourcery.com>
+
+       Merge from Sourcery G++ to fix LP:660021
+       2010-10-18  Paul Brook  <paul@codesourcery.com>
+
+       * tree-vect-stmts.c (supportable_widening_operation): Check if wide
+       vector type exists.
+
+=== modified file 'gcc/tree-vect-stmts.c'
+--- a/gcc/tree-vect-stmts.c    2010-07-23 15:51:08 +0000
++++ b/gcc/tree-vect-stmts.c    2010-10-20 16:52:04 +0000
+@@ -4650,6 +4650,11 @@
+   tree wide_vectype = get_vectype_for_scalar_type (type);
+   enum tree_code c1, c2;
++  /* Check we have a valid vector type for the result.  */
++  if (!wide_vectype)
++    return false;
++
++
+   /* The result of a vectorized widening operation usually requires two vectors
+      (because the widened results do not fit int one vector). The generated
+      vector results would normally be expected to be generated in the same
+
diff --git a/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch b/recipes/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99419.patch
new file mode 100644 (file)
index 0000000..f5267c7
--- /dev/null
@@ -0,0 +1,756 @@
+2010-10-22  Julian Brown  <julian@codesourcery.com>
+
+       Backport from mainline:
+
+       2010-10-18  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+
+       gcc/testsuite/
+       * gcc.target/arm/synchronize.c: Permit dmb or mcr in assembler scan.
+
+2010-10-14  Julian Brown  <julian@codesourcery.com>
+
+       Backport from mainline:
+
+       2010-08-18  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+
+       gcc/
+       * config/arm/arm-protos.h (arm_expand_sync): New.
+       (arm_output_memory_barrier, arm_output_sync_insn): New.
+       (arm_sync_loop_insns): New.
+       * config/arm/arm.c (FL_ARCH7): New.
+       (FL_FOR_ARCH7): Include FL_ARCH7.
+       (arm_arch7): New.
+       (arm_print_operand): Support %C markup.
+       (arm_legitimize_sync_memory): New.
+       (arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
+       (arm_process_output_memory_barrier, arm_output_memory_barrier): New.
+       (arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
+       (arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
+       (arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
+       (arm_process_output_sync_insn, arm_output_sync_insn): New.
+       (arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
+       * config/arm/arm.h (struct arm_sync_generator): New.
+       (TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
+       (TARGET_HAVE_MEMORY_BARRIER): New.
+       (TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
+       * config/arm/arm.md: Include sync.md.
+       (UNSPEC_MEMORY_BARRIER): New.
+       (VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
+       (VUNSPEC_SYNC_OP):New.
+       (VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
+       (sync_result, sync_memory, sync_required_value): New attributes.
+       (sync_new_value, sync_t1, sync_t2): Likewise.
+       (sync_release_barrier, sync_op): Likewise.
+       (length): Add logic to length attribute defintion to call
+       arm_sync_loop_insns when appropriate.
+       * config/arm/sync.md: New file.
+
+       2010-09-02  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+
+       gcc/
+       * config/arm/predicates.md (arm_sync_memory_operand): New.
+       * config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
+       to arm_sync_memory_operand and constraint to Q.
+       (arm_sync_compare_and_swap<mode>): Likewise.
+       (arm_sync_compare_and_swap<mode>): Likewise.
+       (arm_sync_lock_test_and_setsi): Likewise.
+       (arm_sync_lock_test_and_set<mode>): Likewise.
+       (arm_sync_new_<sync_optab>si): Likewise.
+       (arm_sync_new_nandsi): Likewise.
+       (arm_sync_new_<sync_optab><mode>): Likewise.
+       (arm_sync_new_nand<mode>): Likewise.
+       (arm_sync_old_<sync_optab>si): Likewise.
+       (arm_sync_old_nandsi): Likewise.
+       (arm_sync_old_<sync_optab><mode>): Likewise.
+       (arm_sync_old_nand<mode>): Likewise.
+
+       2010-09-13  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+
+       gcc/
+       * config/arm/arm.md: (define_attr "conds"): Update comment.
+       * config/arm/sync.md (arm_sync_compare_and_swapsi): Change
+       conds attribute to clob.
+       (arm_sync_compare_and_swapsi): Likewise.
+       (arm_sync_compare_and_swap<mode>): Likewise.
+       (arm_sync_lock_test_and_setsi): Likewise.
+       (arm_sync_lock_test_and_set<mode>): Likewise.
+       (arm_sync_new_<sync_optab>si): Likewise.
+       (arm_sync_new_nandsi): Likewise.
+       (arm_sync_new_<sync_optab><mode>): Likewise.
+       (arm_sync_new_nand<mode>): Likewise.
+       (arm_sync_old_<sync_optab>si): Likewise.
+       (arm_sync_old_nandsi): Likewise.
+       (arm_sync_old_<sync_optab><mode>): Likewise.
+       (arm_sync_old_nand<mode>): Likewise.
+
+       2010-09-13  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+
+       gcc/testsuite/
+       * gcc.target/arm/sync-1.c: New.
+
+ 2010-10-20  Yao Qi  <yao@codesourcery.com>
+       Merge from Sourcery G++ to fix LP:660021
+@@ -110,22 +200,56 @@
+       Backport from FSF:
+-      2010-08-07  Marcus Shawcroft  <marcus.shawcroft@arm.com>
+-
+-      gcc/
+-      * config/arm/linux-atomic.c (SUBWORD_VAL_CAS): Instantiate with
+-      'unsigned short' and 'unsigned char' instead of 'short' and
+-      'char'. (SUBWORD_BOOL_CAS): Likewise.
+-      (SUBWORD_SYNC_OP): Likewise.
+-      (SUBWORD_TEST_AND_SET): Likewise.
+-      (FETCH_AND_OP_WORD): Parenthesise INF_OP
+-      (SUBWORD_SYNC_OP): Likewise.
+-      (OP_AND_FETCH_WORD): Likewise.
+-
+-      gcc/testsuite/
+-      * lib/target-supports.exp: (check_effective_target_sync_int_long):
+-      Add arm*-*-linux-gnueabi.
+-      (check_effective_target_sync_char_short): Likewise.
++      gcc/
++      2010-08-18  Marcus Shawcroft  <marcus.shawcroft@arm.com>
++      * config/arm/arm-protos.h (arm_expand_sync): New.
++      (arm_output_memory_barrier, arm_output_sync_insn): New.
++      (arm_sync_loop_insns): New.
++      * config/arm/arm.c (FL_ARCH7): New.
++      (FL_FOR_ARCH7): Include FL_ARCH7.
++      (arm_arch7): New.
++      (arm_print_operand): Support %C markup.
++      (arm_legitimize_sync_memory): New.
++      (arm_emit, arm_insn_count, arm_count, arm_output_asm_insn): New.
++      (arm_process_output_memory_barrier, arm_output_memory_barrier): New.
++      (arm_ldrex_suffix, arm_output_ldrex, arm_output_strex): New.
++      (arm_output_op2, arm_output_op3, arm_output_sync_loop): New.
++      (arm_get_sync_operand, FETCH_SYNC_OPERAND): New.
++      (arm_process_output_sync_insn, arm_output_sync_insn): New.
++      (arm_sync_loop_insns,arm_call_generator, arm_expand_sync): New.
++      * config/arm/arm.h (struct arm_sync_generator): New.
++      (TARGET_HAVE_DMB, TARGET_HAVE_DMB_MCR): New.
++      (TARGET_HAVE_MEMORY_BARRIER): New.
++      (TARGET_HAVE_LDREX, TARGET_HAVE_LDREXBHD): New.
++      * config/arm/arm.md: Include sync.md.
++      (UNSPEC_MEMORY_BARRIER): New.
++      (VUNSPEC_SYNC_COMPARE_AND_SWAP, VUNSPEC_SYNC_LOCK): New.
++      (VUNSPEC_SYNC_OP):New.
++      (VUNSPEC_SYNC_NEW_OP, VUNSPEC_SYNC_OLD_OP): New.
++      (sync_result, sync_memory, sync_required_value): New attributes.
++      (sync_new_value, sync_t1, sync_t2): Likewise.
++      (sync_release_barrier, sync_op): Likewise.
++      (length): Add logic to length attribute defintion to call
++      arm_sync_loop_insns when appropriate.
++      * config/arm/sync.md: New file.
++
++      gcc/
++      2010-09-02  Marcus Shawcroft  <marcus.shawcroft@arm.com>
++      * config/arm/predicates.md (arm_sync_memory_operand): New.
++      * config/arm/sync.md (arm_sync_compare_and_swapsi): Change predicate
++      to arm_sync_memory_operand and constraint to Q.
++      (arm_sync_compare_and_swap<mode>): Likewise.
++      (arm_sync_compare_and_swap<mode>): Likewise.
++      (arm_sync_lock_test_and_setsi): Likewise.
++      (arm_sync_lock_test_and_set<mode>): Likewise.
++      (arm_sync_new_<sync_optab>si): Likewise.
++      (arm_sync_new_nandsi): Likewise.
++      (arm_sync_new_<sync_optab><mode>): Likewise.
++      (arm_sync_new_nand<mode>): Likewise.
++      (arm_sync_old_<sync_optab>si): Likewise.
++      (arm_sync_old_nandsi): Likewise.
++      (arm_sync_old_<sync_optab><mode>): Likewise.
++      (arm_sync_old_nand<mode>): Likewise.
+ 2010-09-30  Jie Zhang  <jie@codesourcery.com>
+
+=== modified file 'gcc/config/arm/arm-protos.h'
+--- a/gcc/config/arm/arm-protos.h      2010-10-14 11:33:26 +0000
++++ b/gcc/config/arm/arm-protos.h      2010-11-04 10:45:05 +0000
+@@ -151,6 +151,11 @@
+ extern void arm_set_return_address (rtx, rtx);
+ extern int arm_eliminable_register (rtx);
+ extern const char *arm_output_shift(rtx *, int);
++extern void arm_expand_sync (enum machine_mode, struct arm_sync_generator *,
++                           rtx, rtx, rtx, rtx);
++extern const char *arm_output_memory_barrier (rtx *);
++extern const char *arm_output_sync_insn (rtx, rtx *);
++extern unsigned int arm_sync_loop_insns (rtx , rtx *);
+ extern bool arm_output_addr_const_extra (FILE *, rtx);
+
+=== modified file 'gcc/config/arm/arm.c'
+--- a/gcc/config/arm/arm.c     2010-10-15 06:01:22 +0000
++++ b/gcc/config/arm/arm.c     2010-11-04 10:45:05 +0000
+@@ -602,6 +602,7 @@
+ #define FL_NEON       (1 << 20)       /* Neon instructions.  */
+ #define FL_ARCH7EM    (1 << 21)             /* Instructions present in the ARMv7E-M
+                                        architecture.  */
++#define FL_ARCH7      (1 << 22)       /* Architecture 7.  */
+ #define FL_IWMMXT     (1 << 29)             /* XScale v2 or "Intel Wireless MMX technology".  */
+@@ -626,7 +627,7 @@
+ #define FL_FOR_ARCH6ZK        FL_FOR_ARCH6K
+ #define FL_FOR_ARCH6T2        (FL_FOR_ARCH6 | FL_THUMB2)
+ #define FL_FOR_ARCH6M (FL_FOR_ARCH6 & ~FL_NOTM)
+-#define FL_FOR_ARCH7  (FL_FOR_ARCH6T2 &~ FL_NOTM)
++#define FL_FOR_ARCH7  ((FL_FOR_ARCH6T2 & ~FL_NOTM) | FL_ARCH7)
+ #define FL_FOR_ARCH7A (FL_FOR_ARCH7 | FL_NOTM | FL_ARCH6K)
+ #define FL_FOR_ARCH7R (FL_FOR_ARCH7A | FL_DIV)
+ #define FL_FOR_ARCH7M (FL_FOR_ARCH7 | FL_DIV)
+@@ -664,6 +665,9 @@
+ /* Nonzero if this chip supports the ARM 6K extensions.  */
+ int arm_arch6k = 0;
++/* Nonzero if this chip supports the ARM 7 extensions.  */
++int arm_arch7 = 0;
++
+ /* Nonzero if instructions not present in the 'M' profile can be used.  */
+ int arm_arch_notm = 0;
+@@ -1602,6 +1606,7 @@
+   arm_arch6 = (insn_flags & FL_ARCH6) != 0;
+   arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
+   arm_arch_notm = (insn_flags & FL_NOTM) != 0;
++  arm_arch7 = (insn_flags & FL_ARCH7) != 0;
+   arm_arch7em = (insn_flags & FL_ARCH7EM) != 0;
+   arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0;
+   arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
+@@ -16562,6 +16567,17 @@
+       }
+       return;
++    case 'C':
++      {
++      rtx addr;
++
++      gcc_assert (GET_CODE (x) == MEM);
++      addr = XEXP (x, 0);
++      gcc_assert (GET_CODE (addr) == REG);
++      asm_fprintf (stream, "[%r]", REGNO (addr));
++      }
++      return;
++
+     /* Translate an S register number into a D register number and element index.  */
+     case 'y':
+       {
+@@ -22793,4 +22809,372 @@
+                                                     is_packed);
+ }
++/* Legitimize a memory reference for sync primitive implemented using
++   ldrex / strex.  We currently force the form of the reference to be
++   indirect without offset.  We do not yet support the indirect offset
++   addressing supported by some ARM targets for these
++   instructions.  */
++static rtx
++arm_legitimize_sync_memory (rtx memory)
++{
++  rtx addr = force_reg (Pmode, XEXP (memory, 0));
++  rtx legitimate_memory = gen_rtx_MEM (GET_MODE (memory), addr);
++
++  set_mem_alias_set (legitimate_memory, ALIAS_SET_MEMORY_BARRIER);
++  MEM_VOLATILE_P (legitimate_memory) = MEM_VOLATILE_P (memory);
++  return legitimate_memory;
++}
++
++/* An instruction emitter. */
++typedef void (* emit_f) (int label, const char *, rtx *);
++
++/* An instruction emitter that emits via the conventional
++   output_asm_insn.  */
++static void
++arm_emit (int label ATTRIBUTE_UNUSED, const char *pattern, rtx *operands)
++{
++  output_asm_insn (pattern, operands);
++}
++
++/* Count the number of emitted synchronization instructions.  */
++static unsigned arm_insn_count;
++
++/* An emitter that counts emitted instructions but does not actually
++   emit instruction into the the instruction stream.  */
++static void
++arm_count (int label,
++         const char *pattern ATTRIBUTE_UNUSED,
++         rtx *operands ATTRIBUTE_UNUSED)
++{
++  if (! label)
++    ++ arm_insn_count;
++}
++
++/* Construct a pattern using conventional output formatting and feed
++   it to output_asm_insn.  Provides a mechanism to construct the
++   output pattern on the fly.  Note the hard limit on the pattern
++   buffer size.  */
++static void
++arm_output_asm_insn (emit_f emit, int label, rtx *operands,
++                   const char *pattern, ...)
++{
++  va_list ap;
++  char buffer[256];
++
++  va_start (ap, pattern);
++  vsprintf (buffer, pattern, ap);
++  va_end (ap);
++  emit (label, buffer, operands);
++}
++
++/* Emit the memory barrier instruction, if any, provided by this
++   target to a specified emitter.  */
++static void
++arm_process_output_memory_barrier (emit_f emit, rtx *operands)
++{
++  if (TARGET_HAVE_DMB)
++    {
++      /* Note we issue a system level barrier. We should consider
++         issuing a inner shareabilty zone barrier here instead, ie.
++         "DMB ISH".  */
++      emit (0, "dmb\tsy", operands);
++      return;
++    }
++
++  if (TARGET_HAVE_DMB_MCR)
++    {
++      emit (0, "mcr\tp15, 0, r0, c7, c10, 5", operands);
++      return;
++    }
++
++  gcc_unreachable ();
++}
++
++/* Emit the memory barrier instruction, if any, provided by this
++   target.  */
++const char *
++arm_output_memory_barrier (rtx *operands)
++{
++  arm_process_output_memory_barrier (arm_emit, operands);
++  return "";
++}
++
++/* Helper to figure out the instruction suffix required on ldrex/strex
++   for operations on an object of the specified mode.  */
++static const char *
++arm_ldrex_suffix (enum machine_mode mode)
++{
++  switch (mode)
++    {
++    case QImode: return "b";
++    case HImode: return "h";
++    case SImode: return "";
++    case DImode: return "d";
++    default:
++      gcc_unreachable ();
++    }
++  return "";
++}
++
++/* Emit an ldrex{b,h,d, } instruction appropriate for the specified
++   mode.  */
++static void
++arm_output_ldrex (emit_f emit,
++                enum machine_mode mode,
++                rtx target,
++                rtx memory)
++{
++  const char *suffix = arm_ldrex_suffix (mode);
++  rtx operands[2];
++
++  operands[0] = target;
++  operands[1] = memory;
++  arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
++}
++
++/* Emit a strex{b,h,d, } instruction appropriate for the specified
++   mode.  */
++static void
++arm_output_strex (emit_f emit,
++                enum machine_mode mode,
++                const char *cc,
++                rtx result,
++                rtx value,
++                rtx memory)
++{
++  const char *suffix = arm_ldrex_suffix (mode);
++  rtx operands[3];
++
++  operands[0] = result;
++  operands[1] = value;
++  operands[2] = memory;
++  arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix,
++                     cc);
++}
++
++/* Helper to emit a two operand instruction.  */
++static void
++arm_output_op2 (emit_f emit, const char *mnemonic, rtx d, rtx s)
++{
++  rtx operands[2];
++
++  operands[0] = d;
++  operands[1] = s;
++  arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1", mnemonic);
++}
++
++/* Helper to emit a three operand instruction.  */
++static void
++arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b)
++{
++  rtx operands[3];
++
++  operands[0] = d;
++  operands[1] = a;
++  operands[2] = b;
++  arm_output_asm_insn (emit, 0, operands, "%s\t%%0, %%1, %%2", mnemonic);
++}
++
++/* Emit a load store exclusive synchronization loop.
++
++   do
++     old_value = [mem]
++     if old_value != required_value
++       break;
++     t1 = sync_op (old_value, new_value)
++     [mem] = t1, t2 = [0|1]
++   while ! t2
++
++   Note:
++     t1 == t2 is not permitted
++     t1 == old_value is permitted
++
++   required_value:
++
++   RTX register or const_int representing the required old_value for
++   the modify to continue, if NULL no comparsion is performed.  */
++static void
++arm_output_sync_loop (emit_f emit,
++                    enum machine_mode mode,
++                    rtx old_value,
++                    rtx memory,
++                    rtx required_value,
++                    rtx new_value,
++                    rtx t1,
++                    rtx t2,
++                    enum attr_sync_op sync_op,
++                    int early_barrier_required)
++{
++  rtx operands[1];
++
++  gcc_assert (t1 != t2);
++
++  if (early_barrier_required)
++    arm_process_output_memory_barrier (emit, NULL);
++
++  arm_output_asm_insn (emit, 1, operands, "%sLSYT%%=:", LOCAL_LABEL_PREFIX);
++
++  arm_output_ldrex (emit, mode, old_value, memory);
++
++  if (required_value)
++    {
++      rtx operands[2];
++
++      operands[0] = old_value;
++      operands[1] = required_value;
++      arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1");
++      arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX);
++    }
++
++  switch (sync_op)
++    {
++    case SYNC_OP_ADD:
++      arm_output_op3 (emit, "add", t1, old_value, new_value);
++      break;
++
++    case SYNC_OP_SUB:
++      arm_output_op3 (emit, "sub", t1, old_value, new_value);
++      break;
++
++    case SYNC_OP_IOR:
++      arm_output_op3 (emit, "orr", t1, old_value, new_value);
++      break;
++
++    case SYNC_OP_XOR:
++      arm_output_op3 (emit, "eor", t1, old_value, new_value);
++      break;
++
++    case SYNC_OP_AND:
++      arm_output_op3 (emit,"and", t1, old_value, new_value);
++      break;
++
++    case SYNC_OP_NAND:
++      arm_output_op3 (emit, "and", t1, old_value, new_value);
++      arm_output_op2 (emit, "mvn", t1, t1);
++      break;
++
++    case SYNC_OP_NONE:
++      t1 = new_value;
++      break;
++    }
++
++  arm_output_strex (emit, mode, "", t2, t1, memory);
++  operands[0] = t2;
++  arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
++  arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=", LOCAL_LABEL_PREFIX);
++
++  arm_process_output_memory_barrier (emit, NULL);
++  arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
++}
++
++static rtx
++arm_get_sync_operand (rtx *operands, int index, rtx default_value)
++{
++  if (index > 0)
++    default_value = operands[index - 1];
++
++  return default_value;
++}
++
++#define FETCH_SYNC_OPERAND(NAME, DEFAULT) \
++  arm_get_sync_operand (operands, (int) get_attr_sync_##NAME (insn), DEFAULT);
++
++/* Extract the operands for a synchroniztion instruction from the
++   instructions attributes and emit the instruction.  */
++static void
++arm_process_output_sync_insn (emit_f emit, rtx insn, rtx *operands)
++{
++  rtx result, memory, required_value, new_value, t1, t2;
++  int early_barrier;
++  enum machine_mode mode;
++  enum attr_sync_op sync_op;
++
++  result = FETCH_SYNC_OPERAND(result, 0);
++  memory = FETCH_SYNC_OPERAND(memory, 0);
++  required_value = FETCH_SYNC_OPERAND(required_value, 0);
++  new_value = FETCH_SYNC_OPERAND(new_value, 0);
++  t1 = FETCH_SYNC_OPERAND(t1, 0);
++  t2 = FETCH_SYNC_OPERAND(t2, 0);
++  early_barrier =
++    get_attr_sync_release_barrier (insn) == SYNC_RELEASE_BARRIER_YES;
++  sync_op = get_attr_sync_op (insn);
++  mode = GET_MODE (memory);
++
++  arm_output_sync_loop (emit, mode, result, memory, required_value,
++                      new_value, t1, t2, sync_op, early_barrier);
++}
++
++/* Emit a synchronization instruction loop.  */
++const char *
++arm_output_sync_insn (rtx insn, rtx *operands)
++{
++  arm_process_output_sync_insn (arm_emit, insn, operands);
++  return "";
++}
++
++/* Count the number of machine instruction that will be emitted for a
++   synchronization instruction.  Note that the emitter used does not
++   emit instructions, it just counts instructions being carefull not
++   to count labels.  */
++unsigned int
++arm_sync_loop_insns (rtx insn, rtx *operands)
++{
++  arm_insn_count = 0;
++  arm_process_output_sync_insn (arm_count, insn, operands);
++  return arm_insn_count;
++}
++
++/* Helper to call a target sync instruction generator, dealing with
++   the variation in operands required by the different generators.  */
++static rtx
++arm_call_generator (struct arm_sync_generator *generator, rtx old_value,
++                  rtx memory, rtx required_value, rtx new_value)
++{
++  switch (generator->op)
++    {
++    case arm_sync_generator_omn:
++      gcc_assert (! required_value);
++      return generator->u.omn (old_value, memory, new_value);
++
++    case arm_sync_generator_omrn:
++      gcc_assert (required_value);
++      return generator->u.omrn (old_value, memory, required_value, new_value);
++    }
++
++  return NULL;
++}
++
++/* Expand a synchronization loop. The synchronization loop is expanded
++   as an opaque block of instructions in order to ensure that we do
++   not subsequently get extraneous memory accesses inserted within the
++   critical region. The exclusive access property of ldrex/strex is
++   only guaranteed in there are no intervening memory accesses. */
++void
++arm_expand_sync (enum machine_mode mode,
++               struct arm_sync_generator *generator,
++               rtx target, rtx memory, rtx required_value, rtx new_value)
++{
++  if (target == NULL)
++    target = gen_reg_rtx (mode);
++
++  memory = arm_legitimize_sync_memory (memory);
++  if (mode != SImode)
++    {
++      rtx load_temp = gen_reg_rtx (SImode);
++
++      if (required_value)
++      required_value = convert_modes (SImode, mode, required_value, true);
++
++      new_value = convert_modes (SImode, mode, new_value, true);
++      emit_insn (arm_call_generator (generator, load_temp, memory,
++                                   required_value, new_value));
++      emit_move_insn (target, gen_lowpart (mode, load_temp));
++    }
++  else
++    {
++      emit_insn (arm_call_generator (generator, target, memory, required_value,
++                                   new_value));
++    }
++}
++
+ #include "gt-arm.h"
+
+=== modified file 'gcc/config/arm/arm.h'
+--- a/gcc/config/arm/arm.h     2010-10-15 10:44:40 +0000
++++ b/gcc/config/arm/arm.h     2010-11-04 10:45:05 +0000
+@@ -128,6 +128,24 @@
+ /* The processor for which instructions should be scheduled.  */
+ extern enum processor_type arm_tune;
++enum arm_sync_generator_tag
++  {
++    arm_sync_generator_omn,
++    arm_sync_generator_omrn
++  };
++
++/* Wrapper to pass around a polymorphic pointer to a sync instruction
++   generator and.  */
++struct arm_sync_generator
++{
++  enum arm_sync_generator_tag op;
++  union
++  {
++    rtx (* omn) (rtx, rtx, rtx);
++    rtx (* omrn) (rtx, rtx, rtx, rtx);
++  } u;
++};
++
+ typedef enum arm_cond_code
+ {
+   ARM_EQ = 0, ARM_NE, ARM_CS, ARM_CC, ARM_MI, ARM_PL, ARM_VS, ARM_VC,
+@@ -272,6 +290,20 @@
+    for Thumb-2.  */
+ #define TARGET_UNIFIED_ASM TARGET_THUMB2
++/* Nonzero if this chip provides the DMB instruction.  */
++#define TARGET_HAVE_DMB               (arm_arch7)
++
++/* Nonzero if this chip implements a memory barrier via CP15.  */
++#define TARGET_HAVE_DMB_MCR   (arm_arch6k && ! TARGET_HAVE_DMB)
++
++/* Nonzero if this chip implements a memory barrier instruction.  */
++#define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
++
++/* Nonzero if this chip supports ldrex and strex */
++#define TARGET_HAVE_LDREX     ((arm_arch6 && TARGET_ARM) || arm_arch7)
++
++/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}.  */
++#define TARGET_HAVE_LDREXBHD  ((arm_arch6k && TARGET_ARM) || arm_arch7)
+ /* True iff the full BPABI is being used.  If TARGET_BPABI is true,
+    then TARGET_AAPCS_BASED must be true -- but the converse does not
+@@ -405,6 +437,12 @@
+ /* Nonzero if this chip supports the ARM Architecture 6 extensions.  */
+ extern int arm_arch6;
++/* Nonzero if this chip supports the ARM Architecture 6k extensions.  */
++extern int arm_arch6k;
++
++/* Nonzero if this chip supports the ARM Architecture 7 extensions.  */
++extern int arm_arch7;
++
+ /* Nonzero if instructions not present in the 'M' profile can be used.  */
+ extern int arm_arch_notm;
+
+=== modified file 'gcc/config/arm/arm.md'
+--- a/gcc/config/arm/arm.md    2010-10-14 11:33:26 +0000
++++ b/gcc/config/arm/arm.md    2010-11-04 10:45:05 +0000
+@@ -103,6 +103,7 @@
+    (UNSPEC_RBIT 26)       ; rbit operation.
+    (UNSPEC_SYMBOL_OFFSET 27) ; The offset of the start of the symbol from
+                              ; another symbolic address.
++   (UNSPEC_MEMORY_BARRIER 28) ; Represent a memory barrier.
+   ]
+ )
+@@ -139,6 +140,11 @@
+    (VUNSPEC_ALIGN32  16) ; Used to force 32-byte alignment.
+    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
+                        ; handling.
++   (VUNSPEC_SYNC_COMPARE_AND_SWAP 21) ; Represent an atomic compare swap.
++   (VUNSPEC_SYNC_LOCK             22) ; Represent a sync_lock_test_and_set.
++   (VUNSPEC_SYNC_OP               23) ; Represent a sync_<op>
++   (VUNSPEC_SYNC_NEW_OP           24) ; Represent a sync_new_<op>
++   (VUNSPEC_SYNC_OLD_OP           25) ; Represent a sync_old_<op>
+   ]
+ )
\f
+@@ -163,8 +169,21 @@
+ (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
+   (const (symbol_ref "arm_fpu_attr")))
++(define_attr "sync_result"          "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_memory"          "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_required_value"  "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_new_value"       "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_t1"              "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_t2"              "none,0,1,2,3,4,5" (const_string "none"))
++(define_attr "sync_release_barrier" "yes,no"           (const_string "yes"))
++(define_attr "sync_op"              "none,add,sub,ior,xor,and,nand"
++                                    (const_string "none"))
++
+ ; LENGTH of an instruction (in bytes)
+-(define_attr "length" "" (const_int 4))
++(define_attr "length" ""
++  (cond [(not (eq_attr "sync_memory" "none"))
++         (symbol_ref "arm_sync_loop_insns (insn, operands) * 4")
++      ] (const_int 4)))
+ ; POOL_RANGE is how far away from a constant pool entry that this insn
+ ; can be placed.  If the distance is zero, then this insn will never
+@@ -11549,4 +11568,5 @@
+ (include "thumb2.md")
+ ;; Neon patterns
+ (include "neon.md")
+-
++;; Synchronization Primitives
++(include "sync.md")
+
+=== modified file 'gcc/config/arm/predicates.md'
+--- a/gcc/config/arm/predicates.md     2010-10-14 11:33:26 +0000
++++ b/gcc/config/arm/predicates.md     2010-11-04 10:45:05 +0000
+@@ -573,6 +573,11 @@
+               (and (match_test "TARGET_32BIT")
+                    (match_operand 0 "arm_di_operand"))))
++;; True if the operand is memory reference suitable for a ldrex/strex.
++(define_predicate "arm_sync_memory_operand"
++  (and (match_operand 0 "memory_operand")
++       (match_code "reg" "0")))
++
+ ;; Predicates for parallel expanders based on mode.
+ (define_special_predicate "vect_par_constant_high" 
+   (match_code "parallel")
+
+=== modified file 'gcc/testsuite/gcc.target/arm/synchronize.c'
+--- a/gcc/testsuite/gcc.target/arm/synchronize.c       2009-08-12 14:55:19 +0000
++++ b/gcc/testsuite/gcc.target/arm/synchronize.c       2010-11-04 10:45:05 +0000
+@@ -1,4 +1,4 @@
+-/* { dg-final { scan-assembler "__sync_synchronize" { target arm*-*-linux-*eabi } } } */
++/* { dg-final { scan-assembler "__sync_synchronize|dmb|mcr" { target arm*-*-linux-*eabi } } } */
+ void *foo (void)
+ {
+
@@ -1,9 +1,18 @@
-Source: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45805
+2010-10-18  Kazu Hirata  <kazu@codesourcery.com>
 
-Index: gcc-4.5/gcc/config/arm/neon.md
-===================================================================
---- gcc-4.5.orig/gcc/config/arm/neon.md        2010-09-28 12:04:38.000000000 -0700
-+++ gcc-4.5/gcc/config/arm/neon.md     2010-09-28 12:07:28.026227000 -0700
+       Issue #9720
+       Backport from mainline:
+       gcc/
+       2010-10-07  Tejas Belagod  <tejas.belagod@arm.com>
+       * config/arm/neon.md (neon_unpack<US>_<mode>): Add 'w' to
+       constraint, add register specifier in instruction template.
+       (neon_vec_pack_trunc_<mode>): Likewise.
+       (neon_vec_<US>mult_<mode>): Add register specifier to
+       instruction template.
+
+=== modified file 'gcc/config/arm/neon.md'
+--- a/gcc/config/arm/neon.md   2010-09-09 14:11:34 +0000
++++ b/gcc/config/arm/neon.md   2010-11-04 11:47:50 +0000
 @@ -5682,9 +5682,9 @@
  ;; Vectorize for non-neon-quad case
  (define_insn "neon_unpack<US>_<mode>"
@@ -25,3 +34,4 @@ Index: gcc-4.5/gcc/config/arm/neon.md
    [(set_attr "neon_type" "neon_shift_1")]
  )
  
+