re PR target/65697 (__atomic memory barriers not strong enough for __sync builtins)
[gcc.git] / gcc / lra-constraints.c
index 762889ce13ce12646faa1afb59a40d351d79d281..1d3f94e5ab07a693bfe932301e81a406e8426bf3 100644 (file)
 #include "output.h"
 #include "addresses.h"
 #include "target.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
-#include "input.h"
 #include "function.h"
 #include "symtab.h"
 #include "flags.h"
-#include "statistics.h"
-#include "double-int.h"
-#include "real.h"
-#include "fixed-value.h"
 #include "alias.h"
-#include "wide-int.h"
-#include "inchash.h"
 #include "tree.h"
 #include "expmed.h"
 #include "dojump.h"
 #include "df.h"
 #include "ira.h"
 #include "rtl-error.h"
+#include "params.h"
 #include "lra-int.h"
 
 /* Value of LRA_CURR_RELOAD_NUM at the beginning of BB of the current
@@ -170,6 +160,10 @@ static basic_block curr_bb;
 static lra_insn_recog_data_t curr_id;
 static struct lra_static_insn_data *curr_static_id;
 static machine_mode curr_operand_mode[MAX_RECOG_OPERANDS];
+/* Mode of the register substituted by its equivalence with VOIDmode
+   (e.g. constant) and whose subreg is given operand of the current
+   insn.  VOIDmode in all other cases.  */
+static machine_mode original_subreg_reg_mode[MAX_RECOG_OPERANDS];
 
 \f
 
@@ -528,7 +522,7 @@ get_equiv_with_elimination (rtx x, rtx_insn *insn)
   if (x == res || CONSTANT_P (res))
     return res;
   return lra_eliminate_regs_1 (insn, res, GET_MODE (res),
-                              0, false, false, true);
+                              false, false, 0, true);
 }
 
 /* Set up curr_operand_mode.  */
@@ -744,6 +738,9 @@ operands_match_p (rtx x, rtx y, int y_hard_regno)
 
  slow:
 
+  if (code == REG && REG_P (y))
+    return REGNO (x) == REGNO (y);
+
   if (code == REG && GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))
       && x == SUBREG_REG (y))
     return true;
@@ -868,7 +865,7 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class,
              rtx_insn **before, rtx_insn **after)
 {
   int i, in;
-  rtx new_in_reg, new_out_reg, reg, clobber;
+  rtx new_in_reg, new_out_reg, reg;
   machine_mode inmode, outmode;
   rtx in_rtx = *curr_id->operand_loc[ins[0]];
   rtx out_rtx = out < 0 ? in_rtx : *curr_id->operand_loc[out];
@@ -909,7 +906,7 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class,
             NEW_OUT_REG living above.  We add clobber clause for
             this.  This is just a temporary clobber.  We can remove
             it at the end of LRA work.  */
-         clobber = emit_clobber (new_out_reg);
+         rtx_insn *clobber = emit_clobber (new_out_reg);
          LRA_TEMP_CLOBBER_P (PATTERN (clobber)) = 1;
          LRA_SUBREG_P (new_in_reg) = 1;
          if (GET_CODE (in_rtx) == SUBREG)
@@ -1055,9 +1052,8 @@ emit_spill_move (bool to_p, rtx mem_pseudo, rtx val)
          LRA_SUBREG_P (mem_pseudo) = 1;
        }
     }
-  return as_a <rtx_insn *> (to_p
-                           ? gen_move_insn (mem_pseudo, val)
-                           : gen_move_insn (val, mem_pseudo));
+  return to_p ? gen_move_insn (mem_pseudo, val)
+             : gen_move_insn (val, mem_pseudo);
 }
 
 /* Process a special case insn (register move), return true if we
@@ -1069,10 +1065,9 @@ static bool
 check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
 {
   int sregno, dregno;
-  rtx dest, src, dreg, sreg, old_sreg, new_reg, scratch_reg;
+  rtx dest, src, dreg, sreg, new_reg, scratch_reg;
   rtx_insn *before;
   enum reg_class dclass, sclass, secondary_class;
-  machine_mode sreg_mode;
   secondary_reload_info sri;
 
   lra_assert (curr_insn_set != NULL_RTX);
@@ -1096,8 +1091,6 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
        were a right class for the pseudo, secondary_... hooks usually
        are not define for ALL_REGS.  */
     return false;
