i386.c (legitimize_tls_address): Generate tls_initial_exec_64_sun only when !TARGET_X32.
[gcc.git] / gcc / reload1.c
index f9abf723152d2b9521283e1a522c193e4b5b9269..c887614ce5b886898c72139baaec766df437ca8d 100644 (file)
@@ -462,7 +462,7 @@ init_reload (void)
                          gen_rtx_REG (Pmode, i));
 
       /* This way, we make sure that reg+reg is an offsettable address.  */
-      tem = plus_constant (tem, 4);
+      tem = plus_constant (Pmode, tem, 4);
 
       if (memory_address_p (QImode, tem))
        {
@@ -1746,11 +1746,12 @@ count_pseudo (int reg)
   int r = reg_renumber[reg];
   int nregs;
 
+  /* Ignore spilled pseudo-registers which can be here only if IRA is used.  */
+  if (ira_conflicts_p && r < 0)
+    return;
+
   if (REGNO_REG_SET_P (&pseudos_counted, reg)
-      || REGNO_REG_SET_P (&spilled_pseudos, reg)
-      /* Ignore spilled pseudo-registers which can be here only if IRA
-        is used.  */
-      || (ira_conflicts_p && r < 0))
+      || REGNO_REG_SET_P (&spilled_pseudos, reg))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1827,12 +1828,17 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 {
   int freq = REG_FREQ (reg);
   int r = reg_renumber[reg];
-  int nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
+  int nregs;
+
+  /* Ignore spilled pseudo-registers which can be here only if IRA is used.  */
+  if (ira_conflicts_p && r < 0)
+    return;
+
+  gcc_assert (r >= 0);
+
+  nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
 
-  /* Ignore spilled pseudo-registers which can be here only if IRA is
-     used.  */
-  if ((ira_conflicts_p && r < 0)
-      || REGNO_REG_SET_P (&spilled_pseudos, reg)
+  if (REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
 
@@ -2584,7 +2590,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
               ep++)
            if (ep->from_rtx == x && ep->can_eliminate)
-             return plus_constant (ep->to_rtx, ep->previous_offset);
+             return plus_constant (Pmode, ep->to_rtx, ep->previous_offset);
 
        }
       else if (reg_renumber && reg_renumber[regno] < 0
@@ -2640,7 +2646,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                  return ep->to_rtx;
                else
                  return gen_rtx_PLUS (Pmode, ep->to_rtx,
-                                      plus_constant (XEXP (x, 1),
+                                      plus_constant (Pmode, XEXP (x, 1),
                                                      ep->previous_offset));
              }
 
@@ -2717,7 +2723,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                ep->ref_outside_mem = 1;
 
              return
-               plus_constant (gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
+               plus_constant (Pmode,
+                              gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
                               ep->previous_offset * INTVAL (XEXP (x, 1)));
            }
 
@@ -3291,8 +3298,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
 
                if (base == ep->to_rtx)
                  {
-                   rtx src
-                     = plus_constant (ep->to_rtx, offset - ep->offset);
+                   rtx src = plus_constant (Pmode, ep->to_rtx,
+                                            offset - ep->offset);
 
                    new_body = old_body;
                    if (! replace)
@@ -3406,7 +3413,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
               had a PLUS before.  */
            if (offset == 0 || plus_src)
              {
-               rtx new_src = plus_constant (to_rtx, offset);
+               rtx new_src = plus_constant (GET_MODE (to_rtx),
+                                            to_rtx, offset);
 
                new_body = old_body;
                if (! replace)
@@ -5423,6 +5431,13 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
          return 0;
 
+      /* Reload register of reload with type RELOAD_FOR_INPADDR_ADDRESS
+        could be killed if the register is also used by reload with type
+        RELOAD_FOR_INPUT_ADDRESS, so check it.  */
+      if (type == RELOAD_FOR_INPADDR_ADDRESS
+         && TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], regno))
+       return 0;
+
       for (i = opnum + 1; i < reload_n_operands; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
            || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
@@ -5497,6 +5512,13 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
            || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
          return 0;
 
+      /* Reload register of reload with type RELOAD_FOR_OUTADDR_ADDRESS
+        could be killed if the register is also used by reload with type
+        RELOAD_FOR_OUTPUT_ADDRESS, so check it.  */
+      if (type == RELOAD_FOR_OUTADDR_ADDRESS
+         && TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+       return 0;
+
       return 1;
 
     default:
@@ -5505,15 +5527,15 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
 }
 
 /* Like reload_reg_reaches_end_p, but check that the condition holds for
-   every register in the range [REGNO, REGNO + NREGS).  */
+   every register in REG.  */
 
 static bool
-reload_regs_reach_end_p (unsigned int regno, int nregs, int reloadnum)
+reload_reg_rtx_reaches_end_p (rtx reg, int reloadnum)
 {
-  int i;
+  unsigned int i;
 
-  for (i = 0; i < nregs; i++)
-    if (!reload_reg_reaches_end_p (regno + i, reloadnum))
+  for (i = REGNO (reg); i < END_REGNO (reg); i++)
+    if (!reload_reg_reaches_end_p (i, reloadnum))
       return false;
   return true;
 }
@@ -7058,7 +7080,9 @@ static rtx operand_reload_insns = 0;
 static rtx other_operand_reload_insns = 0;
 static rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
 
-/* Values to be put in spill_reg_store are put here first.  */
+/* Values to be put in spill_reg_store are put here first.  Instructions
+   must only be placed here if the associated reload register reaches
+   the end of the instruction's reload sequence.  */
 static rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
 static HARD_REG_SET reg_reloaded_died;
 
@@ -7219,9 +7243,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
       /* Prevent normal processing of this reload.  */
       special = 1;
-      /* Output a special code sequence for this case, and forget about
-        spill reg information.  */
-      new_spill_reg_store[REGNO (reloadreg)] = NULL;
+      /* Output a special code sequence for this case.  */
       inc_for_reload (reloadreg, oldequiv, rl->out, rl->inc);
     }
 
@@ -7742,14 +7764,14 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                    rld[s].out_reg = rl->out_reg;
                    set = single_set (next);
                    if (set && SET_SRC (set) == s_reg
-                       && ! new_spill_reg_store[REGNO (s_reg)])
+                       && reload_reg_rtx_reaches_end_p (s_reg, s))
                      {
                        SET_HARD_REG_BIT (reg_is_output_reload,
                                          REGNO (s_reg));
                        new_spill_reg_store[REGNO (s_reg)] = next;
                      }
                  }
