[26/46] Make more use of dyn_cast in tree-vect*
[gcc.git] / gcc / recog.c
index 8e1218b519d80fceefcf558d88d77e7d44fbef7c..0a8fa2ce46cf617a2372e7996e2492d1589a3ded 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines used by or related to instruction recognition.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1258,33 +1258,35 @@ nonmemory_operand (rtx op, machine_mode mode)
 int
 push_operand (rtx op, machine_mode mode)
 {
-  unsigned int rounded_size = GET_MODE_SIZE (mode);
-
-#ifdef PUSH_ROUNDING
-  rounded_size = PUSH_ROUNDING (rounded_size);
-#endif
-
   if (!MEM_P (op))
     return 0;
 
   if (mode != VOIDmode && GET_MODE (op) != mode)
     return 0;
 
+  poly_int64 rounded_size = GET_MODE_SIZE (mode);
+
+#ifdef PUSH_ROUNDING
+  rounded_size = PUSH_ROUNDING (MACRO_INT (rounded_size));
+#endif
+
   op = XEXP (op, 0);
 
-  if (rounded_size == GET_MODE_SIZE (mode))
+  if (known_eq (rounded_size, GET_MODE_SIZE (mode)))
     {
       if (GET_CODE (op) != STACK_PUSH_CODE)
        return 0;
     }
   else
     {
+      poly_int64 offset;
       if (GET_CODE (op) != PRE_MODIFY
          || GET_CODE (XEXP (op, 1)) != PLUS
          || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
-         || !CONST_INT_P (XEXP (XEXP (op, 1), 1))
-         || INTVAL (XEXP (XEXP (op, 1), 1))
-            != ((STACK_GROWS_DOWNWARD ? -1 : 1) * (int) rounded_size))
+         || !poly_int_rtx_p (XEXP (XEXP (op, 1), 1), &offset)
+         || (STACK_GROWS_DOWNWARD
+             ? maybe_ne (offset, -rounded_size)
+             : maybe_ne (offset, rounded_size)))
        return 0;
     }
 
@@ -1823,7 +1825,7 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
       len = CONSTRAINT_LEN (c, constraint);
       do
        constraint++;
-      while (--len && *constraint);
+      while (--len && *constraint && *constraint != ',');
       if (len)
        return 0;
     }
@@ -1943,7 +1945,7 @@ offsettable_address_addr_space_p (int strictp, machine_mode mode, rtx y,
   int (*addressp) (machine_mode, rtx, addr_space_t) =
     (strictp ? strict_memory_address_addr_space_p
             : memory_address_addr_space_p);
-  unsigned int mode_sz = GET_MODE_SIZE (mode);
+  poly_int64 mode_sz = GET_MODE_SIZE (mode);
 
   if (CONSTANT_ADDRESS_P (y))
     return 1;
@@ -1965,7 +1967,7 @@ offsettable_address_addr_space_p (int strictp, machine_mode mode, rtx y,
      Clearly that depends on the situation in which it's being used.
      However, the current situation in which we test 0xffffffff is
      less than ideal.  Caveat user.  */
-  if (mode_sz == 0)
+  if (known_eq (mode_sz, 0))
     mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
 
   /* If the expression contains a constant term,
@@ -1996,7 +1998,7 @@ offsettable_address_addr_space_p (int strictp, machine_mode mode, rtx y,
      go inside a LO_SUM here, so we do so as well.  */
   if (GET_CODE (y) == LO_SUM
       && mode != BLKmode
-      && mode_sz <= GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT)
+      && known_le (mode_sz, GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT))
     z = gen_rtx_LO_SUM (address_mode, XEXP (y, 0),
                        plus_constant (address_mode, XEXP (y, 1),
                                       mode_sz - 1));
@@ -2329,15 +2331,20 @@ extract_insn (rtx_insn *insn)
   which_alternative = -1;
 }
 
