x86: Enable FMA in rsqrt<mode>2 expander
[platform/upstream/gcc.git] / gcc / jump.c
index 045b1f0..34a8f20 100644 (file)
@@ -1,5 +1,5 @@
 /* Optimize jump instructions, for GNU compiler.
-   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -36,43 +36,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
+#include "tree.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "memmodel.h"
 #include "tm_p.h"
-#include "flags.h"
-#include "hard-reg-set.h"
-#include "regs.h"
 #include "insn-config.h"
-#include "insn-attr.h"
+#include "regs.h"
+#include "emit-rtl.h"
 #include "recog.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "input.h"
-#include "function.h"
-#include "predict.h"
-#include "dominance.h"
-#include "cfg.h"
 #include "cfgrtl.h"
-#include "basic-block.h"
-#include "symtab.h"
-#include "statistics.h"
-#include "alias.h"
-#include "inchash.h"
-#include "tree.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
-#include "expr.h"
-#include "except.h"
-#include "diagnostic-core.h"
-#include "reload.h"
-#include "tree-pass.h"
-#include "target.h"
 #include "rtl-iter.h"
 
 /* Optimize jump y; x: ... y: jumpif... x?
@@ -86,15 +62,13 @@ static void init_label_info (rtx_insn *);
 static void mark_all_labels (rtx_insn *);
 static void mark_jump_label_1 (rtx, rtx_insn *, bool, bool);
 static void mark_jump_label_asm (rtx, rtx_insn *);
-static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
-static int invert_exp_1 (rtx, rtx);
+static void redirect_exp_1 (rtx *, rtx, rtx, rtx_insn *);
+static int invert_exp_1 (rtx, rtx_insn *);
 \f
 /* Worker for rebuild_jump_labels and rebuild_jump_labels_chain.  */
 static void
 rebuild_jump_labels_1 (rtx_insn *f, bool count_forced)
 {
-  rtx_insn_list *insn;
-
   timevar_push (TV_REBUILD_JUMP);
   init_label_info (f);
   mark_all_labels (f);
@@ -104,9 +78,13 @@ rebuild_jump_labels_1 (rtx_insn *f, bool count_forced)
      count doesn't drop to zero.  */
 
   if (count_forced)
-    for (insn = forced_labels; insn; insn = insn->next ())
-      if (LABEL_P (insn->insn ()))
-       LABEL_NUSES (insn->insn ())++;
+    {
+      rtx_insn *insn;
+      unsigned int i;
+      FOR_EACH_VEC_SAFE_ELT (forced_labels, i, insn)
+       if (LABEL_P (insn))
+         LABEL_NUSES (insn)++;
+    }
   timevar_pop (TV_REBUILD_JUMP);
 }
 
