re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / expr.c
index 930549f8a461a15438201696885a09f30e3e2f28..408ae1a7a1f66349ce74e44cc82404526556348b 100644 (file)
@@ -1,5 +1,5 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
-   Copyright (C) 1988-2014 Free Software Foundation, Inc.
+   Copyright (C) 1988-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,9 +21,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "machmode.h"
 #include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "stringpool.h"
 #include "stor-layout.h"
 #include "attribs.h"
@@ -32,13 +34,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "regs.h"
 #include "hard-reg-set.h"
 #include "except.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "input.h"
 #include "function.h"
 #include "insn-config.h"
 #include "insn-attr.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
 /* Include expr.h after insn-config.h so we get HAVE_conditional_move.  */
 #include "expr.h"
 #include "insn-codes.h"
@@ -59,12 +63,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "gimple-ssa.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
 #include "cgraph.h"
 #include "tree-ssanames.h"
 #include "target.h"
@@ -81,14 +81,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "tree-chkp.h"
 #include "rtl-chkp.h"
-
-#ifndef STACK_PUSH_CODE
-#ifdef STACK_GROWS_DOWNWARD
-#define STACK_PUSH_CODE PRE_DEC
-#else
-#define STACK_PUSH_CODE PRE_INC
-#endif
-#endif
+#include "ccmp.h"
 
 
 /* If this is nonzero, we do not bother generating VOLATILE
@@ -159,8 +152,6 @@ static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT,
 static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree, const_tree);
 
 static int is_aligning_offset (const_tree, const_tree);
-static void expand_operands (tree, tree, rtx, rtx*, rtx*,
-                            enum expand_modifier);
 static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
 static rtx do_store_flag (sepops, rtx, machine_mode);
 #ifdef PUSH_ROUNDING
@@ -168,6 +159,8 @@ static void emit_single_push_insn (machine_mode, rtx, tree);
 #endif
 static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
 static rtx const_vector_from_tree (tree);
+static tree tree_expr_size (const_tree);
+static HOST_WIDE_INT int_expr_size (tree);
 
 \f
 /* This is run to set up which modes can be used
@@ -186,15 +179,15 @@ init_expr_target (void)
   /* Try indexing by frame ptr and try by stack ptr.
      It is known that on the Convex the stack ptr isn't a valid index.
      With luck, one or the other is valid on any machine.  */
-  mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
-  mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
+  mem = gen_rtx_MEM (word_mode, stack_pointer_rtx);
+  mem1 = gen_rtx_MEM (word_mode, frame_pointer_rtx);
 
   /* A scratch register we can modify in-place below to avoid
      useless RTL allocations.  */
-  reg = gen_rtx_REG (VOIDmode, -1);
+  reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
 
   insn = rtx_alloc (INSN);
-  pat = gen_rtx_SET (VOIDmode, NULL_RTX, NULL_RTX);
+  pat = gen_rtx_SET (NULL_RTX, NULL_RTX);
   PATTERN (insn) = pat;
 
   for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
@@ -205,7 +198,6 @@ init_expr_target (void)
       direct_load[(int) mode] = direct_store[(int) mode] = 0;
       PUT_MODE (mem, mode);
       PUT_MODE (mem1, mode);
-      PUT_MODE (reg, mode);
 
       /* See if there is some register that can be used in this mode and
         directly loaded or stored from memory.  */
@@ -218,7 +210,7 @@ init_expr_target (void)
            if (! HARD_REGNO_MODE_OK (regno, mode))
              continue;
 
-           SET_REGNO (reg, regno);
+           set_mode_and_regno (reg, mode, regno);
 
            SET_SRC (pat) = mem;
            SET_DEST (pat) = reg;
@@ -242,7 +234,7 @@ init_expr_target (void)
          }
     }
 
-  mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
+  mem = gen_rtx_MEM (VOIDmode, gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1));
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
@@ -854,11 +846,10 @@ move_by_pieces (rtx to, rtx from, unsigned HOST_WIDE_INT len,
       to_addr = NULL_RTX;
       data.to = NULL_RTX;
       data.autinc_to = 1;
-#ifdef STACK_GROWS_DOWNWARD
-      data.reverse = 1;
-#else
-      data.reverse = 0;
-#endif
+      if (STACK_GROWS_DOWNWARD)
+       data.reverse = 1;
+      else
+       data.reverse = 0;
     }
   data.to_addr = to_addr;
   data.from = from;
