From: Claudiu Zissulescu Date: Wed, 14 Nov 2018 09:45:39 +0000 (+0100) Subject: [ARC] Cleanup, fix and set LRA default. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=73dac59b57ad6af6a369f5005c979a20a2ad2954;p=gcc.git [ARC] Cleanup, fix and set LRA default. LP_COUNT register cannot be freely allocated by the compiler as it size, and/or content may change depending on the ARC hardware configuration. Thus, make this register fixed. Remove register classes and unused constraint letters. Cleanup the implementation of conditional_register_usage hook by using macros instead of magic constants and removing all references to reg_class_contents which are bringing so much grief when lra is enabled. gcc/ xxxx-xx-xx Claudiu Zissulescu * 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. From-SVN: r266100 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f1f2c4c957a..ab9e0010a9c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,58 @@ +2018-11-14 Claudiu Zissulescu + + * 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 PR tree-optimization/87974 diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 6bf8e852235..55175215bfe 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -734,11 +734,6 @@ arc_secondary_reload (bool in_p, 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. */ @@ -756,8 +751,9 @@ arc_secondary_reload (bool in_p, 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. */ @@ -1659,8 +1655,6 @@ enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER]; 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; } @@ -1758,25 +1752,21 @@ arc_conditional_register_usage (void) 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 @@ -1799,8 +1789,8 @@ arc_conditional_register_usage (void) 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"); } @@ -1862,130 +1852,59 @@ arc_conditional_register_usage (void) /* 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) @@ -2007,23 +1926,15 @@ arc_conditional_register_usage (void) } /* 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)) @@ -7801,6 +7712,25 @@ hwloop_fail (hwloop_info loop) 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 @@ -7818,32 +7748,32 @@ hwloop_optimize (hwloop_info loop) 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; } @@ -7851,8 +7781,8 @@ hwloop_optimize (hwloop_info loop) 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; } @@ -7876,8 +7806,8 @@ hwloop_optimize (hwloop_info loop) 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; } @@ -7895,12 +7825,21 @@ hwloop_optimize (hwloop_info loop) 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; } @@ -7918,7 +7857,11 @@ hwloop_optimize (hwloop_info loop) || (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; } @@ -8033,7 +7976,7 @@ hwloop_optimize (hwloop_info loop) { /* 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) @@ -8043,8 +7986,7 @@ hwloop_optimize (hwloop_info loop) } } - 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 (); @@ -8062,12 +8004,12 @@ hwloop_optimize (hwloop_info loop) 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); } @@ -8075,17 +8017,19 @@ hwloop_optimize (hwloop_info loop) { #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); @@ -8737,26 +8681,6 @@ int 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) @@ -9975,17 +9899,20 @@ split_subsi (rtx *operands) 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; } @@ -10337,11 +10264,11 @@ arc_return_address_register (unsigned int fn_type) 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; @@ -10392,14 +10319,12 @@ arc_eh_uses (int regno) 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 @@ -11338,7 +11263,7 @@ operands_ok_ldd_std (rtx rt, rtx rt2, HOST_WIDE_INT offset) 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; diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index b81b0e7ba33..4d01c99a540 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -312,8 +312,6 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -#define PROGRAM_COUNTER_REGNO 63 - /* Standard register usage. */ /* Number of actual hardware registers. @@ -373,7 +371,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \ 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, \ @@ -470,25 +468,15 @@ enum reg_class { 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 }; @@ -497,29 +485,18 @@ enum reg_class /* 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. @@ -527,33 +504,19 @@ enum reg_class 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. */ @@ -590,7 +553,7 @@ extern enum reg_class arc_regno_reg_class[]; /* 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 @@ -1650,4 +1613,8 @@ enum /* 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 */ diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 830236242e0..f9958b72c6a 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -171,18 +171,37 @@ (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) ] @@ -652,8 +671,8 @@ core_3, archs4x, archs4xd, archs4xd_slow" ; 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)" "@ @@ -689,8 +708,8 @@ core_3, archs4x, archs4xd, archs4xd_slow" "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]) @@ -740,9 +759,9 @@ core_3, archs4x, archs4xd, archs4xd_slow" ; 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]) @@ -5002,12 +5021,12 @@ core_3, archs4x, archs4xd, archs4xd_slow" }) (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")]) @@ -5015,16 +5034,16 @@ core_3, archs4x, archs4xd, archs4xd_slow" ;; 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")]) @@ -5069,7 +5088,7 @@ core_3, archs4x, archs4xd, archs4xd_slow" (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 "" "")) @@ -6283,8 +6302,8 @@ core_3, archs4x, archs4xd, archs4xd_slow" (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))] "" "" diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt index e8f97e4d1af..af9e2d16ca0 100644 --- a/gcc/config/arc/arc.opt +++ b/gcc/config/arc/arc.opt @@ -401,12 +401,9 @@ Target 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) diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md index cbb31249240..64e43325cfd 100644 --- a/gcc/config/arc/constraints.md +++ b/gcc/config/arc/constraints.md @@ -24,48 +24,35 @@ ; 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}") @@ -78,10 +65,6 @@ "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}") @@ -472,7 +455,7 @@ (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" diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md index efa3650e1fa..c4be56f766e 100644 --- a/gcc/config/arc/predicates.md +++ b/gcc/config/arc/predicates.md @@ -20,33 +20,12 @@ (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); }) @@ -358,13 +337,14 @@ 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;