]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/reg-stack.c
[testsuite] Add missing dg-require-effective-target label_values
[thirdparty/gcc.git] / gcc / reg-stack.c
index f2381067f5e3885b342d0a6e6c661054ee511fc3..8c934aaf936e945a30e46d34106f3eeafd155544 100644 (file)
@@ -1,5 +1,5 @@
 /* Register to Stack convert for GNU compiler.
-   Copyright (C) 1992-2017 Free Software Foundation, Inc.
+   Copyright (C) 1992-2019 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
 #include "df.h"
 #include "insn-config.h"
 #include "memmodel.h"
+#include "regs.h"
 #include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
 #include "recog.h"
 #include "varasm.h"
@@ -262,7 +263,7 @@ static bool move_for_stack_reg (rtx_insn *, stack_ptr, rtx);
 static bool move_nan_for_stack_reg (rtx_insn *, stack_ptr, rtx);
 static int swap_rtx_condition_1 (rtx);
 static int swap_rtx_condition (rtx_insn *);
-static void compare_for_stack_reg (rtx_insn *, stack_ptr, rtx);
+static void compare_for_stack_reg (rtx_insn *, stack_ptr, rtx, bool);
 static bool subst_stack_regs_pat (rtx_insn *, stack_ptr, rtx);
 static void subst_asm_stack_regs (rtx_insn *, stack_ptr);
 static bool subst_stack_regs (rtx_insn *, stack_ptr);
@@ -413,8 +414,9 @@ get_true_reg (rtx *pat)
        /* Eliminate FP subregister accesses in favor of the
           actual FP register in use.  */
        {
-         rtx subreg;
-         if (STACK_REG_P (subreg = SUBREG_REG (*pat)))
+         rtx subreg = SUBREG_REG (*pat);
+
+         if (STACK_REG_P (subreg))
            {
              int regno_off = subreg_regno_offset (REGNO (subreg),
                                                   GET_MODE (subreg),
@@ -427,6 +429,12 @@ get_true_reg (rtx *pat)
          pat = &XEXP (*pat, 0);
          break;
        }
+
+      case FLOAT_TRUNCATE:
+       if (!flag_unsafe_math_optimizations)
+         return pat;
+       /* FALLTHRU */
+
       case FLOAT:
       case FIX:
       case FLOAT_EXTEND:
@@ -439,12 +447,6 @@ get_true_reg (rtx *pat)
          pat = &XVECEXP (*pat, 0, 0);
        return pat;
 
-      case FLOAT_TRUNCATE:
-       if (!flag_unsafe_math_optimizations)
-         return pat;
-       pat = &XEXP (*pat, 0);
-       break;
-
       default:
        return pat;
       }
@@ -543,7 +545,8 @@ check_asm_stack_operands (rtx_insn *insn)
            for (j = 0; j < n_clobbers; j++)
              if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
                {
-                 error_for_asm (insn, "output constraint %d cannot be specified together with \"%s\" clobber",
+                 error_for_asm (insn, "output constraint %d cannot be "
+                                "specified together with %qs clobber",
                                 i, reg_names [REGNO (clobber_reg[j])]);
                  malformed_asm = 1;
                  break;
@@ -566,7 +569,7 @@ check_asm_stack_operands (rtx_insn *insn)
 
   if (i != LAST_STACK_REG + 1)
     {
-      error_for_asm (insn, "output regs must be grouped at top of stack");
+      error_for_asm (insn, "output registers must be grouped at top of stack");
       malformed_asm = 1;
     }
 
@@ -606,7 +609,8 @@ check_asm_stack_operands (rtx_insn *insn)
   if (i != LAST_STACK_REG + 1)
     {
       error_for_asm (insn,
-                    "implicitly popped regs must be grouped at top of stack");
+                    "implicitly popped registers must be grouped "
+                    "at top of stack");
       malformed_asm = 1;
     }
 
@@ -623,7 +627,8 @@ check_asm_stack_operands (rtx_insn *insn)
   if (i != LAST_STACK_REG + 1)
     {
       error_for_asm (insn,
-                    "explicitly used regs must be grouped at top of stack");
+                    "explicitly used registers must be grouped "
+                    "at top of stack");
       malformed_asm = 1;
     }
 
@@ -710,7 +715,7 @@ replace_reg (rtx *reg, int regno)
   gcc_assert (IN_RANGE (regno, FIRST_STACK_REG, LAST_STACK_REG));
   gcc_assert (STACK_REG_P (*reg));
 
-  gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (*reg))
+  gcc_assert (GET_MODE_CLASS (GET_MODE (*reg)) == MODE_FLOAT
              || GET_MODE_CLASS (GET_MODE (*reg)) == MODE_COMPLEX_FLOAT);
 
   *reg = FP_MODE_REG (regno, GET_MODE (*reg));
