Merge branch 'vendor/GCC47'
authorJohn Marino <draco@marino.st>
Wed, 8 May 2013 16:37:36 +0000 (18:37 +0200)
committerJohn Marino <draco@marino.st>
Wed, 8 May 2013 16:37:36 +0000 (18:37 +0200)
1  2 
contrib/gcc-4.7/gcc/config/i386/i386.c
contrib/gcc-4.7/gcc/gcc.c
contrib/gcc-4.7/gcc/tree-inline.c
contrib/gcc-4.7/libgcc/unwind-dw2-fde-dip.c

@@@ -1,6 -1,6 +1,6 @@@
  /* Subroutines used for code generation on IA-32.
-    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-    2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+    2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
     Free Software Foundation, Inc.
  
  This file is part of GCC.
@@@ -5592,7 -5592,10 +5592,10 @@@ init_cumulative_args (CUMULATIVE_ARGS *
        {
          /* The return value of this function uses 256bit AVX modes.  */
          if (caller)
-           cfun->machine->callee_return_avx256_p = true;
+           {
+             cfun->machine->callee_return_avx256_p = true;
+             cum->callee_return_avx256_p = true;
+           }
          else
            cfun->machine->caller_return_avx256_p = true;
        }
@@@ -6863,11 -6866,20 +6866,20 @@@ ix86_function_arg (cumulative_args_t cu
      {
        /* This argument uses 256bit AVX modes.  */
        if (cum->caller)
-       cfun->machine->callee_pass_avx256_p = true;
+       cum->callee_pass_avx256_p = true;
        else
        cfun->machine->caller_pass_avx256_p = true;
      }
  
+   if (cum->caller && mode == VOIDmode)
+     {
+       /* This function is called with MODE == VOIDmode immediately
+        before the call instruction is emitted.  We copy callee 256bit
+        AVX info from the current CUM here.  */
+       cfun->machine->callee_return_avx256_p = cum->callee_return_avx256_p;
+       cfun->machine->callee_pass_avx256_p = cum->callee_pass_avx256_p;
+     }
    return arg;
  }
  
@@@ -9558,6 -9570,8 +9570,8 @@@ get_scratch_register_on_entry (struct s
        tree decl = current_function_decl, fntype = TREE_TYPE (decl);
        bool fastcall_p
        = lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)) != NULL_TREE;
+       bool thiscall_p
+       = lookup_attribute ("thiscall", TYPE_ATTRIBUTES (fntype)) != NULL_TREE;
        bool static_chain_p = DECL_STATIC_CHAIN (decl);
        int regparm = ix86_function_regparm (fntype, decl);
        int drap_regno
        if ((regparm < 1 || (fastcall_p && !static_chain_p))
          && drap_regno != AX_REG)
        regno = AX_REG;
-       else if (regparm < 2 && drap_regno != DX_REG)
+       /* 'thiscall' sets regparm to 1, uses ecx for arguments and edx
+         for the static chain register.  */
+       else if (thiscall_p && !static_chain_p && drap_regno != AX_REG)
+         regno = AX_REG;
+       else if (regparm < 2 && !thiscall_p && drap_regno != DX_REG)
        regno = DX_REG;
        /* ecx is the static chain register.  */
-       else if (regparm < 3 && !fastcall_p && !static_chain_p
+       else if (regparm < 3 && !fastcall_p && !thiscall_p
+              && !static_chain_p
               && drap_regno != CX_REG)
        regno = CX_REG;
        else if (ix86_save_reg (BX_REG, true))
@@@ -9604,6 -9623,7 +9623,7 @@@ release_scratch_register_on_entry (stru
  {
    if (sr->saved)
      {
+       struct machine_function *m = cfun->machine;
        rtx x, insn = emit_insn (gen_pop (sr->reg));
  
        /* The RTX_FRAME_RELATED_P mechanism doesn't know about pop.  */
        x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD));
        x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x);
        add_reg_note (insn, REG_FRAME_RELATED_EXPR, x);
+       m->fs.sp_offset -= UNITS_PER_WORD;
      }
  }
  