@@ -1501,10 +1492,8 @@ void
 move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
 {
   int i;
-#ifdef HAVE_load_multiple
   rtx pat;
   rtx_insn *last;
-#endif
 
   if (nregs == 0)
     return;
@@ -1513,7 +1502,6 @@ move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
     x = validize_mem (force_const_mem (mode, x));
 
   /* See if the machine can do this with a load multiple insn.  */
-#ifdef HAVE_load_multiple
   if (HAVE_load_multiple)
     {
       last = get_last_insn ();
@@ -1527,7 +1515,6 @@ move_block_to_reg (int regno, rtx x, int nregs, machine_mode mode)
       else
        delete_insns_since (last);
     }
-#endif
 
   for (i = 0; i < nregs; i++)
     emit_move_insn (gen_rtx_REG (word_mode, regno + i),
@@ -1546,7 +1533,6 @@ move_block_from_reg (int regno, rtx x, int nregs)
     return;
 
   /* See if the machine can do this with a store multiple insn.  */
-#ifdef HAVE_store_multiple
   if (HAVE_store_multiple)
     {
       rtx_insn *last = get_last_insn ();
@@ -1560,7 +1546,6 @@ move_block_from_reg (int regno, rtx x, int nregs)
       else
        delete_insns_since (last);
     }
-#endif
 
   for (i = 0; i < nregs; i++)
     {
@@ -2417,7 +2402,6 @@ get_def_for_expr (tree name, enum tree_code code)
   return def_stmt;
 }
 
-#ifdef HAVE_conditional_move
 /* Return the defining gimple statement for SSA_NAME NAME if it is an
    assigment and the class of the expresion on the RHS is CLASS.  Return
    NULL otherwise.  */
@@ -2437,7 +2421,6 @@ get_def_for_expr_class (tree name, enum tree_code_class tclass)
 
   return def_stmt;
 }
-#endif
 \f
 
 /* Determine whether the LEN bytes generated by CONSTFUN can be
@@ -3035,7 +3018,7 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
         where the natural size of floating-point regs is 32-bit.  */
       || (REG_P (cplx)
          && REGNO (cplx) < FIRST_PSEUDO_REGISTER
-         && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
+         && REG_NREGS (cplx) % 2 == 0))
     {
       rtx part = simplify_gen_subreg (imode, cplx, cmode,
                                      imag_p ? GET_MODE_SIZE (imode) : 0);
@@ -3100,7 +3083,7 @@ read_complex_part (rtx cplx, bool imag_p)
         where the natural size of floating-point regs is 32-bit.  */
       || (REG_P (cplx)
          && REGNO (cplx) < FIRST_PSEUDO_REGISTER
-         && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0))
+         && REG_NREGS (cplx) % 2 == 0))
     {
       rtx ret = simplify_gen_subreg (imode, cplx, cmode,
                                     imag_p ? GET_MODE_SIZE (imode) : 0);
@@ -3330,10 +3313,10 @@ emit_move_complex (machine_mode mode, rtx x, rtx y)
       && optab_handler (mov_optab, GET_MODE_INNER (mode)) != CODE_FOR_nothing
       && !(REG_P (x)
           && HARD_REGISTER_P (x)
-          && hard_regno_nregs[REGNO (x)][mode] == 1)
+          && REG_NREGS (x) == 1)
       && !(REG_P (y)
           && HARD_REGISTER_P (y)
-          && hard_regno_nregs[REGNO (y)][mode] == 1))
+          && REG_NREGS (y) == 1))
     try_int = false;
   /* Not possible if the values are inherently not adjacent.  */
   else if (GET_CODE (x) == CONCAT || GET_CODE (y) == CONCAT)
@@ -3636,7 +3619,7 @@ emit_move_insn (rtx x, rtx y)
 /* Generate the body of an instruction to copy Y into X.
    It may be a list of insns, if one insn isn't enough.  */
 
-rtx
+rtx_insn *
 gen_move_insn (rtx x, rtx y)
 {
   rtx_insn *seq;
@@ -3648,6 +3631,15 @@ gen_move_insn (rtx x, rtx y)
   return seq;
 }
 
+/* Same as above, but return rtx (used as a callback, which must have
+   prototype compatible with other functions returning rtx).  */
+
+rtx
+gen_move_insn_uncast (rtx x, rtx y)
+{
+  return gen_move_insn (x, y);
+}
+
 /* If Y is representable exactly in a narrower mode, and the target can
    perform the extension directly from constant or memory, then emit the
    move as an extension.  */
@@ -3768,11 +3760,7 @@ push_block (rtx size, int extra, int below)
       anti_adjust_stack (temp);
     }
 
-#ifndef STACK_GROWS_DOWNWARD
-  if (0)
-#else
-  if (1)
-#endif
+  if (STACK_GROWS_DOWNWARD)
     {
       temp = virtual_outgoing_args_rtx;
       if (extra != 0 && below)
@@ -3980,9 +3968,9 @@ fixup_args_size_notes (rtx_insn *prev, rtx_insn *last, int end_args_size)
        saw_unknown = true;
 
       add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size));
-#ifdef STACK_GROWS_DOWNWARD
-      this_delta = -(unsigned HOST_WIDE_INT) this_delta;
-#endif
+      if (STACK_GROWS_DOWNWARD)
+       this_delta = -(unsigned HOST_WIDE_INT) this_delta;
+
       args_size -= this_delta;
     }
 
@@ -4025,42 +4013,38 @@ emit_single_push_insn_1 (machine_mode mode, rtx x, tree type)
 
       emit_move_insn (stack_pointer_rtx,
                      expand_binop (Pmode,
-#ifdef STACK_GROWS_DOWNWARD
-                                   sub_optab,
-#else
-                                   add_optab,
-#endif
+                                   STACK_GROWS_DOWNWARD ? sub_optab
+                                   : add_optab,
                                    stack_pointer_rtx,
                                    gen_int_mode (rounded_size, Pmode),
                                    NULL_RTX, 0, OPTAB_LIB_WIDEN));
 
       offset = (HOST_WIDE_INT) padding_size;
-#ifdef STACK_GROWS_DOWNWARD
-      if (STACK_PUSH_CODE == POST_DEC)
+      if (STACK_GROWS_DOWNWARD && STACK_PUSH_CODE == POST_DEC)
        /* We have already decremented the stack pointer, so get the
           previous value.  */
        offset += (HOST_WIDE_INT) rounded_size;