@@ -764,8 +769,10 @@ get_hard_regnum (stack_ptr regstack, rtx reg)
    cases the movdf pattern to pop.  */
 
 static rtx_insn *
-emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where where)
+emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg,
+              enum emit_where where)
 {
+  machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
   rtx_insn *pop_insn;
   rtx pop_rtx;
   int hard_regno;
@@ -774,8 +781,8 @@ emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where wher
      CLOBBER and USE expressions.  */
   if (COMPLEX_MODE_P (GET_MODE (reg)))
     {
-      rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
-      rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
+      rtx reg1 = FP_MODE_REG (REGNO (reg), raw_mode);
+      rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, raw_mode);
 
       pop_insn = NULL;
       if (get_hard_regnum (regstack, reg1) >= 0)
@@ -790,15 +797,15 @@ emit_pop_insn (rtx_insn *insn, stack_ptr regstack, rtx reg, enum emit_where wher
 
   gcc_assert (hard_regno >= FIRST_STACK_REG);
 
-  pop_rtx = gen_rtx_SET (FP_MODE_REG (hard_regno, DFmode),
-                        FP_MODE_REG (FIRST_STACK_REG, DFmode));
+  pop_rtx = gen_rtx_SET (FP_MODE_REG (hard_regno, raw_mode),
+                        FP_MODE_REG (FIRST_STACK_REG, raw_mode));
 
   if (where == EMIT_AFTER)
     pop_insn = emit_insn_after (pop_rtx, insn);
   else
     pop_insn = emit_insn_before (pop_rtx, insn);
 
-  add_reg_note (pop_insn, REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode));
+  add_reg_note (pop_insn, REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, raw_mode));
 
   regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]
     = regstack->reg[regstack->top];
@@ -819,7 +826,6 @@ static void
 emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
 {
   int hard_regno;
-  rtx swap_rtx;
   int other_reg;               /* swap regno temps */
   rtx_insn *i1;                        /* the stack-reg insn prior to INSN */
   rtx i1set = NULL_RTX;                /* the SET rtx within I1 */
@@ -977,9 +983,13 @@ emit_swap_insn (rtx_insn *insn, stack_ptr regstack, rtx reg)
       return;
     }
 
-  swap_rtx = gen_swapxf (FP_MODE_REG (hard_regno, XFmode),
-                        FP_MODE_REG (FIRST_STACK_REG, XFmode));
-
+  machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
+  rtx op1 = FP_MODE_REG (hard_regno, raw_mode);
+  rtx op2 = FP_MODE_REG (FIRST_STACK_REG, raw_mode);
+  rtx swap_rtx
+    = gen_rtx_PARALLEL (VOIDmode,
+                       gen_rtvec (2, gen_rtx_SET (op1, op2),
+                                  gen_rtx_SET (op2, op1)));
   if (i1)
     emit_insn_after (swap_rtx, i1);
   else if (current_block)
@@ -1105,13 +1115,16 @@ move_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat)
        }
 
       /* The destination ought to be dead.  */
-      gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG);
-
-      replace_reg (psrc, get_hard_regnum (regstack, src));
+      if (get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
+       gcc_assert (any_malformed_asm);
+      else
+       {
+         replace_reg (psrc, get_hard_regnum (regstack, src));
 
-      regstack->reg[++regstack->top] = REGNO (dest);
-      SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
-      replace_reg (pdest, FIRST_STACK_REG);
+         regstack->reg[++regstack->top] = REGNO (dest);
+         SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
+         replace_reg (pdest, FIRST_STACK_REG);
+       }
     }
   else if (STACK_REG_P (src))
     {
@@ -1170,7 +1183,8 @@ move_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat)
          && XINT (SET_SRC (XVECEXP (pat, 0, 1)), 1) == UNSPEC_TAN)
        emit_swap_insn (insn, regstack, dest);
       else