-/* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS operands,
-   N_ALTERNATIVES alternatives and constraint strings CONSTRAINTS.
-   OP_ALT_BASE has N_ALTERNATIVES * N_OPERANDS entries and CONSTRAINTS
-   has N_OPERANDS entries.  */
+/* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS
+   operands, N_ALTERNATIVES alternatives and constraint strings
+   CONSTRAINTS.  OP_ALT_BASE has N_ALTERNATIVES * N_OPERANDS entries
+   and CONSTRAINTS has N_OPERANDS entries.  OPLOC should be passed in
+   if the insn is an asm statement and preprocessing should take the
+   asm operands into account, e.g. to determine whether they could be
+   addresses in constraints that require addresses; it should then
+   point to an array of pointers to each operand.  */
 
 void
 preprocess_constraints (int n_operands, int n_alternatives,
                        const char **constraints,
-                       operand_alternative *op_alt_base)
+                       operand_alternative *op_alt_base,
+                       rtx **oploc)
 {
   for (int i = 0; i < n_operands; i++)
     {
@@ -2424,6 +2431,9 @@ preprocess_constraints (int n_operands, int n_alternatives,
                      break;
 
                    case CT_ADDRESS:
+                     if (oploc && !address_operand (*oploc[i], VOIDmode))
+                       break;
+
                      op_alt[i].is_address = 1;
                      op_alt[i].cl
                        = (reg_class_subunion
@@ -2468,7 +2478,8 @@ preprocess_insn_constraints (unsigned int icode)
 
   for (int i = 0; i < n_operands; ++i)
     constraints[i] = insn_data[icode].operand[i].constraint;
-  preprocess_constraints (n_operands, n_alternatives, constraints, op_alt);
+  preprocess_constraints (n_operands, n_alternatives, constraints, op_alt,
+                         NULL);
 
   this_target_recog->x_op_alt[icode] = op_alt;
   return op_alt;
@@ -2491,7 +2502,8 @@ preprocess_constraints (rtx_insn *insn)
       int n_entries = n_operands * n_alternatives;
       memset (asm_op_alt, 0, n_entries * sizeof (operand_alternative));
       preprocess_constraints (n_operands, n_alternatives,
-                             recog_data.constraints, asm_op_alt);
+                             recog_data.constraints, asm_op_alt,
+                             NULL);
       recog_op_alt = asm_op_alt;
     }
 }
@@ -2929,6 +2941,7 @@ void
 split_all_insns (void)
 {
   bool changed;
+  bool need_cfg_cleanup = false;
   basic_block bb;
 
   auto_sbitmap blocks (last_basic_block_for_fn (cfun));
@@ -2947,6 +2960,18 @@ split_all_insns (void)
             CODE_LABELS and short-out basic blocks.  */
          next = NEXT_INSN (insn);
          finish = (insn == BB_END (bb));
+
+         /* If INSN has a REG_EH_REGION note and we split INSN, the
+            resulting split may not have/need REG_EH_REGION notes.
+
+            If that happens and INSN was the last reference to the
+            given EH region, then the EH region will become unreachable.
+            We can not leave the unreachable blocks in the CFG as that
+            will trigger a checking failure.
+
+            So track if INSN has a REG_EH_REGION note.  If so and we
+            split INSN, then trigger a CFG cleanup.  */
+         rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
          if (INSN_P (insn))
            {
              rtx set = single_set (insn);
@@ -2963,6 +2988,8 @@ split_all_insns (void)
                     nops then anyways.  */
                  if (reload_completed)
                      delete_insn_and_edges (insn);
+                 if (note)
+                   need_cfg_cleanup = true;
                }
              else
                {
@@ -2970,6 +2997,8 @@ split_all_insns (void)
                    {
                      bitmap_set_bit (blocks, bb->index);
                      changed = true;
+                     if (note)
+                       need_cfg_cleanup = true;
                    }
                }
            }
@@ -2978,7 +3007,16 @@ split_all_insns (void)
 
   default_rtl_profile ();
   if (changed)
-    find_many_sub_basic_blocks (blocks);
+    {
+      find_many_sub_basic_blocks (blocks);
+
+      /* Splitting could drop an REG_EH_REGION if it potentially
+        trapped in its original form, but does not in its split
+        form.  Consider a FLOAT_TRUNCATE which splits into a memory
+        store/load pair and -fnon-call-exceptions.  */
+      if (need_cfg_cleanup)
+       cleanup_cfg (0);
+    }
 
   checking_verify_flow_info ();
 }
@@ -3418,6 +3456,8 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
   last = emit_insn_after_setloc (attempt,
                                 peep2_insn_data[i].insn,
                                 INSN_LOCATION (peepinsn));
+  if (JUMP_P (peepinsn) && JUMP_P (last))
+    CROSSING_JUMP_P (last) = CROSSING_JUMP_P (peepinsn);
   before_try = PREV_INSN (insn);
   delete_insn_chain (insn, peep2_insn_data[i].insn, false);
 
@@ -3466,7 +3506,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
 
   /* Re-insert the ARGS_SIZE notes.  */
   if (as_note)
-    fixup_args_size_notes (before_try, last, INTVAL (XEXP (as_note, 0)));
+    fixup_args_size_notes (before_try, last, get_args_size (as_note));
 
   /* If we generated a jump instruction, it won't have
      JUMP_LABEL set.  Recompute after we're done.  */