-#else
-      if (STACK_PUSH_CODE == POST_INC)
+
+      if (!STACK_GROWS_DOWNWARD && STACK_PUSH_CODE == POST_INC)
        /* We have already incremented the stack pointer, so get the
           previous value.  */
        offset -= (HOST_WIDE_INT) rounded_size;
-#endif
+
       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
                                gen_int_mode (offset, Pmode));
     }
   else
     {
-#ifdef STACK_GROWS_DOWNWARD
-      /* ??? This seems wrong if STACK_PUSH_CODE == POST_DEC.  */
-      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               gen_int_mode (-(HOST_WIDE_INT) rounded_size,
-                                             Pmode));
-#else
-      /* ??? This seems wrong if STACK_PUSH_CODE == POST_INC.  */
-      dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
-                               gen_int_mode (rounded_size, Pmode));
-#endif
+      if (STACK_GROWS_DOWNWARD)
+       /* ??? This seems wrong if STACK_PUSH_CODE == POST_DEC.  */
+       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+                                 gen_int_mode (-(HOST_WIDE_INT) rounded_size,
+                                               Pmode));
+      else
+       /* ??? This seems wrong if STACK_PUSH_CODE == POST_INC.  */
+       dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+                                 gen_int_mode (rounded_size, Pmode));
+
       dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
     }
 
@@ -4105,12 +4089,35 @@ emit_single_push_insn (machine_mode mode, rtx x, tree type)
 }
 #endif
 
+/* If reading SIZE bytes from X will end up reading from
+   Y return the number of bytes that overlap.  Return -1
+   if there is no overlap or -2 if we can't determine
+   (for example when X and Y have different base registers).  */
+
+static int
+memory_load_overlap (rtx x, rtx y, HOST_WIDE_INT size)
+{
+  rtx tmp = plus_constant (Pmode, x, size);
+  rtx sub = simplify_gen_binary (MINUS, Pmode, tmp, y);
+
+  if (!CONST_INT_P (sub))
+    return -2;
+
+  HOST_WIDE_INT val = INTVAL (sub);
+
+  return IN_RANGE (val, 1, size) ? val : -1;
+}
+
 /* Generate code to push X onto the stack, assuming it has mode MODE and
    type TYPE.
    MODE is redundant except when X is a CONST_INT (since they don't
    carry mode info).
    SIZE is an rtx for the size of data to be copied (in bytes),
    needed only if X is BLKmode.
+   Return true if successful.  May return false if asked to push a
+   partial argument during a sibcall optimization (as specified by
+   SIBCALL_P) and the incoming and outgoing pointers cannot be shown
+   to not overlap.
 
    ALIGN (in bits) is maximum alignment we can assume.
 
@@ -4136,19 +4143,14 @@ emit_single_push_insn (machine_mode mode, rtx x, tree type)
    for arguments passed in registers.  If nonzero, it will be the number
    of bytes required.  */
 
-void
+bool
 emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
                unsigned int align, int partial, rtx reg, int extra,
                rtx args_addr, rtx args_so_far, int reg_parm_stack_space,
-               rtx alignment_pad)
+               rtx alignment_pad, bool sibcall_p)
 {
   rtx xinner;
-  enum direction stack_direction
-#ifdef STACK_GROWS_DOWNWARD
-    = downward;
-#else
-    = upward;
-#endif
+  enum direction stack_direction = STACK_GROWS_DOWNWARD ? downward : upward;
 
   /* Decide where to pad the argument: `downward' for below,
      `upward' for above, or `none' for don't pad it.
@@ -4163,6 +4165,10 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
 
   xinner = x;
 
+  int nregs = partial / UNITS_PER_WORD;
+  rtx *tmp_regs = NULL;
+  int overlapping = 0;
+
   if (mode == BLKmode
       || (STRICT_ALIGNMENT && align < GET_MODE_ALIGNMENT (mode)))
     {
@@ -4293,6 +4299,43 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
             PARM_BOUNDARY.  Assume the caller isn't lying.  */
          set_mem_align (target, align);
 
+         /* If part should go in registers and pushing to that part would
+            overwrite some of the values that need to go into regs, load the
+            overlapping values into temporary pseudos to be moved into the hard
+            regs at the end after the stack pushing has completed.
+            We cannot load them directly into the hard regs here because
+            they can be clobbered by the block move expansions.
+            See PR 65358.  */
+
+         if (partial > 0 && reg != 0 && mode == BLKmode
+             && GET_CODE (reg) != PARALLEL)
+           {
+             overlapping = memory_load_overlap (XEXP (x, 0), temp, partial);
+             if (overlapping > 0)
+               {
+                 gcc_assert (overlapping % UNITS_PER_WORD == 0);
+                 overlapping /= UNITS_PER_WORD;
+
+                 tmp_regs = XALLOCAVEC (rtx, overlapping);
+
+                 for (int i = 0; i < overlapping; i++)
+                   tmp_regs[i] = gen_reg_rtx (word_mode);
+
+                 for (int i = 0; i < overlapping; i++)
+                   emit_move_insn (tmp_regs[i],
+                                   operand_subword_force (target, i, mode));
+               }
+             else if (overlapping == -1)
+               overlapping = 0;
+             /* Could not determine whether there is overlap.
+                Fail the sibcall.  */
+             else
+               {
+                 overlapping = 0;
+                 if (sibcall_p)
+                   return false;
+               }
+           }
          emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
        }
     }
@@ -4347,12 +4390,13 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
         has a size a multiple of a word.  */
       for (i = size - 1; i >= not_stack; i--)
        if (i >= not_stack + offset)