@@@ -10339,7 -10360,7 +10360,7 @@@ ix86_expand_prologue (void
        rtx eax = gen_rtx_REG (Pmode, AX_REG);
        rtx r10 = NULL;
        rtx (*adjust_stack_insn)(rtx, rtx, rtx);
+       const bool sp_is_cfa_reg = (m->fs.cfa_reg == stack_pointer_rtx);
        bool eax_live = false;
        bool r10_live = false;
  
        if (!TARGET_64BIT_MS_ABI)
          eax_live = ix86_eax_live_at_start_p ();
  
+       /* Note that SEH directives need to continue tracking the stack
+        pointer even after the frame pointer has been set up.  */
        if (eax_live)
        {
-         emit_insn (gen_push (eax));
+         insn = emit_insn (gen_push (eax));
          allocate -= UNITS_PER_WORD;
+         if (sp_is_cfa_reg || TARGET_SEH)
+           {
+             if (sp_is_cfa_reg)
+               m->fs.cfa_offset += UNITS_PER_WORD;
+             RTX_FRAME_RELATED_P (insn) = 1;
+           }
        }
        if (r10_live)
        {
          r10 = gen_rtx_REG (Pmode, R10_REG);
-         emit_insn (gen_push (r10));
+         insn = emit_insn (gen_push (r10));
          allocate -= UNITS_PER_WORD;
+         if (sp_is_cfa_reg || TARGET_SEH)
+           {
+             if (sp_is_cfa_reg)
+               m->fs.cfa_offset += UNITS_PER_WORD;
+             RTX_FRAME_RELATED_P (insn) = 1;
+           }
        }
  
        emit_move_insn (eax, GEN_INT (allocate));
        insn = emit_insn (adjust_stack_insn (stack_pointer_rtx,
                                           stack_pointer_rtx, eax));
  
-       /* Note that SEH directives need to continue tracking the stack
-        pointer even after the frame pointer has been set up.  */
-       if (m->fs.cfa_reg == stack_pointer_rtx || TARGET_SEH)
+       if (sp_is_cfa_reg || TARGET_SEH)
        {
-         if (m->fs.cfa_reg == stack_pointer_rtx)
+         if (sp_is_cfa_reg)
            m->fs.cfa_offset += allocate;
          RTX_FRAME_RELATED_P (insn) = 1;
          add_reg_note (insn, REG_FRAME_RELATED_EXPR,
                        gen_rtx_SET (VOIDmode, stack_pointer_rtx,
@@@ -11069,12 -11102,15 +11102,15 @@@ split_stack_prologue_scratch_regno (voi
      return R11_REG;
    else
      {
-       bool is_fastcall;
+       bool is_fastcall, is_thiscall;
        int regparm;
  
        is_fastcall = (lookup_attribute ("fastcall",
                                       TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
                     != NULL);
+       is_thiscall = (lookup_attribute ("thiscall",
+                                      TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl)))
+                    != NULL);
        regparm = ix86_function_regparm (TREE_TYPE (cfun->decl), cfun->decl);
  
        if (is_fastcall)
            }
          return AX_REG;
        }
+       else if (is_thiscall)
+         {
+         if (!DECL_STATIC_CHAIN (cfun->decl))
+           return DX_REG;
+         return AX_REG;
+       }
        else if (regparm < 3)
        {
          if (!DECL_STATIC_CHAIN (cfun->decl))
@@@ -11402,10 -11444,6 +11444,6 @@@ ix86_address_subreg_operand (rtx op
    if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
      return false;
  
-   /* simplify_subreg does not handle stack pointer.  */
-   if (REGNO (op) == STACK_POINTER_REGNUM)
-     return false;
    /* Allow only SUBREGs of non-eliminable hard registers.  */
    return register_no_elim_operand (op, mode);
  }
@@@ -12320,7 -12358,6 +12358,6 @@@ legitimize_pic_address (rtx orig, rtx r
  {
    rtx addr = orig;
    rtx new_rtx = orig;
-   rtx base;
  
  #if TARGET_MACHO
    if (TARGET_MACHO && !TARGET_64BIT)
            }
          else
            {
-             base = legitimize_pic_address (XEXP (addr, 0), reg);
-             new_rtx  = legitimize_pic_address (XEXP (addr, 1),
-                                                base == reg ? NULL_RTX : reg);
+             rtx base = legitimize_pic_address (op0, reg);
+             enum machine_mode mode = GET_MODE (base);
+             new_rtx
+               = legitimize_pic_address (op1, base == reg ? NULL_RTX : reg);
  
              if (CONST_INT_P (new_rtx))
-               new_rtx = plus_constant (base, INTVAL (new_rtx));
+               {
+                 if (INTVAL (new_rtx) < -16*1024*1024
+                     || INTVAL (new_rtx) >= 16*1024*1024)
+                   {
+                     if (!x86_64_immediate_operand (new_rtx, mode))
+                       new_rtx = force_reg (mode, new_rtx);
+                     new_rtx
+                       = gen_rtx_PLUS (mode, force_reg (mode, base), new_rtx);
+                   }
+                 else
+                   new_rtx = plus_constant (base, INTVAL (new_rtx));
+               }
              else
                {
-                 if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
+                 if (GET_CODE (new_rtx) == PLUS
+                     && CONSTANT_P (XEXP (new_rtx, 1)))
                    {
-                     base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
+                     base = gen_rtx_PLUS (mode, base, XEXP (new_rtx, 0));
                      new_rtx = XEXP (new_rtx, 1);
                    }
-                 new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
+                 new_rtx = gen_rtx_PLUS (mode, base, new_rtx);
                }
            }
        }
@@@ -12637,6 -12687,9 +12687,9 @@@ legitimize_tls_address (rtx x, enum tls
          tp = get_thread_pointer (true);
          dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
  
+         if (GET_MODE (x) != Pmode)
+           x = gen_rtx_ZERO_EXTEND (Pmode, x);
          set_unique_reg_note (get_last_insn (), REG_EQUAL, x);
        }
        else
  
          if (TARGET_64BIT)
            {
-             rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
+             rtx rax = gen_rtx_REG (Pmode, AX_REG);
+             rtx insns;
  
              start_sequence ();
              emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr));
              insns = get_insns ();
              end_sequence ();
  
+             if (GET_MODE (x) != Pmode)
+               x = gen_rtx_ZERO_EXTEND (Pmode, x);
              RTL_CONST_CALL_P (insns) = 1;
              emit_libcall_block (insns, dest, rax, x);
            }
  
          if (TARGET_64BIT)
            {
-             rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, eqv;
+             rtx rax = gen_rtx_REG (Pmode, AX_REG);
+             rtx insns, eqv;
  
              start_sequence ();
              emit_call_insn (gen_tls_local_dynamic_base_64 (rax, caddr));
        {
          dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, dest, tp));
  
+         if (GET_MODE (x) != Pmode)
+           x = gen_rtx_ZERO_EXTEND (Pmode, x);
          set_unique_reg_note (get_last_insn (), REG_EQUAL, x);
        }
        break;
  print_reg (rtx x, int code, FILE *file)
  {
    const char *reg;
+   unsigned int regno;
    bool duplicated = code == 'd' && TARGET_AVX;
  
-   gcc_assert (x == pc_rtx
-             || (REGNO (x) != ARG_POINTER_REGNUM
-                 && REGNO (x) != FRAME_POINTER_REGNUM
-                 && REGNO (x) != FLAGS_REG
-                 && REGNO (x) != FPSR_REG
-                 && REGNO (x) != FPCR_REG));
    if (ASSEMBLER_DIALECT == ASM_ATT)
      putc ('%', file);
  
        return;
      }
  
+   regno = true_regnum (x);
+   gcc_assert (regno != ARG_POINTER_REGNUM
+             && regno != FRAME_POINTER_REGNUM
+             && regno != FLAGS_REG
+             && regno != FPSR_REG
+             && regno != FPCR_REG);
    if (code == 'w' || MMX_REG_P (x))
      code = 2;
    else if (code == 'b')
  
    /* Irritatingly, AMD extended registers use different naming convention
       from the normal registers: "r%d[bwd]"  */
-   if (REX_INT_REG_P (x))
+   if (REX_INT_REGNO_P (regno))
      {
        gcc_assert (TARGET_64BIT);
        putc ('r', file);
-       fprint_ul (file, REGNO (x) - FIRST_REX_INT_REG + 8);
+       fprint_ul (file, regno - FIRST_REX_INT_REG + 8);
        switch (code)
        {
          case 0:
      case 16:
      case 2:
      normal:
-       reg = hi_reg_name[REGNO (x)];
+       reg = hi_reg_name[regno];
        break;
      case 1:
-       if (REGNO (x) >= ARRAY_SIZE (qi_reg_name))
+       if (regno >= ARRAY_SIZE (qi_reg_name))
        goto normal;
-       reg = qi_reg_name[REGNO (x)];
+       reg = qi_reg_name[regno];
        break;
      case 0:
-       if (REGNO (x) >= ARRAY_SIZE (qi_high_reg_name))
+       if (regno >= ARRAY_SIZE (qi_high_reg_name))
        goto normal;
-       reg = qi_high_reg_name[REGNO (x)];
+       reg = qi_high_reg_name[regno];
        break;
      case 32:
        if (SSE_REG_P (x))
        {
          gcc_assert (!duplicated);
          putc ('y', file);
-         fputs (hi_reg_name[REGNO (x)] + 1, file);
+         fputs (hi_reg_name[regno] + 1, file);
          return;
        }
        break;
@@@ -14458,7 -14520,8 +14520,8 @@@ ix86_print_operand (FILE *file, rtx x, 
        putc ('$', file);
        /* Sign extend 32bit SFmode immediate to 8 bytes.  */
        if (code == 'q')
-       fprintf (file, "0x%08llx", (unsigned long long) (int) l);
+       fprintf (file, "0x%08" HOST_LONG_LONG_FORMAT "x",
+                (unsigned long long) (int) l);
        else
        fprintf (file, "0x%08x", (unsigned int) l);
      }
@@@ -14560,22 -14623,6 +14623,6 @@@ ix86_print_operand_address (FILE *file
  
    gcc_assert (ok);
  
-   if (parts.base && GET_CODE (parts.base) == SUBREG)
-     {
-       rtx tmp = SUBREG_REG (parts.base);
-       parts.base = simplify_subreg (GET_MODE (parts.base),
-                                   tmp, GET_MODE (tmp), 0);
-       gcc_assert (parts.base != NULL_RTX);
-     }
-   if (parts.index && GET_CODE (parts.index) == SUBREG)
-     {
-       rtx tmp = SUBREG_REG (parts.index);
-       parts.index = simplify_subreg (GET_MODE (parts.index),
-                                    tmp, GET_MODE (tmp), 0);
-       gcc_assert (parts.index != NULL_RTX);
-     }
    base = parts.base;
    index = parts.index;
    disp = parts.disp;
    else
      {
        /* Print SImode register names to force addr32 prefix.  */
-       if (GET_CODE (addr) == SUBREG)
-       {
-         gcc_assert (TARGET_64BIT);
-         gcc_assert (GET_MODE (addr) == SImode);
-         gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
-         gcc_assert (!code);
-         code = 'l';
-       }
-       else if (GET_CODE (addr) == ZERO_EXTEND
-              || GET_CODE (addr) == AND)
+       if (SImode_address_operand (addr, VOIDmode))
        {
+ #ifdef ENABLE_CHECKING
          gcc_assert (TARGET_64BIT);
-         gcc_assert (GET_MODE (addr) == DImode);
+         switch (GET_CODE (addr))
+           {
+           case SUBREG:
+             gcc_assert (GET_MODE (addr) == SImode);
+             gcc_assert (GET_MODE (SUBREG_REG (addr)) == DImode);
+             break;
+           case ZERO_EXTEND:
+           case AND:
+             gcc_assert (GET_MODE (addr) == DImode);
+             break;
+           default:
+             gcc_unreachable ();
+           }
+ #endif
          gcc_assert (!code);
-         code = 'l';
+         code = 'k';
+       }
+       else if (code == 0
+              && TARGET_X32
+              && disp
+              && CONST_INT_P (disp)
+              && INTVAL (disp) < -16*1024*1024)
+       {
+         /* X32 runs in 64-bit mode, where displacement, DISP, in
+            address DISP(%r64), is encoded as 32-bit immediate sign-
+            extended from 32-bit to 64-bit.  For -0x40000300(%r64),
+            address is %r64 + 0xffffffffbffffd00.  When %r64 <
+            0x40000300, like 0x37ffe064, address is 0xfffffffff7ffdd64,
+            which is invalid for x32.  The correct address is %r64
+            - 0x40000300 == 0xf7ffdd64.  To properly encode
+            -0x40000300(%r64) for x32, we zero-extend negative
+            displacement by forcing addr32 prefix which truncates
+            0xfffffffff7ffdd64 to 0xf7ffdd64.  In theory, we should
+            zero-extend all negative displacements, including -1(%rsp).
+            However, for small negative displacements, sign-extension
+            won't cause overflow.  We only zero-extend negative
+            displacements if they < -16*1024*1024, which is also used
+            to check legitimate address displacements for PIC.  */
+         code = 'k';
        }
  
        if (ASSEMBLER_DIALECT == ASM_ATT)
@@@ -15543,8 -15618,7 +15618,7 @@@ ix86_expand_move (enum machine_mode mod
                                     op0, 1, OPTAB_DIRECT);
          if (tmp == op0)
            return;
-         if (GET_MODE (tmp) != mode)
-           op1 = convert_to_mode (mode, tmp, 1);
+         op1 = convert_to_mode (mode, tmp, 1);
        }
      }
  
@@@ -15708,7 -15782,8 +15782,8 @@@ ix86_avx256_split_vector_move_misalign 
  {
    rtx m;
    rtx (*extract) (rtx, rtx, rtx);
-   rtx (*move_unaligned) (rtx, rtx);
+   rtx (*load_unaligned) (rtx, rtx);
+   rtx (*store_unaligned) (rtx, rtx);
    enum machine_mode mode;
  
    switch (GET_MODE (op0))
        gcc_unreachable ();
      case V32QImode:
        extract = gen_avx_vextractf128v32qi;
-       move_unaligned = gen_avx_movdqu256;
+       load_unaligned = gen_avx_loaddqu256;
+       store_unaligned = gen_avx_storedqu256;
        mode = V16QImode;
        break;
      case V8SFmode:
        extract = gen_avx_vextractf128v8sf;
-       move_unaligned = gen_avx_movups256;
+       load_unaligned = gen_avx_loadups256;
+       store_unaligned = gen_avx_storeups256;
        mode = V4SFmode;
        break;
      case V4DFmode:
        extract = gen_avx_vextractf128v4df;
-       move_unaligned = gen_avx_movupd256;
+       load_unaligned = gen_avx_loadupd256;
+       store_unaligned = gen_avx_storeupd256;
        mode = V2DFmode;
        break;
      }
  
-   if (MEM_P (op1) && TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
+   if (MEM_P (op1))
      {
-       rtx r = gen_reg_rtx (mode);
-       m = adjust_address (op1, mode, 0);
-       emit_move_insn (r, m);
-       m = adjust_address (op1, mode, 16);
-       r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
-       emit_move_insn (op0, r);
+       if (TARGET_AVX256_SPLIT_UNALIGNED_LOAD)
+       {
+         rtx r = gen_reg_rtx (mode);
+         m = adjust_address (op1, mode, 0);
+         emit_move_insn (r, m);
+         m = adjust_address (op1, mode, 16);
+         r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m);
+         emit_move_insn (op0, r);
+       }
+       else
+       emit_insn (load_unaligned (op0, op1));
      }
-   else if (MEM_P (op0) && TARGET_AVX256_SPLIT_UNALIGNED_STORE)
+   else if (MEM_P (op0))
      {
-       m = adjust_address (op0, mode, 0);
-       emit_insn (extract (m, op1, const0_rtx));
-       m = adjust_address (op0, mode, 16);
-       emit_insn (extract (m, op1, const1_rtx));
+       if (TARGET_AVX256_SPLIT_UNALIGNED_STORE)
+       {
+         m = adjust_address (op0, mode, 0);
+         emit_insn (extract (m, op1, const0_rtx));
+         m = adjust_address (op0, mode, 16);
+         emit_insn (extract (m, op1, const1_rtx));
+       }
+       else
+       emit_insn (store_unaligned (op0, op1));
      }
    else
-     emit_insn (move_unaligned (op0, op1));
+     gcc_unreachable ();
  }
  
  /* Implement the movmisalign patterns for SSE.  Non-SSE modes go
  ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[])
  {
    rtx op0, op1, m;
+   rtx (*move_unaligned) (rtx, rtx);
  
    op0 = operands[0];
    op1 = operands[1];
              /*  If we're optimizing for size, movups is the smallest.  */
              if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
                {
+                 if (MEM_P (op1))
+                   move_unaligned = gen_sse_loadups;
+                 else if (MEM_P (op0))
+                   move_unaligned = gen_sse_storeups;
+                 else
+                   gcc_unreachable ();
                  op0 = gen_lowpart (V4SFmode, op0);
                  op1 = gen_lowpart (V4SFmode, op1);
-                 emit_insn (gen_sse_movups (op0, op1));
+                 emit_insn (move_unaligned (op0, op1));
                  return;
                }
+             if (MEM_P (op1))
+               move_unaligned = gen_sse2_loaddqu;
+             else if (MEM_P (op0))
+               move_unaligned = gen_sse2_storedqu;
+             else
+               gcc_unreachable ();
              op0 = gen_lowpart (V16QImode, op0);
              op1 = gen_lowpart (V16QImode, op1);
-             emit_insn (gen_sse2_movdqu (op0, op1));
+             emit_insn (move_unaligned (op0, op1));
              break;
            case 32:
              op0 = gen_lowpart (V32QImode, op0);
          switch (mode)
            {
            case V4SFmode:
-             emit_insn (gen_sse_movups (op0, op1));
+             if (MEM_P (op1))
+               move_unaligned = gen_sse_loadups;
+             else if (MEM_P (op0))
+               move_unaligned = gen_sse_storeups;
+             else
+               gcc_unreachable ();
+             emit_insn (move_unaligned (op0, op1));
              break;
            case V8SFmode:
              ix86_avx256_split_vector_move_misalign (op0, op1);
            case V2DFmode:
              if (TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL)
                {
+                 if (MEM_P (op1))
+                   move_unaligned = gen_sse_loadups;
+                 else if (MEM_P (op0))
+                   move_unaligned = gen_sse_storeups;
+                 else
+                   gcc_unreachable ();
                  op0 = gen_lowpart (V4SFmode, op0);
                  op1 = gen_lowpart (V4SFmode, op1);
-                 emit_insn (gen_sse_movups (op0, op1));
+                 emit_insn (move_unaligned (op0, op1));
                  return;
                }
-             emit_insn (gen_sse2_movupd (op0, op1));
+             if (MEM_P (op1))
+               move_unaligned = gen_sse2_loadupd;
+             else if (MEM_P (op0))
+               move_unaligned = gen_sse2_storeupd;
+             else
+               gcc_unreachable ();
+             emit_insn (move_unaligned (op0, op1));
              break;
            case V4DFmode:
              ix86_avx256_split_vector_move_misalign (op0, op1);
        {
          op0 = gen_lowpart (V4SFmode, op0);
          op1 = gen_lowpart (V4SFmode, op1);
-         emit_insn (gen_sse_movups (op0, op1));
+         emit_insn (gen_sse_loadups (op0, op1));
          return;
        }
  
        {
          op0 = gen_lowpart (V16QImode, op0);
          op1 = gen_lowpart (V16QImode, op1);
-         emit_insn (gen_sse2_movdqu (op0, op1));
+         emit_insn (gen_sse2_loaddqu (op0, op1));
          return;
        }
  
            {
              op0 = gen_lowpart (V2DFmode, op0);
              op1 = gen_lowpart (V2DFmode, op1);
-             emit_insn (gen_sse2_movupd (op0, op1));
+             emit_insn (gen_sse2_loadupd (op0, op1));
              return;
            }
  
            {
              op0 = gen_lowpart (V4SFmode, op0);
              op1 = gen_lowpart (V4SFmode, op1);
-             emit_insn (gen_sse_movups (op0, op1));
+             emit_insn (gen_sse_loadups (op0, op1));
              return;
              }
  
        {
          op0 = gen_lowpart (V4SFmode, op0);
          op1 = gen_lowpart (V4SFmode, op1);
-         emit_insn (gen_sse_movups (op0, op1));
+         emit_insn (gen_sse_storeups (op0, op1));
          return;
        }
  
          {
          op0 = gen_lowpart (V16QImode, op0);
          op1 = gen_lowpart (V16QImode, op1);
-         emit_insn (gen_sse2_movdqu (op0, op1));
+         emit_insn (gen_sse2_storedqu (op0, op1));
          return;
        }
  
            {
              op0 = gen_lowpart (V2DFmode, op0);
              op1 = gen_lowpart (V2DFmode, op1);
-             emit_insn (gen_sse2_movupd (op0, op1));
+             emit_insn (gen_sse2_storeupd (op0, op1));
            }
          else
            {
          if (TARGET_SSE_UNALIGNED_STORE_OPTIMAL)
            {
              op0 = gen_lowpart (V4SFmode, op0);
-             emit_insn (gen_sse_movups (op0, op1));
+             emit_insn (gen_sse_storeups (op0, op1));
            }
          else
            {
@@@ -23270,7 -23394,6 +23394,6 @@@ ix86_init_machine_status (void
  
    f = ggc_alloc_cleared_machine_function ();
    f->use_fast_prologue_epilogue_nregs = -1;
-   f->tls_descriptor_call_expanded_p = 0;
    f->call_abi = ix86_abi;
  
    return f;
@@@ -23289,9 -23412,6 +23412,6 @@@ assign_386_stack_local (enum machine_mo
  
    gcc_assert (n < MAX_386_STACK_LOCALS);
  
-   /* Virtual slot is valid only before vregs are instantiated.  */
-   gcc_assert ((n == SLOT_VIRTUAL) == !virtuals_instantiated);
    for (s = ix86_stack_locals; s; s = s->next)
      if (s->mode == mode && s->n == n)
        return validize_mem (copy_rtx (s->rtl));
    ix86_stack_locals = s;
    return validize_mem (s->rtl);
  }
+ static void
+ ix86_instantiate_decls (void)
+ {
+   struct stack_local_entry *s;
+   for (s = ix86_stack_locals; s; s = s->next)
+     if (s->rtl != NULL_RTX)
+       instantiate_decl_rtl (s->rtl);
+ }
  \f
  /* Calculate the length of the memory address in the instruction encoding.
     Includes addr32 prefix, does not include the one-byte modrm, opcode,
-    or other prefixes.  */
+    or other prefixes.  We never generate addr32 prefix for LEA insn.  */
  
  int
- memory_address_length (rtx addr)
+ memory_address_length (rtx addr, bool lea)
  {
    struct ix86_address parts;
    rtx base, index, disp;
    ok = ix86_decompose_address (addr, &parts);
    gcc_assert (ok);
  
-   if (parts.base && GET_CODE (parts.base) == SUBREG)
-     parts.base = SUBREG_REG (parts.base);
-   if (parts.index && GET_CODE (parts.index) == SUBREG)
-     parts.index = SUBREG_REG (parts.index);
+   len = (parts.seg == SEG_DEFAULT) ? 0 : 1;
+   /*  If this is not LEA instruction, add the length of addr32 prefix.  */
+   if (TARGET_64BIT && !lea
+       && (SImode_address_operand (addr, VOIDmode)
+         || (parts.base && GET_MODE (parts.base) == SImode)
+         || (parts.index && GET_MODE (parts.index) == SImode)))
+     len++;
  
    base = parts.base;
    index = parts.index;
    disp = parts.disp;
  
-   /* Add length of addr32 prefix.  */
-   len = (GET_CODE (addr) == ZERO_EXTEND
-        || GET_CODE (addr) == AND);
+   if (base && GET_CODE (base) == SUBREG)
+     base = SUBREG_REG (base);
+   if (index && GET_CODE (index) == SUBREG)
+     index = SUBREG_REG (index);
+   gcc_assert (base == NULL_RTX || REG_P (base));
+   gcc_assert (index == NULL_RTX || REG_P (index));
  
    /* Rule of thumb:
         - esp as the base always wants an index,
        /* esp (for its index) and ebp (for its displacement) need
         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;
+       if (base == arg_pointer_rtx
+         || base == frame_pointer_rtx
+         || REGNO (base) == SP_REG
+         || REGNO (base) == BP_REG
+         || REGNO (base) == R12_REG
+         || REGNO (base) == R13_REG)
+       len++;
      }
  
    /* Direct Addressing.  In 64-bit mode mod 00 r/m 5
       by UNSPEC.  */
    else if (disp && !base && !index)
      {
-       len = 4;
+       len += 4;
        if (TARGET_64BIT)
        {
          rtx symbol = disp;
                  || (XINT (symbol, 1) != UNSPEC_GOTPCREL
                      && XINT (symbol, 1) != UNSPEC_PCREL
                      && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
-           len += 1;
+           len++;
        }
      }
    else
      {
        /* Find the length of the displacement constant.  */
        if (disp)
        {
          if (base && satisfies_constraint_K (disp))
-           len = 1;
+           len += 1;
          else
-           len = 4;
+           len += 4;
        }
        /* ebp always wants a displacement.  Similarly r13.  */
-       else if (base && REG_P (base)
-              && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
-       len = 1;
+       else if (base && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
+       len++;
  
        /* An index requires the two-byte modrm form....  */
        if (index
          /* ...like esp (or r12), which always wants an index.  */
          || base == arg_pointer_rtx
          || base == frame_pointer_rtx
-         || (base && 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;
+         || (base && (REGNO (base) == SP_REG || REGNO (base) == R12_REG)))
+       len++;
      }
  
    return len;
@@@ -23477,7 -23601,8 +23601,8 @@@ ix86_attr_length_immediate_default (rt
          case MODE_SI:
            len = 4;
            break;
-         /* Immediates for DImode instructions are encoded as 32bit sign extended values.  */
+         /* Immediates for DImode instructions are encoded
+            as 32bit sign extended values.  */
          case MODE_DI:
            len = 4;
            break;
        }
    return len;
  }
  /* Compute default value for "length_address" attribute.  */
  int
  ix86_attr_length_address_default (rtx insn)
        gcc_assert (GET_CODE (set) == 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);
+       return memory_address_length (addr, true);
      }
  
    extract_insn_cached (insn);
            if (*constraints == 'X')
              continue;
          }
-       return memory_address_length (XEXP (recog_data.operand[i], 0));
+       return memory_address_length (XEXP (recog_data.operand[i], 0), false);
        }
    return 0;
  }
@@@ -24368,7 -24487,7 +24487,7 @@@ ix86_static_chain (const_tree fndecl, b
  
        fntype = TREE_TYPE (fndecl);
        ccvt = ix86_get_callcvt (fntype);
-       if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
+       if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
        {
          /* Fastcall functions use ecx/edx for arguments, which leaves
             us with EAX for the static chain.
             leaves us with EAX for the static chain.  */
          regno = AX_REG;
        }
+       else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
+       {
+         /* Thiscall functions use ecx for arguments, which leaves
+            us with EAX and EDX for the static chain.
+            We are using for abi-compatibility EAX.  */
+         regno = AX_REG;
+       }
        else if (ix86_function_regparm (fntype, fndecl) == 3)
        {
          /* For regparm 3, we have no free call-clobbered registers in
@@@ -25999,9 -26125,9 +26125,9 @@@ static const struct builtin_descriptio
    { OPTION_MASK_ISA_3DNOW, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID },
  
    /* SSE */
-   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
+   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_storeups, "__builtin_ia32_storeups", IX86_BUILTIN_STOREUPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
    { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movntv4sf, "__builtin_ia32_movntps", IX86_BUILTIN_MOVNTPS, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V4SF },
-   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_movups, "__builtin_ia32_loadups", IX86_BUILTIN_LOADUPS, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT },
+   { OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadups, "__builtin_ia32_loadups", IX86_BUILTIN_LOADUPS, UNKNOWN, (int) V4SF_FTYPE_PCFLOAT },
  
    { OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadhps_exp, "__builtin_ia32_loadhps", IX86_BUILTIN_LOADHPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_PCV2SF },
    { OPTION_MASK_ISA_SSE, CODE_FOR_sse_loadlps_exp, "__builtin_ia32_loadlps", IX86_BUILTIN_LOADLPS, UNKNOWN, (int) V4SF_FTYPE_V4SF_PCV2SF },
    /* SSE2 */
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_lfence, "__builtin_ia32_lfence", IX86_BUILTIN_LFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_mfence, 0, IX86_BUILTIN_MFENCE, UNKNOWN, (int) VOID_FTYPE_VOID },
-   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movupd, "__builtin_ia32_storeupd", IX86_BUILTIN_STOREUPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
-   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
+   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storeupd, "__builtin_ia32_storeupd", IX86_BUILTIN_STOREUPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
+   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_storedqu, "__builtin_ia32_storedqu", IX86_BUILTIN_STOREDQU, UNKNOWN, (int) VOID_FTYPE_PCHAR_V16QI },
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2df, "__builtin_ia32_movntpd", IX86_BUILTIN_MOVNTPD, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V2DF },
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntv2di, "__builtin_ia32_movntdq", IX86_BUILTIN_MOVNTDQ, UNKNOWN, (int) VOID_FTYPE_PV2DI_V2DI },
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movntisi, "__builtin_ia32_movnti", IX86_BUILTIN_MOVNTI, UNKNOWN, (int) VOID_FTYPE_PINT_INT },
    { OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_64BIT, CODE_FOR_sse2_movntidi, "__builtin_ia32_movnti64", IX86_BUILTIN_MOVNTI64, UNKNOWN, (int) VOID_FTYPE_PLONGLONG_LONGLONG },
-   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
-   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movdqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
+   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadupd, "__builtin_ia32_loadupd", IX86_BUILTIN_LOADUPD, UNKNOWN, (int) V2DF_FTYPE_PCDOUBLE },
+   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loaddqu, "__builtin_ia32_loaddqu", IX86_BUILTIN_LOADDQU, UNKNOWN, (int) V16QI_FTYPE_PCCHAR },
  
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadhpd_exp, "__builtin_ia32_loadhpd", IX86_BUILTIN_LOADHPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
    { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_loadlpd_exp, "__builtin_ia32_loadlpd", IX86_BUILTIN_LOADLPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_PCDOUBLE },
    { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastf128_v4df, "__builtin_ia32_vbroadcastf128_pd256", IX86_BUILTIN_VBROADCASTPD256, UNKNOWN, (int) V4DF_FTYPE_PCV2DF },
    { OPTION_MASK_ISA_AVX, CODE_FOR_avx_vbroadcastf128_v8sf, "__builtin_ia32_vbroadcastf128_ps256", IX86_BUILTIN_VBROADCASTPS256, UNKNOWN, (int) V8SF_FTYPE_PCV4SF },
  
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movupd256, "__builtin_ia32_loadupd256", IX86_BUILTIN_LOADUPD256, UNKNOWN, (int) V4DF_FTYPE_PCDOUBLE },
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movups256, "__builtin_ia32_loadups256", IX86_BUILTIN_LOADUPS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT },
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movupd256, "__builtin_ia32_storeupd256", IX86_BUILTIN_STOREUPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movups256, "__builtin_ia32_storeups256", IX86_BUILTIN_STOREUPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movdqu256, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
-   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movdqu256, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loadupd256, "__builtin_ia32_loadupd256", IX86_BUILTIN_LOADUPD256, UNKNOWN, (int) V4DF_FTYPE_PCDOUBLE },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loadups256, "__builtin_ia32_loadups256", IX86_BUILTIN_LOADUPS256, UNKNOWN, (int) V8SF_FTYPE_PCFLOAT },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeupd256, "__builtin_ia32_storeupd256", IX86_BUILTIN_STOREUPD256, UNKNOWN, (int) VOID_FTYPE_PDOUBLE_V4DF },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storeups256, "__builtin_ia32_storeups256", IX86_BUILTIN_STOREUPS256, UNKNOWN, (int) VOID_FTYPE_PFLOAT_V8SF },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_loaddqu256, "__builtin_ia32_loaddqu256", IX86_BUILTIN_LOADDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
+   { OPTION_MASK_ISA_AVX, CODE_FOR_avx_storedqu256, "__builtin_ia32_storedqu256", IX86_BUILTIN_STOREDQU256, UNKNOWN, (int) VOID_FTYPE_PCHAR_V32QI },
    { OPTION_MASK_ISA_AVX, CODE_FOR_avx_lddqu256, "__builtin_ia32_lddqu256", IX86_BUILTIN_LDDQU256, UNKNOWN, (int) V32QI_FTYPE_PCCHAR },
  
    { OPTION_MASK_ISA_AVX, CODE_FOR_avx_movntv4di, "__builtin_ia32_movntdq256", IX86_BUILTIN_MOVNTDQ256, UNKNOWN, (int) VOID_FTYPE_PV4DI_V4DI },