-  sreg_mode = GET_MODE (sreg);
-  old_sreg = sreg;
   if (REG_P (sreg))
     sclass = get_reg_class (REGNO (sreg));
   if (sclass == ALL_REGS)
@@ -1156,9 +1149,9 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
       sri.icode = CODE_FOR_nothing;
       sri.extra_cost = 0;
       secondary_class
-       = (enum reg_class) targetm.secondary_reload (true, sreg,
+       = (enum reg_class) targetm.secondary_reload (true, src,
                                                     (reg_class_t) dclass,
-                                                    sreg_mode, &sri);
+                                                    GET_MODE (src), &sri);
       /* Check the target hook consistency.  */
       lra_assert
        ((secondary_class == NO_REGS && sri.icode == CODE_FOR_nothing)
@@ -1174,14 +1167,12 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
   *change_p = true;
   new_reg = NULL_RTX;
   if (secondary_class != NO_REGS)
-    new_reg = lra_create_new_reg_with_unique_value (sreg_mode, NULL_RTX,
+    new_reg = lra_create_new_reg_with_unique_value (GET_MODE (src), NULL_RTX,
                                                    secondary_class,
                                                    "secondary");
   start_sequence ();
-  if (old_sreg != sreg)
-    sreg = copy_rtx (sreg);
   if (sri.icode == CODE_FOR_nothing)
-    lra_emit_move (new_reg, sreg);
+    lra_emit_move (new_reg, src);
   else
     {
       enum reg_class scratch_class;
@@ -1192,18 +1183,13 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
                     (insn_data[sri.icode].operand[2].mode, NULL_RTX,
                      scratch_class, "scratch"));
       emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest,
-                                     sreg, scratch_reg));
+                                     src, scratch_reg));
     }
   before = get_insns ();
   end_sequence ();
   lra_process_new_insns (curr_insn, before, NULL, "Inserting the move");
   if (new_reg != NULL_RTX)