-         emit_push_insn (operand_subword_force (x, i, mode),
+         if (!emit_push_insn (operand_subword_force (x, i, mode),
                          word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
                          0, args_addr,
                          GEN_INT (args_offset + ((i - not_stack + skip)
                                                  * UNITS_PER_WORD)),
-                         reg_parm_stack_space, alignment_pad);
+                         reg_parm_stack_space, alignment_pad, sibcall_p))
+           return false;
     }
   else
     {
@@ -4395,9 +4439,8 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
        }
     }
 
-  /* If part should go in registers, copy that part
-     into the appropriate registers.  Do this now, at the end,
-     since mem-to-mem copies above may do function calls.  */
+  /* Move the partial arguments into the registers and any overlapping
+     values that we moved into the pseudos in tmp_regs.  */
   if (partial > 0 && reg != 0)
     {
       /* Handle calls that pass values in multiple non-contiguous locations.
@@ -4405,9 +4448,15 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
       if (GET_CODE (reg) == PARALLEL)
        emit_group_load (reg, x, type, -1);
       else
-       {
+        {
          gcc_assert (partial % UNITS_PER_WORD == 0);
-         move_block_to_reg (REGNO (reg), x, partial / UNITS_PER_WORD, mode);
+         move_block_to_reg (REGNO (reg), x, nregs - overlapping, mode);
+
+         for (int i = 0; i < overlapping; i++)
+           emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg)
+                                                   + nregs - overlapping + i),
+                           tmp_regs[i]);
+
        }
     }
 
@@ -4416,6 +4465,8 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
 
   if (alignment_pad && args_addr == 0)
     anti_adjust_stack (alignment_pad);
+
+  return true;
 }
 \f
 /* Return X if X can be used as a subtarget in a sequence of arithmetic
@@ -4863,7 +4914,13 @@ expand_assignment (tree to, tree from, bool nontemporal)
          offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
          address_mode = get_address_mode (to_rtx);
          if (GET_MODE (offset_rtx) != address_mode)
-           offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
+           {
+               /* We cannot be sure that the RTL in offset_rtx is valid outside
+                  of a memory address context, so force it into a register
+                  before attempting to convert it to the desired mode.  */
+             offset_rtx = force_operand (offset_rtx, NULL_RTX);
+             offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
+           }
 
          /* If we have an expression in OFFSET_RTX and a non-zero
             byte offset in BITPOS, adding the byte offset before the
@@ -6629,11 +6686,12 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
          && mode != TYPE_MODE (TREE_TYPE (exp)))
        temp = convert_modes (mode, TYPE_MODE (TREE_TYPE (exp)), temp, 1);
 
-      /* If the modes of TEMP and TARGET are both BLKmode, both
-        must be in memory and BITPOS must be aligned on a byte
-        boundary.  If so, we simply do a block copy.  Likewise
-        for a BLKmode-like TARGET.  */
-      if (GET_MODE (temp) == BLKmode
+      /* If TEMP is not a PARALLEL (see below) and its mode and that of TARGET
+        are both BLKmode, both must be in memory and BITPOS must be aligned
+        on a byte boundary.  If so, we simply do a block copy.  Likewise for
+        a BLKmode-like TARGET.  */
+      if (GET_CODE (temp) != PARALLEL
+         && GET_MODE (temp) == BLKmode
          && (GET_MODE (target) == BLKmode
              || (MEM_P (target)
                  && GET_MODE_CLASS (GET_MODE (target)) == MODE_INT
@@ -6924,7 +6982,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   if (offset)
     {
       /* Avoid returning a negative bitpos as this may wreak havoc later.  */
-      if (wi::neg_p (bit_offset))
+      if (wi::neg_p (bit_offset) || !wi::fits_shwi_p (bit_offset))
         {
          offset_int mask = wi::mask <offset_int> (LOG2_BITS_PER_UNIT, false);
          offset_int tem = bit_offset.and_not (mask);
@@ -6952,139 +7010,6 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   return exp;
 }
 
-/* Return a tree of sizetype representing the size, in bytes, of the element
-   of EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
-
-tree
-array_ref_element_size (tree exp)
-{
-  tree aligned_size = TREE_OPERAND (exp, 3);
-  tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
-  location_t loc = EXPR_LOCATION (exp);
-
-  /* If a size was specified in the ARRAY_REF, it's the size measured
-     in alignment units of the element type.  So multiply by that value.  */
-  if (aligned_size)
-    {
-      /* ??? tree_ssa_useless_type_conversion will eliminate casts to
-        sizetype from another type of the same width and signedness.  */
-      if (TREE_TYPE (aligned_size) != sizetype)
-       aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
-      return size_binop_loc (loc, MULT_EXPR, aligned_size,
-                            size_int (TYPE_ALIGN_UNIT (elmt_type)));
-    }
-
-  /* Otherwise, take the size from that of the element type.  Substitute
-     any PLACEHOLDER_EXPR that we have.  */
-  else
-    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
-}
-
-/* Return a tree representing the lower bound of the array mentioned in
-   EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
-
-tree
-array_ref_low_bound (tree exp)
-{
-  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
-
-  /* If a lower bound is specified in EXP, use it.  */
-  if (TREE_OPERAND (exp, 2))
-    return TREE_OPERAND (exp, 2);
-
-  /* Otherwise, if there is a domain type and it has a lower bound, use it,
-     substituting for a PLACEHOLDER_EXPR as needed.  */
-  if (domain_type && TYPE_MIN_VALUE (domain_type))
-    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
-
-  /* Otherwise, return a zero of the appropriate type.  */
-  return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
-}
-
-/* Returns true if REF is an array reference to an array at the end of
-   a structure.  If this is the case, the array may be allocated larger
-   than its upper bound implies.  */
-
-bool
-array_at_struct_end_p (tree ref)
-{
-  if (TREE_CODE (ref) != ARRAY_REF
-      && TREE_CODE (ref) != ARRAY_RANGE_REF)
-    return false;
-
-  while (handled_component_p (ref))
-    {
-      /* If the reference chain contains a component reference to a
-         non-union type and there follows another field the reference
-        is not at the end of a structure.  */
-      if (TREE_CODE (ref) == COMPONENT_REF
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
-       {
-         tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
-         while (nextf && TREE_CODE (nextf) != FIELD_DECL)
-           nextf = DECL_CHAIN (nextf);
-         if (nextf)
-           return false;
-       }
-
-      ref = TREE_OPERAND (ref, 0);
-    }
-
-  /* If the reference is based on a declared entity, the size of the array
-     is constrained by its given domain.  */
-  if (DECL_P (ref))
-    return false;
-
-  return true;
-}
-
-/* Return a tree representing the upper bound of the array mentioned in
-   EXP, an ARRAY_REF or an ARRAY_RANGE_REF.  */
-
-tree
-array_ref_up_bound (tree exp)
-{
-  tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
-
-  /* If there is a domain type and it has an upper bound, use it, substituting
-     for a PLACEHOLDER_EXPR as needed.  */
-  if (domain_type && TYPE_MAX_VALUE (domain_type))
-    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
-
-  /* Otherwise fail.  */
-  return NULL_TREE;
-}
-
-/* Return a tree representing the offset, in bytes, of the field referenced
-   by EXP.  This does not include any offset in DECL_FIELD_BIT_OFFSET.  */
-
-tree
-component_ref_field_offset (tree exp)
-{
-  tree aligned_offset = TREE_OPERAND (exp, 2);
-  tree field = TREE_OPERAND (exp, 1);
-  location_t loc = EXPR_LOCATION (exp);
-
-  /* If an offset was specified in the COMPONENT_REF, it's the offset measured
-     in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT.  So multiply by that
-     value.  */
-  if (aligned_offset)
-    {
-      /* ??? tree_ssa_useless_type_conversion will eliminate casts to
-        sizetype from another type of the same width and signedness.  */
-      if (TREE_TYPE (aligned_offset) != sizetype)
-       aligned_offset = fold_convert_loc (loc, sizetype, aligned_offset);
-      return size_binop_loc (loc, MULT_EXPR, aligned_offset,
-                            size_int (DECL_OFFSET_ALIGN (field)
-                                      / BITS_PER_UNIT));
-    }
-
-  /* Otherwise, take the offset from that of the field.  Substitute
-     any PLACEHOLDER_EXPR that we have.  */
-  else
-    return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
-}
-
 /* Alignment in bits the TARGET of an assignment may be assumed to have.  */
 
 static unsigned HOST_WIDE_INT
@@ -7508,7 +7433,6 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp)
   return MAX (factor, talign);
 }
 \f
-#ifdef HAVE_conditional_move
 /* Convert the tree comparison code TCODE to the rtl one where the
    signedness is UNSIGNEDP.  */
 
@@ -7566,14 +7490,13 @@ convert_tree_comp_to_rtx (enum tree_code tcode, int unsignedp)
     }
   return code;
 }
