+2018-11-14 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.h (reg_class): Reorder registers classes, remove
+ unused register classes.
+ (REG_CLASS_NAMES): Likewise.
+ (REG_CLASS_CONTENTS): Likewise.
+ (FIXED_REGISTERS): Make lp_count fixed.
+ (BASE_REG_CLASS): Remove ACC16_BASE_REGS reference.
+ (PROGRAM_COUNTER_REGNO): Remove.
+ * config/arc/arc.c (arc_conditional_register_usage): Remove unused
+ register classes, use constants for register numbers, remove
+ reg_class_contents references.
+ (arc_process_double_reg_moves): Add asserts.
+ (arc_secondary_reload): Remove LPCOUNT_REG reference, use
+ lra_in_progress predicate.
+ (arc_init_reg_tables): Remove unused register classes.
+ (arc_register_move_cost): Likewise.
+ (arc_preferred_reload_class): Likewise.
+ (hwloop_optimize): Update rtx patterns involving lp_count
+ register.
+ (arc_return_address_register): Rename ILINK1, INLINK2 regnums
+ macros.
+ * config/arc/constraints.md ("c"): Choose between GENERAL_REGS and
+ CHEAP_CORE_REGS. Former one will be used for LRA.
+ ("Rac"): Choose between GENERAL_REGS and ALL_CORE_REGS. Former
+ one will be used for LRA.
+ ("w"): Choose between GENERAL_REGS and WRITABLE_CORE_REGS. Former
+ one will be used for LRA.
+ ("W"): Choose between GENERAL_REGS and MPY_WRITABLE_CORE_REGS.
+ Former one will be used for LRA.
+ ("f"): Delete constraint.
+ ("k"): Likewise.
+ ("e"): Likewise.
+ ("l"): Change it from register constraint to constraint.
+ * config/arc/arc.md (movqi_insn): Remove unsed lp_count constraints.
+ (movhi_insn): Likewise.
+ (movsi_insn): Update pattern.
+ (arc_lp): Likewise.
+ (dbnz): Likewise.
+ (stack_tie): Remove 'b' constraint letter.
+ (R4_REG): Define.
+ (R9_REG, R15_REG, R16_REG, R25_REG): Likewise.
+ (R32_REG, R40_REG, R41_REG, R42_REG, R43_REG, R44_REG): Likewise.
+ (R57_REG, R59_REG, PCL_REG): Likewise.
+ (ILINK1_REGNUM): Renamed to ILINK1_REG.
+ (ILINK2_REGNUM): Renamed to ILINK2_REG.
+ (Rgp): Remove.
+ (SP_REGS): Likewise.
+ (Rcw): Remove unused reg classes.
+ * config/arc/predicates.md (dest_reg_operand): Just default on
+ register_operand predicate.
+ (mpy_dest_reg_operand): Likewise.
+ (move_dest_operand): Use macros instead of constants.
+ * config/arc/arc.opt (mlra): Switch to lra as default.
+
2018-11-14 Richard Biener <rguenther@suse.de>
PR tree-optimization/87974
if (cl == DOUBLE_REGS)
return GENERAL_REGS;
- /* The loop counter register can be stored, but not loaded directly. */
- if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
- && in_p && MEM_P (x))
- return GENERAL_REGS;
-
/* If we have a subreg (reg), where reg is a pseudo (that will end in
a memory location), then we may need a scratch register to handle
the fp/sp+largeoffset address. */
if (regno != -1)
return NO_REGS;
- /* It is a pseudo that ends in a stack location. */
- if (reg_equiv_mem (REGNO (x)))
+ /* It is a pseudo that ends in a stack location. This
+ procedure only works with the old reload step. */
+ if (reg_equiv_mem (REGNO (x)) && !lra_in_progress)
{
/* Get the equivalent address and check the range of the
offset. */
enum reg_class
arc_preferred_reload_class (rtx, enum reg_class cl)
{
- if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
- return GENERAL_REGS;
return cl;
}
strcpy (rname29, "ilink");
strcpy (rname30, "r30");
- if (!TEST_HARD_REG_BIT (overrideregs, 30))
+ if (!TEST_HARD_REG_BIT (overrideregs, R30_REG))
{
/* No user interference. Set the r30 to be used by the
compiler. */
- call_used_regs[30] = 1;
- fixed_regs[30] = 0;
+ call_used_regs[R30_REG] = 1;
+ fixed_regs[R30_REG] = 0;
- arc_regno_reg_class[30] = WRITABLE_CORE_REGS;
- SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], 30);
- SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], 30);
- SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], 30);
- SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], 30);
+ arc_regno_reg_class[R30_REG] = GENERAL_REGS;
}
}
if (TARGET_MUL64_SET)
{
- fix_start = 57;
- fix_end = 59;
+ fix_start = R57_REG;
+ fix_end = R59_REG;
/* We don't provide a name for mmed. In rtl / assembly resource lists,
you are supposed to refer to it as mlo & mhi, e.g
if (TARGET_MULMAC_32BY16_SET)
{
- fix_start = 56;
- fix_end = fix_end > 57 ? fix_end : 57;
+ fix_start = MUL32x16_REG;
+ fix_end = fix_end > R57_REG ? fix_end : R57_REG;
strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
}
/* Reduced configuration: don't use r4-r9, r16-r25. */
if (TARGET_RF16)
{
- for (i = 4; i <= 9; i++)
- {
- fixed_regs[i] = call_used_regs[i] = 1;
- }
- for (i = 16; i <= 25; i++)
- {
- fixed_regs[i] = call_used_regs[i] = 1;
- }
- }
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (!call_used_regs[regno])
- CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
- for (regno = 32; regno < 60; regno++)
- if (!fixed_regs[regno])
- SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
- if (!TARGET_ARC600_FAMILY)
- {
- for (regno = 32; regno <= 60; regno++)
- CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
-
- /* If they have used -ffixed-lp_count, make sure it takes
- effect. */
- if (fixed_regs[LP_COUNT])
- {
- CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
- CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
- CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
-
- /* Instead of taking out SF_MODE like below, forbid it outright. */
- arc_hard_regno_modes[60] = 0;
- }
- else
- arc_hard_regno_modes[60] = 1 << (int) S_MODE;
+ for (i = R4_REG; i <= R9_REG; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
+ for (i = R16_REG; i <= R25_REG; i++)
+ fixed_regs[i] = call_used_regs[i] = 1;
}
/* ARCHS has 64-bit data-path which makes use of the even-odd paired
registers. */
if (TARGET_HS)
- {
- for (regno = 1; regno < 32; regno +=2)
- {
- arc_hard_regno_modes[regno] = S_MODES;
- }
- }
+ for (regno = R1_REG; regno < R32_REG; regno +=2)
+ arc_hard_regno_modes[regno] = S_MODES;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (i < 29)
- {
- if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
- && ((i <= 3) || ((i >= 12) && (i <= 15))))
- arc_regno_reg_class[i] = ARCOMPACT16_REGS;
- else
- arc_regno_reg_class[i] = GENERAL_REGS;
- }
- else if (i < 60)
- arc_regno_reg_class[i]
- = (fixed_regs[i]
- ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
- ? CHEAP_CORE_REGS : ALL_CORE_REGS)
- : (((!TARGET_ARC600_FAMILY)
- && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
- ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
- else
- arc_regno_reg_class[i] = NO_REGS;
- }
-
- /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS / TARGET_RRQ_CLASS
- has not been activated. */
- if (!TARGET_Q_CLASS && !TARGET_RRQ_CLASS)
- CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
- if (!TARGET_Q_CLASS)
- CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
-
- gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
+ if (i < ILINK1_REG)
+ {
+ if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
+ && ((i <= R3_REG) || ((i >= R12_REG) && (i <= R15_REG))))
+ arc_regno_reg_class[i] = ARCOMPACT16_REGS;
+ else
+ arc_regno_reg_class[i] = GENERAL_REGS;
+ }
+ else if (i < LP_COUNT)
+ arc_regno_reg_class[i] = GENERAL_REGS;
+ else
+ arc_regno_reg_class[i] = NO_REGS;
/* Handle Special Registers. */
- arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
- if (!TARGET_V2)
- arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
- arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
- arc_regno_reg_class[60] = LPCOUNT_REG;
- arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
+ arc_regno_reg_class[CC_REG] = NO_REGS; /* CC_REG: must be NO_REGS. */
arc_regno_reg_class[62] = GENERAL_REGS;
if (TARGET_DPFP)
- {
- for (i = 40; i < 44; ++i)
- {
- arc_regno_reg_class[i] = DOUBLE_REGS;
-
- /* Unless they want us to do 'mov d1, 0x00000000' make sure
- no attempt is made to use such a register as a destination
- operand in *movdf_insn. */
- if (!TARGET_ARGONAUT_SET)
- {
- /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
- interpreted to mean they can use D1 or D2 in their insn. */
- CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
- CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
- CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
- CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
- }
- }
- }
+ for (i = R40_REG; i < R44_REG; ++i)
+ {
+ arc_regno_reg_class[i] = DOUBLE_REGS;
+ if (!TARGET_ARGONAUT_SET)
+ CLEAR_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i);
+ }
else
{
- /* Disable all DOUBLE_REGISTER settings,
- if not generating DPFP code. */
- arc_regno_reg_class[40] = ALL_REGS;
- arc_regno_reg_class[41] = ALL_REGS;
- arc_regno_reg_class[42] = ALL_REGS;
- arc_regno_reg_class[43] = ALL_REGS;
+ /* Disable all DOUBLE_REGISTER settings, if not generating DPFP
+ code. */
+ arc_regno_reg_class[R40_REG] = ALL_REGS;
+ arc_regno_reg_class[R41_REG] = ALL_REGS;
+ arc_regno_reg_class[R42_REG] = ALL_REGS;
+ arc_regno_reg_class[R43_REG] = ALL_REGS;
- fixed_regs[40] = 1;
- fixed_regs[41] = 1;
- fixed_regs[42] = 1;
- fixed_regs[43] = 1;
+ fixed_regs[R40_REG] = 1;
+ fixed_regs[R41_REG] = 1;
+ fixed_regs[R42_REG] = 1;
+ fixed_regs[R43_REG] = 1;
- arc_hard_regno_modes[40] = 0;
- arc_hard_regno_modes[42] = 0;
-
- CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
+ arc_hard_regno_modes[R40_REG] = 0;
+ arc_hard_regno_modes[R42_REG] = 0;
}
if (TARGET_SIMD_SET)
}
/* pc : r63 */
- arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
+ arc_regno_reg_class[PCL_REG] = NO_REGS;
/*ARCV2 Accumulator. */
if ((TARGET_V2
&& (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED))
|| TARGET_PLUS_DMPY)
{
- arc_regno_reg_class[ACCL_REGNO] = WRITABLE_CORE_REGS;
- arc_regno_reg_class[ACCH_REGNO] = WRITABLE_CORE_REGS;
- SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCL_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCH_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCL_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCH_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCL_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCH_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCL_REGNO);
- SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCH_REGNO);
+ arc_regno_reg_class[ACCL_REGNO] = GENERAL_REGS;
+ arc_regno_reg_class[ACCH_REGNO] = GENERAL_REGS;
/* Allow the compiler to freely use them. */
if (!TEST_HARD_REG_BIT (overrideregs, ACCL_REGNO))
delete_insn (loop->loop_end);
}
+/* Return the next insn after INSN that is not a NOTE, but stop the
+ search before we enter another basic block. This routine does not
+ look inside SEQUENCEs. */
+
+static rtx_insn *
+next_nonnote_insn_bb (rtx_insn *insn)
+{
+ while (insn)
+ {
+ insn = NEXT_INSN (insn);
+ if (insn == 0 || !NOTE_P (insn))
+ break;
+ if (NOTE_INSN_BASIC_BLOCK_P (insn))
+ return NULL;
+ }
+
+ return insn;
+}
+
/* Optimize LOOP. */
static bool
if (loop->depth > 1)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d is not innermost\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d is not innermost\n",
+ loop->loop_no);
return false;
}
if (!loop->incoming_dest)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d has more than one entry\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d has more than one entry\n",
+ loop->loop_no);
return false;
}
if (loop->incoming_dest != loop->head)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d is not entered from head\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d is not entered from head\n",
+ loop->loop_no);
return false;
}
if (loop->has_call || loop->has_asm)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d has invalid insn\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d has invalid insn\n",
+ loop->loop_no);
return false;
}
if (loop->iter_reg_used || loop->iter_reg_used_outside)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d uses iterator\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d uses iterator\n",
+ loop->loop_no);
return false;
}
if (!insn)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
+ loop->loop_no);
return false;
}
return false;
}
- /* Check if we use a register or not. */
+ /* Check if we use a register or not. */
if (!REG_P (loop->iter_reg))
{
if (dump_file)
- fprintf (dump_file, ";; loop %d iterator is MEM\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d iterator is MEM\n",
+ loop->loop_no);
+ return false;
+ }
+
+ /* Check if we use a register or not. */
+ if (!REG_P (loop->iter_reg))
+ {
+ if (dump_file)
+ fprintf (dump_file, ";; loop %d iterator is MEM\n",
+ loop->loop_no);
return false;
}
|| (loop->incoming_src
&& REGNO_REG_SET_P (df_get_live_out (loop->incoming_src),
LP_COUNT)))
- return false;
+ {
+ if (dump_file)
+ fprintf (dump_file, ";; loop %d, lp_count is alive", loop->loop_no);
+ return false;
+ }
else
need_fix = true;
}
{
/* The loop uses a R-register, but the lp_count is free, thus
use lp_count. */
- emit_insn (gen_movsi (lp_reg, iter_reg));
+ emit_insn (gen_rtx_SET (lp_reg, iter_reg));
SET_HARD_REG_BIT (loop->regs_set_in_loop, LP_COUNT);
iter_reg = lp_reg;
if (dump_file)
}
}
- insn = emit_insn (gen_arc_lp (iter_reg,
- loop->start_label,
+ insn = emit_insn (gen_arc_lp (loop->start_label,
loop->end_label));
seq = get_insns ();
seq = emit_label_before (gen_label_rtx (), seq);
new_bb = create_basic_block (seq, insn, entry_bb);
FOR_EACH_EDGE (e, ei, loop->incoming)
- {
- if (!(e->flags & EDGE_FALLTHRU))
- redirect_edge_and_branch_force (e, new_bb);
- else
- redirect_edge_succ (e, new_bb);
- }
+ {
+ if (!(e->flags & EDGE_FALLTHRU))
+ redirect_edge_and_branch_force (e, new_bb);
+ else
+ redirect_edge_succ (e, new_bb);
+ }
make_edge (new_bb, loop->head, 0);
}
{
#if 0
while (DEBUG_INSN_P (entry_after)
- || (NOTE_P (entry_after)
- && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
+ || (NOTE_P (entry_after)
+ && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK
+ /* Make sure we don't split a call and its corresponding
+ CALL_ARG_LOCATION note. */
+ && NOTE_KIND (entry_after) != NOTE_INSN_CALL_ARG_LOCATION))
entry_after = NEXT_INSN (entry_after);
#endif
- entry_after = next_nonnote_nondebug_insn_bb (entry_after);
+ entry_after = next_nonnote_insn_bb (entry_after);
gcc_assert (entry_after);
emit_insn_before (seq, entry_after);
}
- delete_insn (loop->loop_end);
/* Insert the loop end label before the last instruction of the
loop. */
emit_label_after (end_label, loop->last_insn);
arc_register_move_cost (machine_mode,
enum reg_class from_class, enum reg_class to_class)
{
- /* The ARC600 has no bypass for extension registers, hence a nop might be
- needed to be inserted after a write so that reads are safe. */
- if (TARGET_ARC600)
- {
- if (to_class == MPY_WRITABLE_CORE_REGS)
- return 3;
- /* Instructions modifying LP_COUNT need 4 additional cycles before
- the register will actually contain the value. */
- else if (to_class == LPCOUNT_REG)
- return 6;
- else if (to_class == WRITABLE_CORE_REGS)
- return 6;
- }
-
- /* Using lp_count as scratch reg is a VERY bad idea. */
- if (from_class == LPCOUNT_REG)
- return 1000;
- if (to_class == LPCOUNT_REG)
- return 6;
-
/* Force an attempt to 'mov Dy,Dx' to spill. */
if ((TARGET_ARC700 || TARGET_EM) && TARGET_DPFP
&& from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
static bool
arc_process_double_reg_moves (rtx *operands)
{
- rtx dest = operands[0];
- rtx src = operands[1];
-
enum usesDxState { none, srcDx, destDx, maxDx };
enum usesDxState state = none;
+ rtx dest = operands[0];
+ rtx src = operands[1];
if (refers_to_regno_p (40, 44, src, 0))
- state = srcDx;
+ {
+ state = srcDx;
+ gcc_assert (REG_P (dest));
+ }
if (refers_to_regno_p (40, 44, dest, 0))
{
/* Via arc_register_move_cost, we should never see D,D moves. */
+ gcc_assert (REG_P (src));
gcc_assert (state == none);
state = destDx;
}
if (ARC_INTERRUPT_P (fn_type))
{
if ((fn_type & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_FIRQ)) != 0)
- regno = ILINK1_REGNUM;
+ regno = ILINK1_REG;
else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
- regno = ILINK2_REGNUM;
+ regno = ILINK2_REG;
else
- gcc_unreachable ();
+ gcc_unreachable ();
}
else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
regno = RETURN_ADDR_REGNUM;
return false;
}
-#ifndef TARGET_NO_LRA
-#define TARGET_NO_LRA !TARGET_LRA
-#endif
+/* Return true if we use LRA instead of reload pass. */
-static bool
+bool
arc_lra_p (void)
{
- return !TARGET_NO_LRA;
+ return arc_lra_flag;
}
/* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
t = REGNO (rt);
t2 = REGNO (rt2);
- if ((t2 == PROGRAM_COUNTER_REGNO)
+ if ((t2 == PCL_REG)
|| (t % 2 != 0) /* First destination register is not even. */
|| (t2 != t + 1))
return false;
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-#define PROGRAM_COUNTER_REGNO 63
-
/* Standard register usage. */
/* Number of actual hardware registers.
1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 0, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
\
0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, \
{
NO_REGS,
R0_REGS, /* 'x' */
- GP_REG, /* 'Rgp' */
- FP_REG, /* 'f' */
- SP_REGS, /* 'b' */
- LPCOUNT_REG, /* 'l' */
- LINK_REGS, /* 'k' */
- DOUBLE_REGS, /* D0, D1 */
- SIMD_VR_REGS, /* VR00-VR63 */
- SIMD_DMA_CONFIG_REGS, /* DI0-DI7,DO0-DO7 */
+ R0R1_CD_REGS, /* 'Rsd' */
+ R0R3_CD_REGS, /* 'Rcd' */
ARCOMPACT16_REGS, /* 'q' */
- AC16_BASE_REGS, /* 'e' */
SIBCALL_REGS, /* "Rsc" */
- GENERAL_REGS, /* 'r' */
- MPY_WRITABLE_CORE_REGS, /* 'W' */
- WRITABLE_CORE_REGS, /* 'w' */
- CHEAP_CORE_REGS, /* 'c' */
- ALL_CORE_REGS, /* 'Rac' */
- R0R3_CD_REGS, /* 'Rcd' */
- R0R1_CD_REGS, /* 'Rsd' */
AC16_H_REGS, /* 'h' */
+ DOUBLE_REGS, /* 'D' */
+ GENERAL_REGS, /* 'r' */
+ SIMD_VR_REGS, /* 'v' */
+ SIMD_DMA_CONFIG_REGS, /* 'd' */
ALL_REGS,
LIM_REG_CLASSES
};
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "R0_REGS", \
- "GP_REG", \
- "FP_REG", \
- "SP_REGS", \
- "LPCOUNT_REG", \
- "LINK_REGS", \
- "DOUBLE_REGS", \
- "SIMD_VR_REGS", \
+{ \
+ "NO_REGS", \
+ "R0_REGS", \
+ "R0R1_CD_REGS", \
+ "R0R3_CD_REGS", \
+ "ARCOMPACT16_REGS", \
+ "AC16_H_REGS", \
+ "DOUBLE_REGS", \
+ "GENERAL_REGS", \
+ "SIMD_VR_REGS", \
"SIMD_DMA_CONFIG_REGS", \
- "ARCOMPACT16_REGS", \
- "AC16_BASE_REGS", \
- "SIBCALL_REGS", \
- "GENERAL_REGS", \
- "MPY_WRITABLE_CORE_REGS", \
- "WRITABLE_CORE_REGS", \
- "CHEAP_CORE_REGS", \
- "R0R3_CD_REGS", \
- "R0R1_CD_REGS", \
- "AC16_H_REGS", \
- "ALL_CORE_REGS", \
- "ALL_REGS" \
+ "ALL_REGS" \
}
/* Define which registers fit in which classes.
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
-{ \
- {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* No Registers */ \
- {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'x', r0 register , r0 */ \
- {0x04000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rgp', Global Pointer, r26 */ \
- {0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'f', Frame Pointer, r27 */ \
- {0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'b', Stack Pointer, r28 */ \
- {0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000000}, /* 'l', LPCOUNT Register, r60 */ \
- {0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'k', LINK Registers, r29-r31 */ \
- {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D', D1, D2 Registers */ \
- {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'V', VR00-VR63 Registers */ \
- {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'V', DI0-7,DO0-7 Registers */ \
- {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q', r0-r3, r12-r15 */ \
- {0x1000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'e', r0-r3, r12-r15, sp */ \
- {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* "Rsc", r0-r12 */ \
- {0x9fffffff, 0x80000000, 0x00000000, 0x00000000, 0x00000000}, /* 'r', r0-r28, blink, ap and pcl */ \
- {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'W', r0-r31 */ \
- /* Include ap / pcl in WRITABLE_CORE_REGS for sake of symmetry. As these \
- registers are fixed, it does not affect the literal meaning of the \
- constraints, but it makes it a superset of GENERAL_REGS, thus \
- enabling some operations that would otherwise not be possible. */ \
- {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'w', r0-r31, r60 */ \
- {0xffffffff, 0x9fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'c', r0-r60, ap, pcl */ \
- {0xffffffff, 0x9fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'Rac', r0-r60, ap, pcl */ \
- {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd', r0-r3 */ \
- {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd', r0-r1 */ \
- {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h', r0-28, r30 */ \
- {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* All Registers */ \
+{ \
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* NO_REGS. */\
+ {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'x'. */ \
+ {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd'. */ \
+ {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd'. */ \
+ {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q'. */ \
+ {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'. */ \
+ {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h'. */ \
+ {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D'. */ \
+ {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00000000}, /* 'r'. */ \
+ {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v'. */ \
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd'. */ \
+ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* ALL_REGS. */\
}
/* Local macros to mark the first and last regs of different classes. */
/* The class value for valid base registers. A base register is one used in
an address which is the register value plus a displacement. */
-#define BASE_REG_CLASS (TARGET_MIXED_CODE ? AC16_BASE_REGS : GENERAL_REGS)
+#define BASE_REG_CLASS GENERAL_REGS
/* These assume that REGNO is a hard or pseudo reg number.
They give nonzero only if REGNO is a hard reg of the suitable class
/* The default option for BI/BIH instructions. */
#define DEFAULT_BRANCH_INDEX 0
+#ifndef TARGET_LRA
+#define TARGET_LRA arc_lra_p()
+#endif
+
#endif /* GCC_ARC_H */
(R1_REG 1)
(R2_REG 2)
(R3_REG 3)
+ (R4_REG 4)
+
+ (R9_REG 9)
(R10_REG 10)
+
(R12_REG 12)
+
+ (R15_REG 15)
+ (R16_REG 16)
+
+ (R25_REG 25)
(SP_REG 28)
- (ILINK1_REGNUM 29)
- (ILINK2_REGNUM 30)
+ (ILINK1_REG 29)
+ (ILINK2_REG 30)
+ (R30_REG 30)
(RETURN_ADDR_REGNUM 31)
+ (R32_REG 32)
+ (R40_REG 40)
+ (R41_REG 41)
+ (R42_REG 42)
+ (R43_REG 43)
+ (R44_REG 44)
+ (R57_REG 57)
(MUL64_OUT_REG 58)
(MUL32x16_REG 56)
(ARCV2_ACC 58)
+ (R59_REG 59)
(LP_COUNT 60)
(CC_REG 61)
+ (PCL_REG 63)
(LP_START 144)
(LP_END 145)
]
; The iscompact attribute allows the epilogue expander to know for which
; insns it should lengthen the return insn.
(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l,???w,h,w*l,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc")
- (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,?Rac,i, ?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
+ [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc")
+ (match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"@
"if (prepare_move_operands (operands, HImode)) DONE;")
(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l,???w,Rcq#q,h,w*l,Rcq, S, r,r, Ucm,m,???m, m,VUsc")
- (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,?Rac, i,i, ?i, T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
+ [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,Rcq#q,h, w,Rcq, S, r,r, Ucm,m,???m, m,VUsc")
+ (match_operand:HI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac, i,i,?i, T,Rcq,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)
|| (CONSTANT_P (operands[1])
; the iscompact attribute allows the epilogue expander to know for which
; insns it should lengthen the return insn.
; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
-(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,w*l,w*l, w, w, w, w, ???w, ?w, w,Rcq#q, h, w*l,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m, m,VUsc")
- (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1, cL, I,Crr,Clo,Chi,Cbi,?Rac*l,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac,Cm3, C32"))]
+(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,wl, w, w, w, w, w,???w, ?w, w,Rcq#q, h, wl,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m, m,VUsc")
+ (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac,Cm3, C32"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| (CONSTANT_P (operands[1])
})
(define_insn "arc_lp"
- [(unspec:SI [(match_operand:SI 0 "register_operand" "l")]
+ [(unspec:SI [(reg:SI LP_COUNT)]
UNSPEC_ARC_LP)
- (use (label_ref (match_operand 1 "" "")))
- (use (label_ref (match_operand 2 "" "")))]
+ (use (label_ref (match_operand 0 "" "")))
+ (use (label_ref (match_operand 1 "" "")))]
""
- "lp\\t@%l2\\t; %0:@%l1->@%l2"
+ "lp\\t@%l1\\t; lp_count:@%l0->@%l1"
[(set_attr "type" "loop_setup")
(set_attr "length" "4")])
;; register, instead of going to memory.
(define_insn "loop_end"
[(set (pc)
- (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,0")
+ (if_then_else (ne (match_operand:SI 2 "nonimmediate_operand" "0,m")
(const_int 1))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_operand:SI 0 "nonimmediate_operand" "=l!r,m")
+ (set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
(plus (match_dup 2) (const_int -1)))
(unspec [(const_int 0)] UNSPEC_ARC_LP)
(clobber (match_scratch:SI 3 "=X,&r"))]
""
- "\\t;%0 %1 %2"
+ "; ZOL_END, begins @%l1"
[(set_attr "length" "0")
(set_attr "predicable" "no")
(set_attr "type" "loop_end")])
(define_insn_and_split "dbnz"
[(set (pc)
(if_then_else
- (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+r!l,m")
+ (ne (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+rl,m")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(define_insn "stack_tie"
[(set (mem:BLK (scratch))
- (unspec:BLK [(match_operand:SI 0 "register_operand" "rb")
- (match_operand:SI 1 "register_operand" "rb")]
+ (unspec:BLK [(match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r")]
UNSPEC_ARC_STKTIE))]
""
""
Pass -marclinux_prof option through to linker.
;; lra is still unproven for ARC, so allow to fall back to reload with -mno-lra.
-;Target InverseMask(NO_LRA)
-; lra still won't allow to configure libgcc; see PR rtl-optimization/55464.
-; so don't enable by default.
mlra
-Target Mask(LRA)
-Enable lra.
+Target Report Var(arc_lra_flag) Init(1) Save
+Use LRA instead of reload.
mlra-priority-none
Target RejectNegative Var(arc_lra_priority_tag, ARC_LRA_PRIORITY_NONE)
; result registers of ARC600.
; First, define a class for core registers that can be read cheaply. This
; is most or all core registers for ARC600, but only r0-r31 for ARC700
-(define_register_constraint "c" "CHEAP_CORE_REGS"
- "core register @code{r0}-@code{r31}, @code{ap},@code{pcl}")
+(define_register_constraint "c" "GENERAL_REGS"
+ "Legacy, core register @code{r0}-@code{r31}, @code{ap},@code{pcl}")
; All core regs - e.g. for when we must have a way to reload a register.
-(define_register_constraint "Rac" "ALL_CORE_REGS"
- "core register @code{r0}-@code{r60}, @code{ap},@code{pcl}")
+(define_register_constraint "Rac" "GENERAL_REGS"
+ "Legacy, core register @code{r0}-@code{r60}, @code{ap},@code{pcl}")
; Some core registers (.e.g lp_count) aren't general registers because they
; can't be used as the destination of a multi-cycle operation like
; load and/or multiply, yet they are still writable in the sense that
; register-register moves and single-cycle arithmetic (e.g "add", "and",
; but not "mpy") can write to them.
-(define_register_constraint "w" "WRITABLE_CORE_REGS"
- "writable core register: @code{r0}-@code{r31}, @code{r60}, nonfixed core register")
+(define_register_constraint "w" "GENERAL_REGS"
+ "Legacy, writable core register: @code{r0}-@code{r31}, @code{r60},
+ nonfixed core register")
-(define_register_constraint "W" "MPY_WRITABLE_CORE_REGS"
- "writable core register except @code{LP_COUNT} (@code{r60}): @code{r0}-@code{r31}, nonfixed core register")
+(define_register_constraint "W" "GENERAL_REGS"
+ "Legacy, writable core register except @code{LP_COUNT} (@code{r60}):
+ @code{r0}-@code{r31}, nonfixed core register")
-(define_register_constraint "l" "LPCOUNT_REG"
+(define_constraint "l"
"@internal
- Loop count register @code{r60}")
+ Loop count register @code{r60}"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == LP_COUNT")))
(define_register_constraint "x" "R0_REGS"
"@code{R0} register.")
-(define_register_constraint "Rgp" "GP_REG"
- "@internal
- Global Pointer register @code{r26}")
-
-(define_register_constraint "f" "FP_REG"
- "@internal
- Frame Pointer register @code{r27}")
-
-(define_register_constraint "b" "SP_REGS"
- "@internal
- Stack Pointer register @code{r28}")
-
-(define_register_constraint "k" "LINK_REGS"
- "@internal
- Link Registers @code{ilink1}:@code{r29}, @code{ilink2}:@code{r30},
- @code{blink}:@code{r31},")
-
(define_register_constraint "q" "TARGET_Q_CLASS ? ARCOMPACT16_REGS : NO_REGS"
"Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3},
@code{r12}-@code{r15}")
"Registers usable in NPS400 bitfield instructions: @code{r0}-@code{r3},
@code{r12}-@code{r15}")
-(define_register_constraint "e" "AC16_BASE_REGS"
- "Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
- instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}, @code{sp}")
-
(define_register_constraint "D" "DOUBLE_REGS"
"ARC FPX (dpfp) 64-bit registers. @code{D0}, @code{D1}")
(match_test
"TARGET_Rcw
&& REGNO (op) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
+ && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
REGNO (op))")))
(define_constraint "Rcr"
(define_predicate "dest_reg_operand"
(match_code "reg,subreg")
{
- rtx op0 = op;
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
- if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
- REGNO (op0))
- && !TEST_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS],
- REGNO (op0)))
- return 0;
return register_operand (op, mode);
})
(define_predicate "mpy_dest_reg_operand"
(match_code "reg,subreg")
{
- rtx op0 = op;
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
- if (REG_P (op0) && REGNO (op0) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (reg_class_contents[ALL_CORE_REGS],
- REGNO (op0))
- /* Make sure the destination register is not LP_COUNT. */
- && !TEST_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS],
- REGNO (op0)))
- return 0;
return register_operand (op, mode);
})
case REG :
/* Program Counter register cannot be the target of a move. It is
a readonly register. */
- if (REGNO (op) == PROGRAM_COUNTER_REGNO)
+ if (REGNO (op) == PCL_REG)
return 0;
else if (TARGET_MULMAC_32BY16_SET
- && (REGNO (op) == 56 || REGNO(op) == 57))
+ && (REGNO (op) == MUL32x16_REG || REGNO (op) == R57_REG))
return 0;
else if (TARGET_MUL64_SET
- && (REGNO (op) == 57 || REGNO(op) == 58 || REGNO(op) == 59 ))
+ && (REGNO (op) == R57_REG || REGNO (op) == MUL64_OUT_REG
+ || REGNO (op) == R59_REG))
return 0;
else if (REGNO (op) == LP_COUNT)
return 1;