@@@ -29364,13 -29490,13 +29490,13 @@@ ix86_expand_builtin (tree exp, rtx targ
  
      case IX86_BUILTIN_LDMXCSR:
        op0 = expand_normal (CALL_EXPR_ARG (exp, 0));
-       target = assign_386_stack_local (SImode, SLOT_VIRTUAL);
+       target = assign_386_stack_local (SImode, SLOT_TEMP);
        emit_move_insn (target, op0);
        emit_insn (gen_sse_ldmxcsr (target));
        return 0;
  
      case IX86_BUILTIN_STMXCSR:
-       target = assign_386_stack_local (SImode, SLOT_VIRTUAL);
+       target = assign_386_stack_local (SImode, SLOT_TEMP);
        emit_insn (gen_sse_stmxcsr (target));
        return copy_to_mode_reg (SImode, target);
  
@@@ -31496,6 -31622,13 +31622,13 @@@ ix86_rtx_costs (rtx x, int code, int ou
        {
          if (CONST_INT_P (XEXP (x, 1)))
            *total = cost->shift_const;
+         else if (GET_CODE (XEXP (x, 1)) == SUBREG
+                  && GET_CODE (XEXP (XEXP (x, 1), 0)) == AND)
+           {
+             /* Return the cost after shift-and truncation.  */
+             *total = cost->shift_var;
+             return true;
+           }
          else
            *total = cost->shift_var;
        }
@@@ -32165,8 -32298,10 +32298,10 @@@ x86_output_mi_thunk (FILE *file
    else
      {
        unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (function));
-       if ((ccvt & (IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL)) != 0)
+       if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
        tmp_regno = AX_REG;
+       else if ((ccvt & IX86_CALLCVT_THISCALL) != 0)
+       tmp_regno = DX_REG;
        else
        tmp_regno = CX_REG;
      }
@@@ -34794,13 -34929,9 +34929,13 @@@ ix86_mangle_type (const_tree type
  static tree ATTRIBUTE_UNUSED
  ix86_stack_protect_fail (void)
  {
 +#if 0  /*  Still broken -- affects FreeBSD too  */
    return TARGET_64BIT
         ? default_external_stack_protect_fail ()
         : default_hidden_stack_protect_fail ();
 +#else
 +  return default_external_stack_protect_fail ();
 +#endif
  }
  
  /* Select a format to encode pointers in exception handling data.  CODE
@@@ -38873,6 -39004,9 +39008,9 @@@ ix86_autovectorize_vector_sizes (void
  #undef TARGET_PROMOTE_FUNCTION_MODE
  #define TARGET_PROMOTE_FUNCTION_MODE ix86_promote_function_mode
  
+ #undef TARGET_INSTANTIATE_DECLS
+ #define TARGET_INSTANTIATE_DECLS ix86_instantiate_decls
  #undef TARGET_SECONDARY_RELOAD
  #define TARGET_SECONDARY_RELOAD ix86_secondary_reload
  
@@@ -267,6 -267,7 +267,7 @@@ static const char *compare_debug_dump_o
  static const char *compare_debug_self_opt_spec_function (int, const char **);
  static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
  static const char *pass_through_libs_spec_func (int, const char **);
+ static char *convert_white_space (char *);
  \f
  /* The Specs Language
  
@@@ -1153,6 -1154,11 +1154,11 @@@ static const char *multilib_dir
     set_multilib_dir based on the compilation options.  */
  
  static const char *multilib_os_dir;
+ /* Subdirectory to use for locating libraries in multiarch conventions.  Set by
+    set_multilib_dir based on the compilation options.  */
+ static const char *multiarch_dir;
  \f
  /* Structure to keep track of the specs that have been defined so far.
     These are accessed using %(specname) in a compiler or link
@@@ -2078,6 -2084,7 +2084,7 @@@ for_each_path (const struct path_prefi
    struct prefix_list *pl;
    const char *multi_dir = NULL;
    const char *multi_os_dir = NULL;
+   const char *multiarch_suffix = NULL;
    const char *multi_suffix;
    const char *just_multi_suffix;
    char *path = NULL;
      }
    if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
      multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+   if (multiarch_dir)
+     multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
  
    while (1)
      {
        size_t multi_dir_len = 0;
        size_t multi_os_dir_len = 0;
+       size_t multiarch_len = 0;
        size_t suffix_len;
        size_t just_suffix_len;
        size_t len;
        multi_dir_len = strlen (multi_dir);
        if (multi_os_dir)
        multi_os_dir_len = strlen (multi_os_dir);
+       if (multiarch_suffix)
+       multiarch_len = strlen (multiarch_suffix);
        suffix_len = strlen (multi_suffix);
        just_suffix_len = strlen (just_multi_suffix);
  
        if (path == NULL)
        {
          len = paths->max_len + extra_space + 1;
-         if (suffix_len > multi_os_dir_len)
-           len += suffix_len;
-         else
-           len += multi_os_dir_len;
+         len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
          path = XNEWVEC (char, len);
        }
  
          len = strlen (pl->prefix);
          memcpy (path, pl->prefix, len);
  
 +#if 0 /* MACHINE/VERSION isn't used anywhere DragonFly */
          /* Look first in MACHINE/VERSION subdirectory.  */
          if (!skip_multi_dir)
            {
              if (ret)
                break;
            }
 +#endif
  
          /* Some paths are tried with just the machine (ie. target)
             subdir.  This is used for finding as, ld, etc.  */
                break;
            }
  
+         /* Now try the multiarch path.  */
+         if (!skip_multi_dir
+             && !pl->require_machine_suffix && multiarch_dir)
+           {
+             memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+             ret = callback (path, callback_info);
+             if (ret)
+               break;
+           }
          /* Now try the base path.  */
          if (!pl->require_machine_suffix
              && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
@@@ -2972,6 -2989,9 +2991,9 @@@ display_help (void
    fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
    fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
    fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
+   fputs (_("\
+   -print-multiarch         Display the target's normalized GNU triplet, used as\n\
+                            a component in the library path\n"), stdout);
    fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
    fputs (_("\
    -print-multi-lib         Display the mapping between command line options and\n\
@@@ -3246,6 -3266,7 +3268,7 @@@ driver_handle_option (struct gcc_option
      case OPT_print_multi_directory:
      case OPT_print_sysroot:
      case OPT_print_multi_os_directory:
+     case OPT_print_multiarch:
      case OPT_print_sysroot_headers_suffix:
      case OPT_time:
      case OPT_wrapper:
@@@ -3608,7 -3629,6 +3631,7 @@@ process_command (unsigned int decoded_o
    /* FIXME: make_relative_prefix doesn't yet work for VMS.  */
    if (!gcc_exec_prefix)
      {
 +#if 0  /* Never use relative prefix (not bootstrapped) */
        gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
                                             standard_bindir_prefix,
                                             standard_exec_prefix);
                                             standard_libexec_prefix);
        if (gcc_exec_prefix)
        xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
 +#endif
      }
    else
      {
            len -= sizeof ("/lib/gcc/") - 1;
        }
  
 +#if 0  /* Bad Paths */
        set_std_prefix (gcc_exec_prefix, len);
        add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
                  PREFIX_PRIORITY_LAST, 0, 0);
        add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
                  PREFIX_PRIORITY_LAST, 0, 0);
 +#endif
      }
  
    /* COMPILER_PATH and LIBRARY_PATH have values
    if (!gcc_exec_prefix)
      {
  #ifndef OS2
 +      add_prefix (&exec_prefixes, standard_libexec_prefix, NULL,
 +                PREFIX_PRIORITY_LAST, 0, 0);
 +#if 0  /* Bad paths */
        add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
                  PREFIX_PRIORITY_LAST, 1, 0);
        add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
        add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
                  PREFIX_PRIORITY_LAST, 2, 0);
  #endif
 +#endif
 +#if 0  /* Bad paths */
        add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
                  PREFIX_PRIORITY_LAST, 1, 0);
 +#endif
      }
  
    gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
              spec_machine, dir_separator_str,
              spec_version, dir_separator_str, tooldir_prefix, NULL);
  
 +#if 0  /* Bad paths */
    add_prefix (&exec_prefixes,
              concat (tooldir_prefix, "bin", dir_separator_str, NULL),
              "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
    add_prefix (&startfile_prefixes,
              concat (tooldir_prefix, "lib", dir_separator_str, NULL),
              "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
 +#endif
  
  #if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
    /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
@@@ -4910,6 -4919,15 +4933,15 @@@ do_spec_1 (const char *spec, int inswit
                  do_spec_1 (" ", 0, NULL);
                }
  
+             if (multiarch_dir)
+               {
+                 do_spec_1 ("-imultiarch", 1, NULL);
+                 /* Make this a separate argument.  */
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (multiarch_dir, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
+               }
              if (gcc_exec_prefix)
                {
                  do_spec_1 ("-iprefix", 1, NULL);
@@@ -6489,6 -6507,7 +6521,7 @@@ main (int argc, char **argv
                                    X_OK, false);
    if (lto_wrapper_file)
      {
+       lto_wrapper_file = convert_white_space (lto_wrapper_file);
        lto_wrapper_spec = lto_wrapper_file;
        obstack_init (&collect_obstack);
        obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
  
    if (print_search_dirs)
      {
 -      printf (_("install: %s%s\n"),
 -            gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
 -            gcc_exec_prefix ? "" : machine_suffix);
 +      printf (_("install: %s\n"), STD_EXEC_PATH);
        printf (_("programs: %s\n"),
              build_search_list (&exec_prefixes, "", false, false));
        printf (_("libraries: %s\n"),
        return (0);
      }
  
+   if (print_multiarch)
+     {
+       if (multiarch_dir == NULL)
+       printf ("\n");
+       else
+       printf ("%s\n", multiarch_dir);
+       return (0);
+     }
    if (print_sysroot)
      {
        if (target_system_root)
@@@ -6888,12 -6918,13 +6930,13 @@@ warranty; not even for MERCHANTABILITY 
                              + strlen (fuse_linker_plugin), 0))
  #endif
            {
-             linker_plugin_file_spec = find_a_file (&exec_prefixes,
-                                                    LTOPLUGINSONAME, R_OK,
-                                                    false);
-             if (!linker_plugin_file_spec)
+             char *temp_spec = find_a_file (&exec_prefixes,
+                                            LTOPLUGINSONAME, R_OK,
+                                            false);
+             if (!temp_spec)
                fatal_error ("-fuse-linker-plugin, but %s not found",
                             LTOPLUGINSONAME);
+             linker_plugin_file_spec = convert_white_space (temp_spec);
            }
  #endif
          lto_gcc_spec = argv[0];
@@@ -7314,7 -7345,9 +7357,9 @@@ default_arg (const char *p, int len
     options are present, then we will ignore this completely. Passing
     that, gcc will consider each multilib_select in turn using the same
     rules for matching the options. If a match is found, that subdirectory
-    will be used.  */
+    will be used.
+    A subdirectory name is optionally followed by a colon and the corresponding
+    multiarch name.  */
  
  static void
  set_multilib_dir (void)
            q++;
          if (q < end)
            {
-             char *new_multilib_os_dir = XNEWVEC (char, end - q);
-             memcpy (new_multilib_os_dir, q + 1, end - q - 1);
-             new_multilib_os_dir[end - q - 1] = '\0';
-             multilib_os_dir = new_multilib_os_dir;
+             const char *q2 = q + 1, *ml_end = end;
+             char *new_multilib_os_dir;
+             while (q2 < end && *q2 != ':')
+               q2++;
+             if (*q2 == ':')
+               ml_end = q2;
+             new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+             memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+             new_multilib_os_dir[ml_end - q - 1] = '\0';
+             multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+             if (q2 < end && *q2 == ':')
+               {
+                 char *new_multiarch_dir = XNEWVEC (char, end - q2);
+                 memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+                 new_multiarch_dir[end - q2 - 1] = '\0';
+                 multiarch_dir = new_multiarch_dir;
+               }
              break;
            }
        }
@@@ -7589,9 -7637,10 +7649,10 @@@ print_multilib_info (void
        }
  
        /* When --disable-multilib was used but target defines
-        MULTILIB_OSDIRNAMES, entries starting with .: are there just
-        to find multilib_os_dir, so skip them from output.  */
-       if (this_path[0] == '.' && this_path[1] == ':')
+        MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+          with .:: for multiarch configurations) are there just to find
+          multilib_os_dir, so skip them from output.  */
+       if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
        skip = 1;
  
        /* Check for matches with the multilib_exclusions. We don't bother
@@@ -8330,3 -8379,51 +8391,51 @@@ pass_through_libs_spec_func (int argc, 
      }
    return prepended;
  }
+ /* Insert backslash before spaces in ORIG (usually a file path), to 
+    avoid being broken by spec parser.
+    This function is needed as do_spec_1 treats white space (' ' and '\t')
+    as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+    the file name should be treated as a single argument rather than being
+    broken into multiple. Solution is to insert '\\' before the space in a 
+    file name.
+    
+    This function converts and only converts all occurrence of ' ' 
+    to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
+    "a b"  -> "a\\ b"
+    "a  b" -> "a\\ \\ b"
+    "a\tb" -> "a\\\tb"
+    "a\\ b" -> "a\\\\ b"
+    orig: input null-terminating string that was allocated by xalloc. The
+    memory it points to might be freed in this function. Behavior undefined
+    if ORIG wasn't xalloced or was freed already at entry.
+    Return: ORIG if no conversion needed. Otherwise a newly allocated string
+    that was converted from ORIG.  */
+ static char *
+ convert_white_space (char *orig)
+ {
+   int len, number_of_space = 0;
+   for (len = 0; orig[len]; len++)
+     if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
+   if (number_of_space)
+     {
+       char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+       int j, k;
+       for (j = 0, k = 0; j <= len; j++, k++)
+       {
+         if (orig[j] == ' ' || orig[j] == '\t')
+           new_spec[k++] = '\\';
+         new_spec[k] = orig[j];
+       }
+       free (orig);
+       return new_spec;
+   }
+   else
+     return orig;
+ }
@@@ -2983,10 -2983,15 +2983,15 @@@ declare_return_variable (copy_body_dat
        if (gimple_in_ssa_p (id->src_cfun))
        add_referenced_var (temp);
        insert_decl_map (id, result, temp);
-       /* When RESULT_DECL is in SSA form, we need to use it's default_def
-        SSA_NAME.  */
-       if (gimple_in_ssa_p (id->src_cfun) && gimple_default_def (id->src_cfun, result))
-         temp = remap_ssa_name (gimple_default_def (id->src_cfun, result), id);
+       /* When RESULT_DECL is in SSA form, we need to remap and initialize
+        it's default_def SSA_NAME.  */
+       if (gimple_in_ssa_p (id->src_cfun)
+         && is_gimple_reg (result))
+       {
+         temp = make_ssa_name (temp, NULL);
+         insert_decl_map (id, gimple_default_def (id->src_cfun, result),
+                          temp);
+       }
        insert_init_stmt (id, entry_bb, gimple_build_assign (temp, var));
      }
    else
@@@ -3836,6 -3841,12 +3841,12 @@@ expand_call_inline (basic_block bb, gim
        goto egress;
  
        if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
+           /* For extern inline functions that get redefined we always
+            silently ignored always_inline flag. Better behaviour would
+            be to be able to keep both bodies and use extern inline body
+            for inlining, but we can't do that because frontends overwrite
+            the body.  */
+         && !cg_edge->callee->local.redefined_extern_inline
          /* Avoid warnings during early inline pass. */
          && cgraph_global_info_ready
          /* PR 20090218-1_0.c. Body can be provided by another module. */
               /* Do not warn about not inlined recursive calls.  */
               && !cgraph_edge_recursive_p (cg_edge)
               /* Avoid warnings during early inline pass. */
 -             && cgraph_global_info_ready)
 +             && cgraph_global_info_ready
 +             && reason != CIF_UNLIKELY_CALL)
        {
          warning (OPT_Winline, "inlining failed in call to %q+F: %s",
                   fn, _(cgraph_inline_failed_string (reason)));
@@@ -33,7 -33,7 +33,7 @@@
  
  #include "tconfig.h"
  #include "tsystem.h"
- #ifndef inhibit_libc
+ #if !defined(inhibit_libc) && !defined(__OpenBSD__)
  #include <elf.h>              /* Get DT_CONFIG.  */
  #endif
  #include "coretypes.h"
  #endif
  
  #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
 -    && defined(__FreeBSD__) && __FreeBSD__ >= 7
 +    && defined(TARGET_DL_ITERATE_PHDR) \
 +    && (defined(__FreeBSD__) || defined(__DragonFly__))
  # define ElfW __ElfN
  # define USE_PT_GNU_EH_FRAME
  #endif
  
+ #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
+     && defined(__OpenBSD__)
+ # define ElfW(type) Elf_##type
+ # define USE_PT_GNU_EH_FRAME
+ #endif
 +#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
 +    && defined(TARGET_DL_ITERATE_PHDR) \
 +    && (defined(__OpenBSD__) || defined(__NetBSD__))
 +# define ElfW(n) Elf_##n
 +# define USE_PT_GNU_EH_FRAME
 +#endif
 +
  #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
      && defined(TARGET_DL_ITERATE_PHDR) \
      && defined(__sun__) && defined(__svr4__)