-    {
-      if (GET_CODE (src) == SUBREG)
-       SUBREG_REG (src) = new_reg;
-      else
-       SET_SRC (curr_insn_set) = new_reg;
-    }
+    SET_SRC (curr_insn_set) = new_reg;
   else
     {
       if (lra_dump_file != NULL)
@@ -1382,13 +1368,13 @@ static int valid_address_p (machine_mode mode, rtx addr, addr_space_t as);
 
 /* Make reloads for subreg in operand NOP with internal subreg mode
    REG_MODE, add new reloads for further processing.  Return true if
-   any reload was generated.  */
+   any change was done.  */
 static bool
 simplify_operand_subreg (int nop, machine_mode reg_mode)
 {
   int hard_regno;
   rtx_insn *before, *after;
-  machine_mode mode;
+  machine_mode mode, innermode;
   rtx reg, new_reg;
   rtx operand = *curr_id->operand_loc[nop];
   enum reg_class regclass;
@@ -1401,6 +1387,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
 
   mode = GET_MODE (operand);
   reg = SUBREG_REG (operand);
+  innermode = GET_MODE (reg);
   type = curr_static_id->operand[nop].type;
   /* If we change address for paradoxical subreg of memory, the
      address might violate the necessary alignment or the access might
@@ -1419,7 +1406,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
       alter_subreg (curr_id->operand_loc[nop], false);
       subst = *curr_id->operand_loc[nop];
       lra_assert (MEM_P (subst));
-      if (! valid_address_p (GET_MODE (reg), XEXP (reg, 0),
+      if (! valid_address_p (innermode, XEXP (reg, 0),
                             MEM_ADDR_SPACE (reg))
          || valid_address_p (GET_MODE (subst), XEXP (subst, 0),
                              MEM_ADDR_SPACE (subst)))
@@ -1434,6 +1421,20 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
       alter_subreg (curr_id->operand_loc[nop], false);
       return true;
     }
+  else if (CONSTANT_P (reg))
+    {
+      /* Try to simplify subreg of constant.  It is usually result of
+        equivalence substitution.  */
+      if (innermode == VOIDmode
+         && (innermode = original_subreg_reg_mode[nop]) == VOIDmode)
+       innermode = curr_static_id->operand[nop].mode;
+      if ((new_reg = simplify_subreg (mode, reg, innermode,
+                                     SUBREG_BYTE (operand))) != NULL_RTX)
+       {
+         *curr_id->operand_loc[nop] = new_reg;
+         return true;
+       }
+    }
   /* Put constant into memory when we have mixed modes.  It generates
      a better code in most cases as it does not need a secondary
      reload memory.  It also prevents LRA looping when LRA is using
@@ -1453,9 +1454,9 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
        && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
        /* Don't reload paradoxical subregs because we could be looping
          having repeatedly final regno out of hard regs range.  */
-       && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+       && (hard_regno_nregs[hard_regno][innermode]
           >= hard_regno_nregs[hard_regno][mode])
-       && simplify_subreg_regno (hard_regno, GET_MODE (reg),
+       && simplify_subreg_regno (hard_regno, innermode,
                                 SUBREG_BYTE (operand), mode) < 0
        /* Don't reload subreg for matching reload.  It is actually
          valid subreg in LRA.  */
@@ -1481,7 +1482,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
          bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
 
          insert_before = (type != OP_OUT
-                          || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode));
+                          || GET_MODE_SIZE (innermode) > GET_MODE_SIZE (mode));
          insert_after = (type != OP_IN);
          insert_move_for_subreg (insert_before ? &before : NULL,
                                  insert_after ? &after : NULL,
@@ -1524,7 +1525,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
   else if (REG_P (reg)
           && REGNO (reg) >= FIRST_PSEUDO_REGISTER
           && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
-          && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+          && (hard_regno_nregs[hard_regno][innermode]
               < hard_regno_nregs[hard_regno][mode])
           && (regclass = lra_get_allocno_class (REGNO (reg)))
           && (type != OP_IN
@@ -1542,7 +1543,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
          bool insert_before, insert_after;
 
          PUT_MODE (new_reg, mode);
-          subreg = simplify_gen_subreg (GET_MODE (reg), new_reg, mode, 0);
+          subreg = simplify_gen_subreg (innermode, new_reg, mode, 0);
          bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
 
          insert_before = (type != OP_OUT);
@@ -1646,7 +1647,7 @@ prohibited_class_reg_set_mode_p (enum reg_class rclass,
 {
   HARD_REG_SET temp;
   
-  lra_assert (hard_reg_set_subset_p (set, reg_class_contents[rclass]));
+  lra_assert (hard_reg_set_subset_p (reg_class_contents[rclass], set));
   COPY_HARD_REG_SET (temp, set);
   AND_COMPL_HARD_REG_SET (temp, lra_no_alloc_regs);
   return (hard_reg_set_subset_p
@@ -2678,7 +2679,7 @@ base_to_reg (struct address_info *ad)
                                    : *ad->disp_term);
   if (!valid_address_p (ad->mode, new_inner, ad->as))
     return NULL_RTX;
-  insn = emit_insn (gen_rtx_SET (ad->mode, new_reg, *ad->base_term));
+  insn = emit_insn (gen_rtx_SET (new_reg, *ad->base_term));
   code = recog_memoized (insn);
   if (code < 0)
     {
@@ -2950,42 +2951,42 @@ process_address_1 (int nop, bool check_only_p,
          rtx addr = *ad.inner;
 
          new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "addr");
-#ifdef HAVE_lo_sum
-         {
-           rtx_insn *insn;
-           rtx_insn *last = get_last_insn ();
-
-           /* addr => lo_sum (new_base, addr), case (2) above.  */
-           insn = emit_insn (gen_rtx_SET
-                             (VOIDmode, new_reg,
-                              gen_rtx_HIGH (Pmode, copy_rtx (addr))));
-           code = recog_memoized (insn);
-           if (code >= 0)
-             {
-               *ad.inner = gen_rtx_LO_SUM (Pmode, new_reg, addr);
-               if (! valid_address_p (ad.mode, *ad.outer, ad.as))
-                 {
-                   /* Try to put lo_sum into register.  */
-                   insn = emit_insn (gen_rtx_SET
-                                     (VOIDmode, new_reg,
-                                      gen_rtx_LO_SUM (Pmode, new_reg, addr)));
-                   code = recog_memoized (insn);
-                   if (code >= 0)
-                     {
-                       *ad.inner = new_reg;
-                       if (! valid_address_p (ad.mode, *ad.outer, ad.as))
-                         {
-                           *ad.inner = addr;
-                           code = -1;
-                         }
-                     }
-                   
-                 }
-             }
-           if (code < 0)
-             delete_insns_since (last);
-         }
-#endif
+         if (HAVE_lo_sum)
+           {
+             rtx_insn *insn;
+             rtx_insn *last = get_last_insn ();
+
+             /* addr => lo_sum (new_base, addr), case (2) above.  */
+             insn = emit_insn (gen_rtx_SET
+                               (new_reg,
+                                gen_rtx_HIGH (Pmode, copy_rtx (addr))));
+             code = recog_memoized (insn);
+             if (code >= 0)
+               {
+                 *ad.inner = gen_rtx_LO_SUM (Pmode, new_reg, addr);
+                 if (! valid_address_p (ad.mode, *ad.outer, ad.as))
+                   {
+                     /* Try to put lo_sum into register.  */
+                     insn = emit_insn (gen_rtx_SET
+                                       (new_reg,
+                                        gen_rtx_LO_SUM (Pmode, new_reg, addr)));
+                     code = recog_memoized (insn);
+                     if (code >= 0)
+                       {
+                         *ad.inner = new_reg;
+                         if (! valid_address_p (ad.mode, *ad.outer, ad.as))
+                           {
+                             *ad.inner = addr;
+                             code = -1;
+                           }
+                       }
+
+                   }
+               }
+             if (code < 0)
+               delete_insns_since (last);
+           }
+
          if (code < 0)
            {
              /* addr => new_base, case (2) above.  */
@@ -3283,12 +3284,9 @@ simple_move_p (void)
 static inline void
 swap_operands (int nop)
 {
-  machine_mode mode = curr_operand_mode[nop];
-  curr_operand_mode[nop] = curr_operand_mode[nop + 1];
-  curr_operand_mode[nop + 1] = mode;
-  rtx x = *curr_id->operand_loc[nop];
-  *curr_id->operand_loc[nop] = *curr_id->operand_loc[nop + 1];
-  *curr_id->operand_loc[nop + 1] = x;
+  std::swap (curr_operand_mode[nop], curr_operand_mode[nop + 1]);
+  std::swap (original_subreg_reg_mode[nop], original_subreg_reg_mode[nop + 1]);
+  std::swap (*curr_id->operand_loc[nop], *curr_id->operand_loc[nop + 1]);
   /* Swap the duplicates too.  */
   lra_update_dup (curr_id, nop);
   lra_update_dup (curr_id, nop + 1);
@@ -3341,12 +3339,10 @@ curr_insn_transform (bool check_only_p)
   if (JUMP_P (curr_insn) || CALL_P (curr_insn))
     no_output_reloads_p = true;
 
-#ifdef HAVE_cc0
-  if (reg_referenced_p (cc0_rtx, PATTERN (curr_insn)))
+  if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (curr_insn)))
     no_input_reloads_p = true;
-  if (reg_set_p (cc0_rtx, PATTERN (curr_insn)))
+  if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (curr_insn)))
     no_output_reloads_p = true;
-#endif
 
   n_operands = curr_static_id->n_operands;
   n_alternatives = curr_static_id->n_alternatives;
@@ -3389,21 +3385,26 @@ curr_insn_transform (bool check_only_p)
        if (GET_CODE (old) == SUBREG)
          old = SUBREG_REG (old);
        subst = get_equiv_with_elimination (old, curr_insn);
+       original_subreg_reg_mode[i] = VOIDmode;
        if (subst != old)
          {
            subst = copy_rtx (subst);
            lra_assert (REG_P (old));
-           if (GET_CODE (op) == SUBREG)
-             SUBREG_REG (op) = subst;
-           else
+           if (GET_CODE (op) != SUBREG)
              *curr_id->operand_loc[i] = subst;
+           else
+             {
+               SUBREG_REG (op) = subst;
+               if (GET_MODE (subst) == VOIDmode)
+                 original_subreg_reg_mode[i] = GET_MODE (old);
+             }
            if (lra_dump_file != NULL)
              {
                fprintf (lra_dump_file,
                         "Changing pseudo %d in operand %i of insn %u on equiv ",
                         REGNO (old), i, INSN_UID (curr_insn));
                dump_value_slim (lra_dump_file, subst, 1);
-             fprintf (lra_dump_file, "\n");
+               fprintf (lra_dump_file, "\n");
              }
            op_change_p = change_p = true;
          }
@@ -4125,7 +4126,7 @@ contains_deleted_insn_p (rtx_insn_list *list)
 
 /* Return true if X contains a pseudo dying in INSN.  */
 static bool
-dead_pseudo_p (rtx x, rtx insn)
+dead_pseudo_p (rtx x, rtx_insn *insn)
 {
   int i, j;
   const char *fmt;
@@ -4750,7 +4751,7 @@ inherit_reload_reg (bool def_p, int original_regno,
                   "    Inheritance reuse change %d->%d (bb%d):\n",
                   original_regno, REGNO (new_reg),
                   BLOCK_FOR_INSN (usage_insn)->index);
-         dump_insn_slim (lra_dump_file, usage_insn);
+         dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn));
        }
     }
   if (lra_dump_file != NULL)
@@ -5010,7 +5011,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
        {
          fprintf (lra_dump_file, "    Split reuse change %d->%d:\n",
                   original_regno, REGNO (new_reg));
-         dump_insn_slim (lra_dump_file, usage_insn);
+         dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn));
        }
     }
   lra_assert (NOTE_P (usage_insn) || NONDEBUG_INSN_P (usage_insn));
@@ -5551,7 +5552,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
                           || reg_renumber[src_regno] >= 0)
                    {
                      bool before_p;
-                     rtx use_insn = curr_insn;
+                     rtx_insn *use_insn = curr_insn;
 
                      before_p = (JUMP_P (curr_insn)
                                  || (CALL_P (curr_insn) && reg->type == OP_IN));
@@ -5667,7 +5668,8 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
 /* This value affects EBB forming.  If probability of edge from EBB to
    a BB is not greater than the following value, we don't add the BB
    to EBB.  */
-#define EBB_PROBABILITY_CUTOFF ((REG_BR_PROB_BASE * 50) / 100)
+#define EBB_PROBABILITY_CUTOFF \
+  ((REG_BR_PROB_BASE * LRA_INHERITANCE_EBB_PROBABILITY_CUTOFF) / 100)
 
 /* Current number of inheritance/split iteration.  */
 int lra_inheritance_iter;
@@ -5713,7 +5715,7 @@ lra_inheritance (void)
          e = find_fallthru_edge (bb->succs);
          if (! e)
            break;
-         if (e->probability <= EBB_PROBABILITY_CUTOFF)
+         if (e->probability < EBB_PROBABILITY_CUTOFF)
            break;
          bb = bb->next_bb;
        }