-#endif
 
 /* Subroutine of expand_expr.  Expand the two operands of a binary
    expression EXP0 and EXP1 placing the results in OP0 and OP1.
    The value may be stored in TARGET if TARGET is nonzero.  The
    MODIFIER argument is as documented by expand_expr.  */
 
-static void
+void
 expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
                 enum expand_modifier modifier)
 {
@@ -7678,11 +7601,13 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
       break;
 
     case COMPOUND_LITERAL_EXPR:
-      /* Allow COMPOUND_LITERAL_EXPR in initializers, if e.g.
-        rtl_for_decl_init is called on DECL_INITIAL with
-        COMPOUNT_LITERAL_EXPRs in it, they aren't gimplified.  */
-      if (modifier == EXPAND_INITIALIZER
-         && COMPOUND_LITERAL_EXPR_DECL (exp))
+      /* Allow COMPOUND_LITERAL_EXPR in initializers or coming from
+        initializers, if e.g. rtl_for_decl_init is called on DECL_INITIAL
+        with COMPOUND_LITERAL_EXPRs in it, or ARRAY_REF on a const static
+        array with address of COMPOUND_LITERAL_EXPR in DECL_INITIAL;
+        the initializers aren't gimplified.  */
+      if (COMPOUND_LITERAL_EXPR_DECL (exp)
+         && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
        return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp),
                                        target, tmode, modifier, as);
       /* FALLTHRU */
@@ -8010,7 +7935,6 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
                              tree treeop1 ATTRIBUTE_UNUSED,
                              tree treeop2 ATTRIBUTE_UNUSED)
 {
-#ifdef HAVE_conditional_move
   rtx insn;
   rtx op00, op01, op1, op2;
   enum rtx_code comparison_code;
@@ -8049,7 +7973,7 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
       unsignedp = TYPE_UNSIGNED (type);
       comparison_code = convert_tree_comp_to_rtx (cmpcode, unsignedp);
     }