-       gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG);
+       gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG
+                   || any_malformed_asm);
 
       gcc_assert (regstack->top < REG_STACK_SIZE);
 
@@ -1325,7 +1339,8 @@ swap_rtx_condition (rtx_insn *insn)
    set up.  */
 
 static void
-compare_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat_src)
+compare_for_stack_reg (rtx_insn *insn, stack_ptr regstack,
+                      rtx pat_src, bool can_pop_second_op)
 {
   rtx *src1, *src2;
   rtx src1_note, src2_note;
@@ -1366,8 +1381,18 @@ compare_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat_src)
 
   if (src1_note)
     {
-      pop_stack (regstack, REGNO (XEXP (src1_note, 0)));
-      replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+      if (*src2 == CONST0_RTX (GET_MODE (*src2)))
+       {
+         /* This is `ftst' insn that can't pop register.  */
+         remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src1_note, 0)));
+         emit_pop_insn (insn, regstack, XEXP (src1_note, 0),
+                        EMIT_AFTER);
+       }
+      else
+       {
+         pop_stack (regstack, REGNO (XEXP (src1_note, 0)));
+         replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+       }
     }
 
   /* If the second operand dies, handle that.  But if the operands are
@@ -1384,7 +1409,7 @@ compare_for_stack_reg (rtx_insn *insn, stack_ptr regstack, rtx pat_src)
         at top (FIRST_STACK_REG) now.  */
 
       if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG
-         && src1_note)
+         && src1_note && can_pop_second_op)
        {
          pop_stack (regstack, REGNO (XEXP (src2_note, 0)));
          replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
@@ -1549,10 +1574,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
 
        switch (GET_CODE (pat_src))
          {
-         case COMPARE:
-           compare_for_stack_reg (insn, regstack, pat_src);
-           break;
-
          case CALL:
            {
              int count;
@@ -1800,7 +1821,6 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
              case UNSPEC_FRNDINT_FLOOR:
              case UNSPEC_FRNDINT_CEIL:
              case UNSPEC_FRNDINT_TRUNC:
-             case UNSPEC_FRNDINT_MASK_PM:
 
                /* Above insns operate on the top of the stack.  */
 
@@ -1953,31 +1973,35 @@ subst_stack_regs_pat (rtx_insn *insn, stack_ptr regstack, rtx pat)
                replace_reg (src2, FIRST_STACK_REG + 1);
                break;
 
-             case UNSPEC_SAHF:
-               /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF)
-                  The combination matches the PPRO fcomi instruction.  */
-
-               pat_src = XVECEXP (pat_src, 0, 0);
-               gcc_assert (GET_CODE (pat_src) == UNSPEC);
-               gcc_assert (XINT (pat_src, 1) == UNSPEC_FNSTSW);
-               /* Fall through.  */
-
              case UNSPEC_FNSTSW:
                /* Combined fcomp+fnstsw generated for doing well with
                   CSE.  When optimizing this would have been broken
                   up before now.  */
 
                pat_src = XVECEXP (pat_src, 0, 0);
-               gcc_assert (GET_CODE (pat_src) == COMPARE);
+               if (GET_CODE (pat_src) == COMPARE)
+                 goto do_compare;
 
-               compare_for_stack_reg (insn, regstack, pat_src);
-               break;
+               /* Fall through.  */
+
+             case UNSPEC_NOTRAP:
+
+               pat_src = XVECEXP (pat_src, 0, 0);
+               gcc_assert (GET_CODE (pat_src) == COMPARE);
+               goto do_compare;
 
              default:
                gcc_unreachable ();
              }
            break;
 
+         case COMPARE:
+         do_compare:
+           /* `fcomi' insn can't pop two regs.  */
+           compare_for_stack_reg (insn, regstack, pat_src,
+                                  REGNO (*dest) != FLAGS_REG);
+           break;
+
          case IF_THEN_ELSE:
            /* This insn requires the top of stack to be the destination.  */
 
@@ -2259,13 +2283,7 @@ subst_asm_stack_regs (rtx_insn *insn, stack_ptr regstack)
       int regnum = get_hard_regnum (regstack, clobber_reg[i]);
 
       if (regnum >= 0)
-       {
-         /* Sigh - clobbers always have QImode.  But replace_reg knows
-            that these regs can't be MODE_INT and will assert.  Just put
-            the right reg there without calling replace_reg.  */
-
-         *clobber_loc[i] = FP_MODE_REG (regnum, DFmode);
-       }
+       replace_reg (clobber_loc[i], regnum);
     }
 
   /* Now remove from REGSTACK any inputs that the asm implicitly popped.  */
