]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/sh/sh.c
Update copyright years.
[thirdparty/gcc.git] / gcc / config / sh / sh.c
index da912ca9abdcb296744d08104df4c1e336d7b56f..1564109c9425752f7ceb8e6c7d67910a9d3f8b8b 100644 (file)
@@ -1,5 +1,5 @@
 /* Output routines for GCC for Renesas / SuperH SH.
-   Copyright (C) 1993-2019 Free Software Foundation, Inc.
+   Copyright (C) 1993-2021 Free Software Foundation, Inc.
    Contributed by Steve Chamberlain (sac@cygnus.com).
    Improved by Jim Wilson (wilson@cygnus.com).
 
@@ -249,7 +249,7 @@ static void sh_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
                                HOST_WIDE_INT, tree);
 static void sh_file_start (void);
 static bool sh_assemble_integer (rtx, unsigned int, int);
-static bool flow_dependent_p (rtx, rtx);
+static bool flow_dependent_p (rtx_insn *, rtx_insn *);
 static void flow_dependent_p_1 (rtx, const_rtx, void *);
 static int shiftcosts (rtx);
 static int and_xor_ior_costs (rtx, int);
@@ -661,6 +661,9 @@ static const struct attribute_spec sh_attribute_table[] =
 #undef TARGET_CONSTANT_ALIGNMENT
 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
 
+#undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 
@@ -734,7 +737,7 @@ got_mode_name:;
     {
       if (tokens[i] == "strict")
        ret.strict = true;
-      else if (tokens[i].find ("gbr-offset=") == 0)
+      else if (!tokens[i].compare (0, strlen ("gbr-offset="), "gbr-offset="))
        {
          std::string offset_str = tokens[i].substr (strlen ("gbr-offset="));
          ret.tcb_gbr_offset = integral_argument (offset_str.c_str ());
@@ -797,7 +800,7 @@ register_sh_passes (void)
   /* Run sh_treg_combine pass after register allocation and basic block
      reordering as this sometimes creates new opportunities.  */
   register_pass (make_pass_sh_treg_combine (g, true, "sh_treg_combine3"),
-                PASS_POS_INSERT_AFTER, "split4", 1);
+                PASS_POS_INSERT_AFTER, "split3", 1);
 
   /* Optimize sett and clrt insns, by e.g. removing them if the T bit value
      is known after a conditional branch.
@@ -955,11 +958,13 @@ sh_option_override (void)
   if (flag_unsafe_math_optimizations)
     {
       /* Enable fsca insn for SH4A if not otherwise specified by the user.  */
-      if (global_options_set.x_TARGET_FSCA == 0 && TARGET_SH4A_FP)
+      if (global_options_set.x_TARGET_FSCA == 0
+         && (TARGET_SH4A_FP || TARGET_FPU_SH4_300))
        TARGET_FSCA = 1;
 
       /* Enable fsrra insn for SH4A if not otherwise specified by the user.  */
-      if (global_options_set.x_TARGET_FSRRA == 0 && TARGET_SH4A_FP)
+      if (global_options_set.x_TARGET_FSRRA == 0
+         && (TARGET_SH4A_FP || TARGET_FPU_SH4_300))
        TARGET_FSRRA = 1;
     }
 