-  else if (TREE_CODE_CLASS (TREE_CODE (treeop0)) == tcc_comparison)
+  else if (COMPARISON_CLASS_P (treeop0))
     {
       tree type = TREE_TYPE (TREE_OPERAND (treeop0, 0));
       enum tree_code cmpcode = TREE_CODE (treeop0);
@@ -8064,7 +7988,9 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
       op00 = expand_normal (treeop0);
       op01 = const0_rtx;
       comparison_code = NE;
-      comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
+      comparison_mode = GET_MODE (op00);
+      if (comparison_mode == VOIDmode)
+       comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
     }
 
   if (GET_MODE (op1) != mode)
@@ -8092,7 +8018,6 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
   /* Otherwise discard the sequence and fall back to code with
      branches.  */
   end_sequence ();
-#endif
   return NULL_RTX;
 }
 
@@ -8101,6 +8026,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
                    enum expand_modifier modifier)
 {
   rtx op0, op1, op2, temp;
+  rtx_code_label *lab;
   tree type;
   int unsignedp;
   machine_mode mode;
@@ -8498,11 +8424,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
         Thus the following special case checks need only
         check the second operand.  */
       if (TREE_CODE (treeop0) == INTEGER_CST)
-       {
-         tree t1 = treeop0;
-         treeop0 = treeop1;
-         treeop1 = t1;
-       }
+       std::swap (treeop0, treeop1);
 
       /* First, check if we have a multiplication of one signed and one
         unsigned operand.  */
@@ -8627,11 +8549,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
            def0 = get_def_for_expr (treeop1, NEGATE_EXPR);
            /* Swap operands if the 2nd operand is fed by a negate.  */
            if (def0)
-             {
-               tree tem = treeop0;
-               treeop0 = treeop1;
-               treeop1 = tem;
-             }
+             std::swap (treeop0, treeop1);
          }
        def2 = get_def_for_expr (treeop2, NEGATE_EXPR);
 
@@ -8678,11 +8596,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
         Thus the following special case checks need only
         check the second operand.  */
       if (TREE_CODE (treeop0) == INTEGER_CST)
-       {
-         tree t1 = treeop0;
-         treeop0 = treeop1;
-         treeop1 = t1;
-       }
+       std::swap (treeop0, treeop1);
 
       /* Attempt to return something suitable for generating an
         indexed address, for machines that support that.  */
@@ -8843,11 +8757,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 
       /* If op1 was placed in target, swap op0 and op1.  */
       if (target != op0 && target == op1)
-       {
-         temp = op0;
-         op0 = op1;
-         op1 = temp;
-       }
+       std::swap (op0, op1);
 
       /* We generate better code and avoid problems with op1 mentioning
         target by forcing op1 into a pseudo if it isn't a constant.  */
@@ -8882,7 +8792,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
            if (code == MIN_EXPR)
              comparison_code = LT;
          }
-#ifdef HAVE_conditional_move
+
        /* Use a conditional move if possible.  */
        if (can_conditionally_move_p (mode))
          {
@@ -8910,17 +8820,17 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
               branches.  */
            end_sequence ();
          }
-#endif
+
        if (target != op0)
          emit_move_insn (target, op0);
 
-       temp = gen_label_rtx ();
+       lab = gen_label_rtx ();
        do_compare_rtx_and_jump (target, cmpop1, comparison_code,
-                                unsignedp, mode, NULL_RTX, NULL_RTX, temp,
+                                unsignedp, mode, NULL_RTX, NULL, lab,
                                 -1);
       }
       emit_move_insn (target, op1);
-      emit_label (temp);
+      emit_label (lab);
       return target;
 
     case BIT_NOT_EXPR:
@@ -8998,38 +8908,39 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
     case UNGE_EXPR:
     case UNEQ_EXPR:
     case LTGT_EXPR:
-      temp = do_store_flag (ops,
-                           modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
-                           tmode != VOIDmode ? tmode : mode);
-      if (temp)
-       return temp;
-
-      /* Use a compare and a jump for BLKmode comparisons, or for function
-        type comparisons is HAVE_canonicalize_funcptr_for_compare.  */
-
-      if ((target == 0
-          || modifier == EXPAND_STACK_PARM
-          || ! safe_from_p (target, treeop0, 1)
-          || ! safe_from_p (target, treeop1, 1)
-          /* Make sure we don't have a hard reg (such as function's return
-             value) live across basic blocks, if not optimizing.  */
-          || (!optimize && REG_P (target)
-              && REGNO (target) < FIRST_PSEUDO_REGISTER)))
-       target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
+      {
+       temp = do_store_flag (ops,
+                             modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
+                             tmode != VOIDmode ? tmode : mode);
+       if (temp)
+         return temp;
 
-      emit_move_insn (target, const0_rtx);
+       /* Use a compare and a jump for BLKmode comparisons, or for function
+          type comparisons is HAVE_canonicalize_funcptr_for_compare.  */
+
+       if ((target == 0
+            || modifier == EXPAND_STACK_PARM
+            || ! safe_from_p (target, treeop0, 1)
+            || ! safe_from_p (target, treeop1, 1)
+            /* Make sure we don't have a hard reg (such as function's return
+               value) live across basic blocks, if not optimizing.  */
+            || (!optimize && REG_P (target)
+                && REGNO (target) < FIRST_PSEUDO_REGISTER)))
+         target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
 
-      op1 = gen_label_rtx ();
-      jumpifnot_1 (code, treeop0, treeop1, op1, -1);
+       emit_move_insn (target, const0_rtx);
 
-      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
-       emit_move_insn (target, constm1_rtx);
-      else
-       emit_move_insn (target, const1_rtx);
+       rtx_code_label *lab1 = gen_label_rtx ();
+       jumpifnot_1 (code, treeop0, treeop1, lab1, -1);
 
-      emit_label (op1);
-      return target;
+       if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
+         emit_move_insn (target, constm1_rtx);
+       else
+         emit_move_insn (target, const1_rtx);
 
+       emit_label (lab1);
+       return target;
+      }
     case COMPLEX_EXPR:
       /* Get the rtx code of the operands.  */
       op0 = expand_normal (treeop0);