@@ -145,21 +123,10 @@ cleanup_barriers (void)
     {
       if (BARRIER_P (insn))
        {
-         rtx_insn *prev = prev_nonnote_insn (insn);
+         rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
          if (!prev)
            continue;
 
-         if (CALL_P (prev))
-           {
-             /* Make sure we do not split a call and its corresponding
-                CALL_ARG_LOCATION note.  */
-             rtx_insn *next = NEXT_INSN (prev);
-
-             if (NOTE_P (next)
-                 && NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION)
-               prev = next;
-           }
-
          if (BARRIER_P (prev))
            delete_insn (insn);
          else if (prev != PREV_INSN (insn))
@@ -306,7 +273,7 @@ maybe_propagate_label_ref (rtx_insn *jump_insn, rtx_insn *prev_nonjump_insn)
             CODE_LABEL in the LABEL_REF of the "set".  We can
             conveniently use it for the marker function, which
             requires a LABEL_REF wrapping.  */
-         gcc_assert (XEXP (label_note, 0) == LABEL_REF_LABEL (SET_SRC (label_set)));
+         gcc_assert (XEXP (label_note, 0) == label_ref_label (SET_SRC (label_set)));
 
          mark_jump_label_1 (label_set, jump_insn, false, true);
 
@@ -383,7 +350,7 @@ mark_all_labels (rtx_insn *f)
    to help this function avoid overhead in these cases.  */
 enum rtx_code
 reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
-                               const_rtx arg1, const_rtx insn)
+                               const_rtx arg1, const rtx_insn *insn)
 {
   machine_mode mode;
 
@@ -401,13 +368,7 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
      machine description to do tricks.  */
   if (GET_MODE_CLASS (mode) == MODE_CC
       && REVERSIBLE_CC_MODE (mode))
-    {
-#ifdef REVERSE_CONDITION
-      return REVERSE_CONDITION (code, mode);
-#else
-      return reverse_condition (code);
-#endif
-    }
+    return REVERSE_CONDITION (code, mode);
 
   /* Try a few special cases based on the comparison code.  */
   switch (code)
@@ -441,7 +402,6 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
 
   if (GET_MODE_CLASS (mode) == MODE_CC || CC0_P (arg0))
     {
-      const_rtx prev;
       /* Try to search for the comparison to determine the real mode.
          This code is expensive, but with sane machine description it
          will be never used, since REVERSIBLE_CC_MODE will return true
@@ -452,9 +412,9 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
       /* These CONST_CAST's are okay because prev_nonnote_insn just
         returns its argument and we assign it to a const_rtx
         variable.  */
-      for (prev = prev_nonnote_insn (CONST_CAST_RTX (insn));
+      for (rtx_insn *prev = prev_nonnote_insn (const_cast<rtx_insn *> (insn));
           prev != 0 && !LABEL_P (prev);
-          prev = prev_nonnote_insn (CONST_CAST_RTX (prev)))
+          prev = prev_nonnote_insn (prev))
        {
          const_rtx set = set_of (arg0, prev);
          if (set && GET_CODE (set) == SET
@@ -500,7 +460,7 @@ reversed_comparison_code_parts (enum rtx_code code, const_rtx arg0,
 /* A wrapper around the previous function to take COMPARISON as rtx
    expression.  This simplifies many callers.  */
 enum rtx_code
-reversed_comparison_code (const_rtx comparison, const_rtx insn)
+reversed_comparison_code (const_rtx comparison, const rtx_insn *insn)
 {
   if (!COMPARISON_P (comparison))
     return UNKNOWN;
@@ -514,7 +474,7 @@ reversed_comparison_code (const_rtx comparison, const_rtx insn)
 rtx
 reversed_comparison (const_rtx exp, machine_mode mode)
 {
-  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX);
+  enum rtx_code reversed_code = reversed_comparison_code (exp, NULL);
   if (reversed_code == UNKNOWN)
     return NULL_RTX;
   else
@@ -1180,7 +1140,7 @@ mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
 
     case LABEL_REF:
       {
-       rtx label = LABEL_REF_LABEL (x);
+       rtx_insn *label = label_ref_label (x);
 
        /* Ignore remaining references to unreachable labels that
           have been deleted.  */
@@ -1194,7 +1154,7 @@ mark_jump_label_1 (rtx x, rtx_insn *insn, bool in_mem, bool is_target)
        if (LABEL_REF_NONLOCAL_P (x))
          break;
 
-       LABEL_REF_LABEL (x) = label;
+       set_label_ref_label (x, label);
        if (! insn || ! insn->deleted ())
          ++LABEL_NUSES (label);
 
@@ -1308,26 +1268,6 @@ delete_related_insns (rtx uncast_insn)
   if (next != 0 && BARRIER_P (next))
     delete_insn (next);
 
-  /* If this is a call, then we have to remove the var tracking note
-     for the call arguments.  */
-
-  if (CALL_P (insn)
-      || (NONJUMP_INSN_P (insn)
-         && GET_CODE (PATTERN (insn)) == SEQUENCE
-         && CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
-    {
-      rtx_insn *p;
-
-      for (p = next && next->deleted () ? NEXT_INSN (next) : next;
-          p && NOTE_P (p);
-          p = NEXT_INSN (p))
-       if (NOTE_KIND (p) == NOTE_INSN_CALL_ARG_LOCATION)
-         {
-           remove_insn (p);
-           break;
-         }
-    }
-
   /* If deleting a jump, decrement the count of the label,
      and delete the label if it is now unused.  */
 
@@ -1486,14 +1426,14 @@ redirect_target (rtx x)
    NLABEL as a return.  Accrue modifications into the change group.  */
 
 static void
-redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
+redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx_insn *insn)
 {
   rtx x = *loc;
   RTX_CODE code = GET_CODE (x);
   int i;
   const char *fmt;
 
-  if ((code == LABEL_REF && LABEL_REF_LABEL (x) == olabel)
+  if ((code == LABEL_REF && label_ref_label (x) == olabel)
       || x == olabel)
     {
       x = redirect_target (nlabel);
@@ -1506,7 +1446,7 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
   if (code == SET && SET_DEST (x) == pc_rtx
       && ANY_RETURN_P (nlabel)
       && GET_CODE (SET_SRC (x)) == LABEL_REF
-      && LABEL_REF_LABEL (SET_SRC (x)) == olabel)
+      && label_ref_label (SET_SRC (x)) == olabel)
     {
       validate_change (insn, loc, nlabel, 1);
       return;
@@ -1653,7 +1593,7 @@ redirect_jump_2 (rtx_jump_insn *jump, rtx olabel, rtx nlabel, int delete_unused,
 /* Invert the jump condition X contained in jump insn INSN.  Accrue the
    modifications into the change group.  Return nonzero for success.  */
 static int
-invert_exp_1 (rtx x, rtx insn)
+invert_exp_1 (rtx x, rtx_insn *insn)
 {
   RTX_CODE code = GET_CODE (x);
 
@@ -1753,7 +1693,7 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
                                  && REG_P (SUBREG_REG (y)))))
     {
       int reg_x = -1, reg_y = -1;
-      int byte_x = 0, byte_y = 0;
+      poly_int64 byte_x = 0, byte_y = 0;
       struct subreg_info info;
 
       if (GET_MODE (x) != GET_MODE (y))
@@ -1810,7 +1750,7 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
            reg_y = reg_renumber[reg_y];
        }
 
-      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
+      return reg_x >= 0 && reg_x == reg_y && known_eq (byte_x, byte_y);
     }
 
   /* Now we have disposed of all the cases
@@ -1830,12 +1770,20 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
     case LABEL_REF:
       /* We can't assume nonlocal labels have their following insns yet.  */
       if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
-       return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
+       return label_ref_label (x) == label_ref_label (y);
 
       /* Two label-refs are equivalent if they point at labels
         in the same position in the instruction stream.  */
-      return (next_real_insn (LABEL_REF_LABEL (x))
-             == next_real_insn (LABEL_REF_LABEL (y)));
+      else
+       {
+         rtx_insn *xi = next_nonnote_nondebug_insn (label_ref_label (x));
+         rtx_insn *yi = next_nonnote_nondebug_insn (label_ref_label (y));
+         while (xi && LABEL_P (xi))
+           xi = next_nonnote_nondebug_insn (xi);
+         while (yi && LABEL_P (yi))
+           yi = next_nonnote_nondebug_insn (yi);
+         return xi == yi;
+       }
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -1894,6 +1842,11 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 't':
          if (XTREE (x, i) != XTREE (y, i))
            return 0;