@@ -2103,7 +2108,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
       lsw_taken = EQ;
       if (prob.initialized_p ())
        {
-         /* FIXME: This is not optimal.  We do not really know the probablity
+         /* FIXME: This is not optimal.  We do not really know the probability
             that values differ by MCW only, but we should probably distribute
             probabilities more evenly.  */
          msw_skip_prob = rev_prob;
@@ -6703,13 +6708,13 @@ output_stack_adjust (int size, rtx reg, int epilogue_p,
             to handle this case, so just die when we see it.  */
          if (epilogue_p < 0
              || current_function_interrupt
-             || ! call_really_used_regs[temp] || fixed_regs[temp])
+             || ! call_used_regs[temp] || fixed_regs[temp])
            temp = -1;
          if (temp < 0 && ! current_function_interrupt && epilogue_p >= 0)
            {
-             HARD_REG_SET temps;
-             COPY_HARD_REG_SET (temps, call_used_reg_set);
-             AND_COMPL_HARD_REG_SET (temps, call_fixed_reg_set);
+             HARD_REG_SET temps = (regs_invalidated_by_call
+                                   & ~fixed_reg_set
+                                   & savable_regs);
              if (epilogue_p > 0)
                {
                  int nreg = 0;
@@ -6743,7 +6748,7 @@ output_stack_adjust (int size, rtx reg, int epilogue_p,
            {
              HARD_REG_SET temps;
 
-             COPY_HARD_REG_SET (temps, *live_regs_mask);
+             temps = *live_regs_mask;
              CLEAR_HARD_REG_BIT (temps, REGNO (reg));
              temp = scavenge_reg (&temps);
            }
@@ -6908,11 +6913,8 @@ push_regs (HARD_REG_SET *mask, bool interrupt_handler)
       if (i == FIRST_FP_REG && interrupt_handler && TARGET_FMOVD
          && hard_reg_set_intersect_p (*mask, reg_class_contents[DF_REGS]))
        {
-         HARD_REG_SET unsaved;
-
          push (FPSCR_REG);
-         COMPL_HARD_REG_SET (unsaved, *mask);
-         fpscr_set_from_mem (NORMAL_MODE (FP_MODE), unsaved);
+         fpscr_set_from_mem (NORMAL_MODE (FP_MODE), ~*mask);
          skip_fpscr = true;
        }
       if (i != PR_REG
@@ -7012,7 +7014,7 @@ calc_live_regs (HARD_REG_SET *live_regs_mask)
   else if (TARGET_FPU_DOUBLE && TARGET_FMOVD && TARGET_FPU_SINGLE)
     for (int count = 0, reg = FIRST_FP_REG; reg <= LAST_FP_REG; reg += 2)
       if (df_regs_ever_live_p (reg) && df_regs_ever_live_p (reg+1)
-         && (! call_really_used_regs[reg]
+         && (! call_used_regs[reg]
              || interrupt_handler)
          && ++count > 2)
        {
@@ -7043,7 +7045,7 @@ calc_live_regs (HARD_REG_SET *live_regs_mask)
          : interrupt_handler
          ? (/* Need to save all the regs ever live.  */
             (df_regs_ever_live_p (reg)
-             || (call_really_used_regs[reg]
+             || (call_used_regs[reg]
                  && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG
                      || reg == PIC_OFFSET_TABLE_REGNUM)
                  && has_call))
@@ -7056,9 +7058,10 @@ calc_live_regs (HARD_REG_SET *live_regs_mask)
          : (/* Only push those regs which are used and need to be saved.  */
             (false)
             || (df_regs_ever_live_p (reg)
-                && ((!call_really_used_regs[reg]
+                && ((!call_used_regs[reg]
                      && !(reg != PIC_OFFSET_TABLE_REGNUM
-                          && fixed_regs[reg] && call_used_regs[reg]))
+                          && fixed_regs[reg]
+                          && call_used_or_fixed_reg_p (reg)))
                     || (trapa_handler && reg == FPSCR_REG && TARGET_FPU_ANY)))
             || (crtl->calls_eh_return
                 && (reg == EH_RETURN_DATA_REGNO (0)
@@ -7901,7 +7904,7 @@ sh_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
 {
   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
 
-  if (targetm.calls.must_pass_in_stack (arg.mode, arg.type))
+  if (targetm.calls.must_pass_in_stack (arg))
     return true;
 
   /* ??? std_gimplify_va_arg_expr passes NULL for cum.  That function
@@ -8291,7 +8294,7 @@ sh_fix_range (const char *const_str)
        }
 
       for (int i = first; i <= last; ++i)
-       fixed_regs[i] = call_used_regs[i] = 1;
+       fixed_regs[i] = 1;
 
       if (!comma)
        break;
@@ -8811,7 +8814,7 @@ reg_unused_after (rtx reg, rtx_insn *insn)
       if (set == NULL && reg_overlap_mentioned_p (reg, PATTERN (insn)))
        return false;
 
-      if (code == CALL_INSN && call_really_used_regs[REGNO (reg)])
+      if (code == CALL_INSN && call_used_regs[REGNO (reg)])
        return true;
     }
   return true;
@@ -9633,11 +9636,11 @@ sh_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
 /* Check if INSN is flow-dependent on DEP_INSN.  Can also be used to check
    if DEP_INSN is anti-flow dependent on INSN.  */
 static bool
-flow_dependent_p (rtx insn, rtx dep_insn)
+flow_dependent_p (rtx_insn *insn, rtx_insn *dep_insn)
 {
   rtx tmp = PATTERN (insn);
 
-  note_stores (PATTERN (dep_insn), flow_dependent_p_1, &tmp);
+  note_stores (dep_insn, flow_dependent_p_1, &tmp);
   return tmp == NULL_RTX;
 }
 
@@ -10636,7 +10639,7 @@ sh_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
              && ((regno - FIRST_FP_REG) & 1) == 0)))
     return mode;
 
-  return choose_hard_reg_mode (regno, nregs, false);
+  return choose_hard_reg_mode (regno, nregs, NULL);
 }
 
 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
@@ -10818,16 +10821,16 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
      registers are used for argument passing, are callee-saved, or reserved.  */
   /* We need to check call_used_regs / fixed_regs in case -fcall_saved-reg /
      -ffixed-reg has been used.  */
-  if (! call_used_regs[0] || fixed_regs[0])
+  if (! call_used_or_fixed_reg_p (0) || fixed_regs[0])
     error ("r0 needs to be available as a call-clobbered register");
   scratch0 = scratch1 = scratch2 = gen_rtx_REG (Pmode, 0);
 
     {
-      if (call_used_regs[1] && ! fixed_regs[1])
+      if (call_used_or_fixed_reg_p (1) && ! fixed_regs[1])
        scratch1 = gen_rtx_REG (ptr_mode, 1);
       /* N.B., if not TARGET_HITACHI, register 2 is used to pass the pointer
         pointing where to return struct values.  */
-      if (call_used_regs[3] && ! fixed_regs[3])
+      if (call_used_or_fixed_reg_p (3) && ! fixed_regs[3])
        scratch2 = gen_rtx_REG (Pmode, 3);
     }
 
@@ -11449,32 +11452,28 @@ sh_conditional_register_usage (void)
 {
   for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
     if (! VALID_REGISTER_P (regno))
-      fixed_regs[regno] = call_used_regs[regno] = 1;
+      fixed_regs[regno] = 1;
   /* R8 and R9 are call-clobbered on SH5, but not on earlier SH ABIs.  */
   if (flag_pic)
-    {
-      fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
-      call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
-    }
+    fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
   if (TARGET_FDPIC)
     {
       fixed_regs[PIC_REG] = 1;
       call_used_regs[PIC_REG] = 1;
-      call_really_used_regs[PIC_REG] = 1;
     }
   /* Renesas saves and restores mac registers on call.  */
   if (TARGET_HITACHI && ! TARGET_NOMACSAVE)
     {
-      call_really_used_regs[MACH_REG] = 0;
-      call_really_used_regs[MACL_REG] = 0;
+      call_used_regs[MACH_REG] = 0;
+      call_used_regs[MACL_REG] = 0;
     }
 
   for (int regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)
-    if (! fixed_regs[regno] && call_really_used_regs[regno])
+    if (! fixed_regs[regno] && call_used_regs[regno])
       SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
 
-  call_really_used_regs[FPSCR_MODES_REG] = 0;
-  call_really_used_regs[FPSCR_STAT_REG] = 0;
+  call_used_regs[FPSCR_MODES_REG] = 0;
+  call_used_regs[FPSCR_STAT_REG] = 0;
 }
 
 /* Implement TARGET_LEGITIMATE_CONSTANT_P
@@ -11700,7 +11699,7 @@ sh_find_equiv_gbr_addr (rtx_insn* insn, rtx mem)
        {
          if (CALL_P (DF_REF_INSN (d)))
            {
-             if (REGNO_REG_SET_P (regs_invalidated_by_call_regset, GBR_REG))
+             if (TEST_HARD_REG_BIT (regs_invalidated_by_call, GBR_REG))
                return NULL_RTX;
              else
                continue;
@@ -12071,9 +12070,11 @@ sh_extending_set_of_reg::use_as_extended_reg (rtx_insn* use_at_insn) const
        rtx r = gen_reg_rtx (SImode);
        rtx_insn* i0;
        if (from_mode == QImode)
-         i0 = emit_insn_after (gen_extendqisi2 (r, set_src), insn);
+         i0 = sh_check_add_incdec_notes (
+                       emit_insn_after (gen_extendqisi2 (r, set_src), insn));
        else if (from_mode == HImode)
-         i0 = emit_insn_after (gen_extendhisi2 (r, set_src), insn);
+         i0 = sh_check_add_incdec_notes (
+                       emit_insn_after (gen_extendhisi2 (r, set_src), insn));
        else
          gcc_unreachable ();
 
@@ -12491,7 +12492,7 @@ static void
 sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
                  int prev_mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED)
 {
-  if ((TARGET_SH4A_FP || TARGET_SH4_300)
+  if ((TARGET_SH4A_FP || TARGET_FPU_SH4_300)
       && prev_mode != FP_MODE_NONE && prev_mode != mode)
     {
       emit_insn (gen_toggle_pr ());