@@ -9252,58 +9163,60 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
       }
 
     case COND_EXPR:
-      /* A COND_EXPR with its type being VOID_TYPE represents a
-        conditional jump and is handled in
-        expand_gimple_cond_expr.  */
-      gcc_assert (!VOID_TYPE_P (type));
-
-      /* Note that COND_EXPRs whose type is a structure or union
-        are required to be constructed to contain assignments of
-        a temporary variable, so that we can evaluate them here
-        for side effect only.  If type is void, we must do likewise.  */
-
-      gcc_assert (!TREE_ADDRESSABLE (type)
-                 && !ignore
-                 && TREE_TYPE (treeop1) != void_type_node
-                 && TREE_TYPE (treeop2) != void_type_node);
-
-      temp = expand_cond_expr_using_cmove (treeop0, treeop1, treeop2);
-      if (temp)
-       return temp;
-
-      /* If we are not to produce a result, we have no target.  Otherwise,
-        if a target was specified use it; it will not be used as an
-        intermediate target unless it is safe.  If no target, use a
-        temporary.  */
-
-      if (modifier != EXPAND_STACK_PARM
-         && original_target
-         && safe_from_p (original_target, treeop0, 1)
-         && GET_MODE (original_target) == mode
-         && !MEM_P (original_target))
-       temp = original_target;
-      else
-       temp = assign_temp (type, 0, 1);
-
-      do_pending_stack_adjust ();
-      NO_DEFER_POP;
-      op0 = gen_label_rtx ();
-      op1 = gen_label_rtx ();
-      jumpifnot (treeop0, op0, -1);
-      store_expr (treeop1, temp,
-                 modifier == EXPAND_STACK_PARM,
-                 false);
-
-      emit_jump_insn (gen_jump (op1));
-      emit_barrier ();
-      emit_label (op0);
-      store_expr (treeop2, temp,
-                 modifier == EXPAND_STACK_PARM,
-                 false);
+      {
+       /* A COND_EXPR with its type being VOID_TYPE represents a
+          conditional jump and is handled in
+          expand_gimple_cond_expr.  */
+       gcc_assert (!VOID_TYPE_P (type));
+
+       /* Note that COND_EXPRs whose type is a structure or union
+          are required to be constructed to contain assignments of
+          a temporary variable, so that we can evaluate them here
+          for side effect only.  If type is void, we must do likewise.  */
+
+       gcc_assert (!TREE_ADDRESSABLE (type)
+                   && !ignore
+                   && TREE_TYPE (treeop1) != void_type_node
+                   && TREE_TYPE (treeop2) != void_type_node);
+
+       temp = expand_cond_expr_using_cmove (treeop0, treeop1, treeop2);
+       if (temp)
+         return temp;
 
-      emit_label (op1);
-      OK_DEFER_POP;
-      return temp;
+       /* If we are not to produce a result, we have no target.  Otherwise,
+          if a target was specified use it; it will not be used as an
+          intermediate target unless it is safe.  If no target, use a
+          temporary.  */
+
+       if (modifier != EXPAND_STACK_PARM
+           && original_target
+           && safe_from_p (original_target, treeop0, 1)
+           && GET_MODE (original_target) == mode
+           && !MEM_P (original_target))
+         temp = original_target;
+       else
+         temp = assign_temp (type, 0, 1);
+
+       do_pending_stack_adjust ();
+       NO_DEFER_POP;
+       rtx_code_label *lab0 = gen_label_rtx ();
+       rtx_code_label *lab1 = gen_label_rtx ();
+       jumpifnot (treeop0, lab0, -1);
+       store_expr (treeop1, temp,
+                   modifier == EXPAND_STACK_PARM,
+                   false);
+
+       emit_jump_insn (gen_jump (lab1));
+       emit_barrier ();
+       emit_label (lab0);
+       store_expr (treeop2, temp,
+                   modifier == EXPAND_STACK_PARM,
+                   false);
+
+       emit_label (lab1);
+       OK_DEFER_POP;
+       return temp;
+      }
 
     case VEC_COND_EXPR:
       target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target);
@@ -9506,6 +9419,15 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
              /* Fallthru */
            case GIMPLE_BINARY_RHS:
              ops.op1 = gimple_assign_rhs2 (g);
+
+             /* Try to expand conditonal compare.  */
+             if (targetm.gen_ccmp_first)
+               {
+                 gcc_checking_assert (targetm.gen_ccmp_next != NULL);
+                 r = expand_ccmp_expr (g);
+                 if (r)
+                   break;
+               }
              /* Fallthru */
            case GIMPLE_UNARY_RHS:
              ops.op0 = gimple_assign_rhs1 (g);
@@ -10119,7 +10041,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
                                        &mode1, &unsignedp, &volatilep, true);
        rtx orig_op0, memloc;