-               else
+               else if (reload_reg_rtx_reaches_end_p (rl_reg_rtx, j))
                  new_spill_reg_store[REGNO (rl_reg_rtx)] = p;
              }
          }
@@ -8009,6 +8031,15 @@ emit_reload_insns (struct insn_chain *chain)
       debug_reload_to_stream (dump_file);
     }
 
+  for (j = 0; j < n_reloads; j++)
+    if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
+      {
+       unsigned int i;
+
+       for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
+         new_spill_reg_store[i] = 0;
+      }
+
   /* Now output the instructions to copy the data into and out of the
      reload registers.  Do these in the order that the reloads were reported,
      since reloads of base and index registers precede reloads of operands
@@ -8016,14 +8047,6 @@ emit_reload_insns (struct insn_chain *chain)
 
   for (j = 0; j < n_reloads; j++)
     {
-      if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
-       {
-         unsigned int i;
-
-         for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
-           new_spill_reg_store[i] = 0;
-       }
-
       do_input_reload (chain, rld + j, j);
       do_output_reload (chain, rld + j, j);
     }
@@ -8149,15 +8172,13 @@ emit_reload_insns (struct insn_chain *chain)
                         && GET_CODE (rld[r].out) != PRE_MODIFY))))
            {
              rtx reg;
-             enum machine_mode mode;
-             int regno, nregs;
 
              reg = reload_reg_rtx_for_output[r];
-             mode = GET_MODE (reg);
-             regno = REGNO (reg);
-             nregs = hard_regno_nregs[regno][mode];
-             if (reload_regs_reach_end_p (regno, nregs, r))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 enum machine_mode mode = GET_MODE (reg);
+                 int regno = REGNO (reg);
+                 int nregs = hard_regno_nregs[regno][mode];
                  rtx out = (REG_P (rld[r].out)
                             ? rld[r].out
                             : rld[r].out_reg
@@ -8221,20 +8242,21 @@ emit_reload_insns (struct insn_chain *chain)
                   && !reg_set_p (reload_reg_rtx_for_input[r], PATTERN (insn)))
            {
              rtx reg;
-             enum machine_mode mode;
-             int regno, nregs;
 
              reg = reload_reg_rtx_for_input[r];
-             mode = GET_MODE (reg);
-             regno = REGNO (reg);
-             nregs = hard_regno_nregs[regno][mode];
-             if (reload_regs_reach_end_p (regno, nregs, r))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 enum machine_mode mode;
+                 int regno;
+                 int nregs;
                  int in_regno;
                  int in_nregs;
                  rtx in;
                  bool piecemeal;
 
+                 mode = GET_MODE (reg);
+                 regno = REGNO (reg);
+                 nregs = hard_regno_nregs[regno][mode];
                  if (REG_P (rld[r].in)
                      && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER)
                    in = rld[r].in;
@@ -8336,10 +8358,17 @@ emit_reload_insns (struct insn_chain *chain)
                 delete_output_reload.  */
              src_reg = reload_reg_rtx_for_output[r];
 
-             /* If this is an optional reload, try to find the source reg
-                from an input reload.  */
-             if (! src_reg)
+             if (src_reg)
                {
+                 if (reload_reg_rtx_reaches_end_p (src_reg, r))
+                   store_insn = new_spill_reg_store[REGNO (src_reg)];
+                 else
+                   src_reg = NULL_RTX;
+               }
+             else
+               {
+                 /* If this is an optional reload, try to find the
+                    source reg from an input reload.  */
                  rtx set = single_set (insn);
                  if (set && SET_DEST (set) == rld[r].out)
                    {
@@ -8357,8 +8386,6 @@ emit_reload_insns (struct insn_chain *chain)
                        }
                    }
                }
-             else
-               store_insn = new_spill_reg_store[REGNO (src_reg)];
              if (src_reg && REG_P (src_reg)
                  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
                {