@@ -2477,7 +2495,8 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
              enum emit_where where)
 {
   int reg;
-  int update_end = 0;
+  machine_mode raw_mode = reg_raw_mode[FIRST_STACK_REG];
+  rtx_insn *update_end = NULL;
   int i;
 
   /* Stack adjustments for the first insn in a block update the
@@ -2499,7 +2518,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
   if (where == EMIT_AFTER)
     {
       if (current_block && BB_END (current_block) == insn)
-       update_end = 1;
+       update_end = insn;
       insn = NEXT_INSN (insn);
     }
 
@@ -2578,7 +2597,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
                next--;
              dest = next--;
            }
-         emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], DFmode),
+         emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], raw_mode),
                         EMIT_BEFORE);
        }
     }
@@ -2600,11 +2619,11 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
          {
            while (TEST_HARD_REG_BIT (new_stack->reg_set, old->reg[next]))
              next--;
-           emit_pop_insn (insn, old, FP_MODE_REG (old->reg[next], DFmode),
+           emit_pop_insn (insn, old, FP_MODE_REG (old->reg[next], raw_mode),
                           EMIT_BEFORE);
          }
        else
-         emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], DFmode),
+         emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], raw_mode),
                         EMIT_BEFORE);
     }
 
@@ -2651,7 +2670,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
                gcc_assert (reg != -1);
 
                emit_swap_insn (insn, old,
-                               FP_MODE_REG (old->reg[reg], DFmode));
+                               FP_MODE_REG (old->reg[reg], raw_mode));
              }
 
            /* See if any regs remain incorrect.  If so, bring an
@@ -2662,7 +2681,7 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
              if (new_stack->reg[reg] != old->reg[reg])
                {
                  emit_swap_insn (insn, old,
-                                 FP_MODE_REG (old->reg[reg], DFmode));
+                                 FP_MODE_REG (old->reg[reg], raw_mode));
                  break;
                }
          } while (reg >= 0);
@@ -2674,7 +2693,16 @@ change_stack (rtx_insn *insn, stack_ptr old, stack_ptr new_stack,
     }
 
   if (update_end)
-    BB_END (current_block) = PREV_INSN (insn);
+    {
+      for (update_end = NEXT_INSN (update_end); update_end != insn;
+          update_end = NEXT_INSN (update_end))
+       {
+         set_block_for_insn (update_end, current_block);
+         if (INSN_P (update_end))
+           df_insn_rescan (update_end);
+       }
+      BB_END (current_block) = PREV_INSN (insn);
+    }
 }
 \f
 /* Print stack configuration.  */
@@ -2943,14 +2971,9 @@ better_edge (edge e1, edge e2)
   if (!e1)
     return e2;
 
-  if (EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2))
-    return e1;
-  if (EDGE_FREQUENCY (e1) < EDGE_FREQUENCY (e2))
-    return e2;
-
-  if (e1->count > e2->count)
+  if (e1->count () > e2->count ())
     return e1;
-  if (e1->count < e2->count)
+  if (e1->count () < e2->count ())
     return e2;
 
   /* Prefer critical edges to minimize inserting compensation code on
@@ -3028,7 +3051,7 @@ convert_regs_1 (basic_block block)
 
       /* Don't bother processing unless there is a stack reg
         mentioned or if it's a CALL_INSN.  */
-      if (DEBUG_INSN_P (insn))
+      if (DEBUG_BIND_INSN_P (insn))
        {
          if (starting_stack_p)
            debug_insns_with_starting_stack++;
@@ -3068,7 +3091,7 @@ convert_regs_1 (basic_block block)
       for (insn = BB_HEAD (block); debug_insns_with_starting_stack;
           insn = NEXT_INSN (insn))
        {
-         if (!DEBUG_INSN_P (insn))
+         if (!DEBUG_BIND_INSN_P (insn))
            continue;
 
          debug_insns_with_starting_stack--;