-       bool mem_attrs_from_type = false;
+       bool clear_mem_expr = false;
 
        /* If we got back the original object, something is wrong.  Perhaps
           we are evaluating an expression too early.  In any event, don't
@@ -10215,7 +10137,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
            memloc = assign_temp (TREE_TYPE (tem), 1, 1);
            emit_move_insn (memloc, op0);
            op0 = memloc;
-           mem_attrs_from_type = true;
+           clear_mem_expr = true;
          }
 
        if (offset)
@@ -10228,7 +10150,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 
            address_mode = get_address_mode (op0);
            if (GET_MODE (offset_rtx) != address_mode)
-             offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
+             {
+               /* We cannot be sure that the RTL in offset_rtx is valid outside
+                  of a memory address context, so force it into a register
+                  before attempting to convert it to the desired mode.  */
+               offset_rtx = force_operand (offset_rtx, NULL_RTX);
+               offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
+             }
 
            /* See the comment in expand_assignment for the rationale.  */
            if (mode1 != VOIDmode
@@ -10399,17 +10327,17 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
        if (op0 == orig_op0)
          op0 = copy_rtx (op0);
 
-       /* If op0 is a temporary because of forcing to memory, pass only the
-          type to set_mem_attributes so that the original expression is never
-          marked as ADDRESSABLE through MEM_EXPR of the temporary.  */
-       if (mem_attrs_from_type)
-         set_mem_attributes (op0, type, 0);
-       else
-         set_mem_attributes (op0, exp, 0);
+       set_mem_attributes (op0, exp, 0);
 
        if (REG_P (XEXP (op0, 0)))
          mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
 
+       /* If op0 is a temporary because the original expressions was forced
+          to memory, clear MEM_EXPR so that the original expression cannot
+          be marked as addressable through MEM_EXPR of the temporary.  */
+       if (clear_mem_expr)
+         set_mem_expr (op0, NULL_TREE);
+
        MEM_VOLATILE_P (op0) |= volatilep;
        if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
            || modifier == EXPAND_CONST_ADDRESS
@@ -10452,7 +10380,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
        if (fndecl && DECL_BUILT_IN (fndecl))
          {
            gcc_assert (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_FRONTEND);
-           return expand_builtin (exp, target, subtarget, tmode, ignore);
+           if (CALL_WITH_BOUNDS_P (exp))
+             return expand_builtin_with_bounds (exp, target, subtarget,
+                                                tmode, ignore);
+           else
+             return expand_builtin (exp, target, subtarget, tmode, ignore);
          }
       }
       return expand_call (exp, target, ignore);
@@ -10605,7 +10537,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
              if ((icode = optab_handler (movmisalign_optab, mode))
                  != CODE_FOR_nothing)
                {
-                 rtx reg, insn;
+                 rtx reg;
 
                  op0 = adjust_address (op0, mode, 0);
                  /* We've already validated the memory, and we're creating a
@@ -10614,7 +10546,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
                  reg = gen_reg_rtx (mode);
 
                  /* Nor can the insn generator.  */
-                 insn = GEN_FCN (icode) (reg, op0);
+                 rtx_insn *insn = GEN_FCN (icode) (reg, op0);
                  emit_insn (insn);
                  return reg;
                }
@@ -10964,7 +10896,6 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
 {
   enum rtx_code code;
   tree arg0, arg1, type;
-  tree tem;
   machine_mode operand_mode;
   int unsignedp;
   rtx op0, op1;
@@ -11087,7 +11018,7 @@ do_store_flag (sepops ops, rtx target, machine_mode mode)
   if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST
       || TREE_CODE (arg0) == FIXED_CST)
     {
-      tem = arg0; arg0 = arg1; arg1 = tem;
+      std::swap (arg0, arg1);
       code = swap_condition (code);
     }
 
@@ -11206,11 +11137,6 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
 }
 
 /* Attempt to generate a tablejump instruction; same concept.  */
-#ifndef HAVE_tablejump
-#define HAVE_tablejump 0
-#define gen_tablejump(x, y) (0)
-#endif
-
 /* Subroutine of the next function.
 
    INDEX is the value being switched on, with the lowest value
@@ -11416,4 +11342,57 @@ get_personality_function (tree decl)
   return XEXP (DECL_RTL (personality), 0);
 }
 
+/* Returns a tree for the size of EXP in bytes.  */
+
+static tree
+tree_expr_size (const_tree exp)
+{
+  if (DECL_P (exp)
+      && DECL_SIZE_UNIT (exp) != 0)
+    return DECL_SIZE_UNIT (exp);
+  else
+    return size_in_bytes (TREE_TYPE (exp));
+}
+
+/* Return an rtx for the size in bytes of the value of EXP.  */
+
+rtx
+expr_size (tree exp)
+{
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    {
+      size = tree_expr_size (exp);
+      gcc_assert (size);
+      gcc_assert (size == SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp));
+    }
+
+  return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), EXPAND_NORMAL);
+}
+
+/* Return a wide integer for the size in bytes of the value of EXP, or -1
+   if the size can vary or is larger than an integer.  */
+
+static HOST_WIDE_INT
+int_expr_size (tree exp)
+{
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    {
+      size = tree_expr_size (exp);
+      gcc_assert (size);
+    }
+
+  if (size == 0 || !tree_fits_shwi_p (size))
+    return -1;
+
+  return tree_to_shwi (size);
+}
+
 #include "gt-expr.h"