diff options
Diffstat (limited to 'gcc/config/epiphany/epiphany.c')
-rw-r--r-- | gcc/config/epiphany/epiphany.c | 90 |
1 files changed, 56 insertions, 34 deletions
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index 5520a633c1f..7d251e3d00e 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -335,7 +335,8 @@ epiphany_select_cc_mode (enum rtx_code op, { if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) { - if (TARGET_SOFT_CMPSF) + if (TARGET_SOFT_CMPSF + || op == ORDERED || op == UNORDERED) { if (op == EQ || op == NE) return CC_FP_EQmode; @@ -537,24 +538,47 @@ gen_compare_reg (enum machine_mode cmode, enum rtx_code code, if (mode == CC_FP_GTEmode && (code == LE || code == LT || code == UNGT || code == UNGE)) { - rtx tmp = x; x = y; y = tmp; - code = swap_condition (code); + if (flag_finite_math_only + && ((REG_P (x) && REGNO (x) == GPR_0) + || (REG_P (y) && REGNO (y) == GPR_1))) + switch (code) + { + case LE: code = UNLE; break; + case LT: code = UNLT; break; + case UNGT: code = GT; break; + case UNGE: code = GE; break; + default: gcc_unreachable (); + } + else + { + rtx tmp = x; x = y; y = tmp; + code = swap_condition (code); + } } cc_reg = gen_rtx_REG (mode, CC_REGNUM); } if ((mode == CC_FP_EQmode || mode == CC_FP_GTEmode || mode == CC_FP_ORDmode || mode == CC_FP_UNEQmode) /* mov<mode>cc might want to re-emit a comparison during ifcvt. */ - && (!REG_P (x) || REGNO (x) != 0 || !REG_P (y) || REGNO (y) != 1)) + && (!REG_P (x) || REGNO (x) != GPR_0 + || !REG_P (y) || REGNO (y) != GPR_1)) { rtx reg; +#if 0 + /* ??? We should really do the r0/r1 clobber only during rtl expansion, + but just like the flag clobber of movsicc, we have to allow + this for ifcvt to work, on the assumption that we'll only want + to do this if these registers have been used before by the + pre-ifcvt code. */ gcc_assert (currently_expanding_to_rtl); - reg = gen_rtx_REG (in_mode, 0); - gcc_assert (!reg_overlap_mentioned_p (reg, y)); +#endif + reg = gen_rtx_REG (in_mode, GPR_0); + if (reg_overlap_mentioned_p (reg, y)) + return 0; emit_move_insn (reg, x); x = reg; - reg = gen_rtx_REG (in_mode, 1); + reg = gen_rtx_REG (in_mode, GPR_1); emit_move_insn (reg, y); y = reg; } @@ -964,7 +988,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) int first_slot, last_slot, first_slot_offset, last_slot_offset; int first_slot_size; int small_slots = 0; - long lr_slot_offset; var_size = size; args_size = crtl->outgoing_args_size; @@ -1021,7 +1044,7 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) first_slot = regno; else if (last_slot < 0 && (first_slot ^ regno) != 1 - && (!interrupt_p || regno > GPR_0 + 1)) + && (!interrupt_p || regno > GPR_1)) last_slot = regno; } } @@ -1116,28 +1139,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) } total_size = first_slot_offset + last_slot_offset; - lr_slot_offset - = (frame_pointer_needed ? first_slot_offset : (long) total_size); - if (first_slot != GPR_LR) - { - int stack_offset = epiphany_stack_offset - UNITS_PER_WORD; - - for (regno = 0; ; regno++) - { - if (stack_offset + UNITS_PER_WORD - first_slot_size == 0 - && first_slot >= 0) - { - stack_offset -= first_slot_size; - regno--; - } - else if (regno == GPR_LR) - break; - else if TEST_HARD_REG_BIT (gmask, regno) - stack_offset -= UNITS_PER_WORD; - } - lr_slot_offset += stack_offset; - } - /* Save computed information. */ current_frame_info.total_size = total_size; current_frame_info.pretend_size = pretend_size; @@ -1150,7 +1151,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) current_frame_info.first_slot_offset = first_slot_offset; current_frame_info.first_slot_size = first_slot_size; current_frame_info.last_slot_offset = last_slot_offset; - MACHINE_FUNCTION (cfun)->lr_slot_offset = lr_slot_offset; current_frame_info.initialized = reload_completed; @@ -1622,6 +1622,28 @@ epiphany_emit_save_restore (int min, int limit, rtx addr, int epilogue_p) mem = skipped_mem; else mem = gen_mem (mode, addr); + + /* If we are loading / storing LR, note the offset that + gen_reload_insi_ra requires. Since GPR_LR is even, + we only need to test n, even if mode is DImode. */ + gcc_assert ((GPR_LR & 1) == 0); + if (n == GPR_LR) + { + long lr_slot_offset = 0; + rtx m_addr = XEXP (mem, 0); + + if (GET_CODE (m_addr) == PLUS) + lr_slot_offset = INTVAL (XEXP (m_addr, 1)); + if (frame_pointer_needed) + lr_slot_offset += (current_frame_info.first_slot_offset + - current_frame_info.total_size); + if (MACHINE_FUNCTION (cfun)->lr_slot_known) + gcc_assert (MACHINE_FUNCTION (cfun)->lr_slot_offset + == lr_slot_offset); + MACHINE_FUNCTION (cfun)->lr_slot_offset = lr_slot_offset; + MACHINE_FUNCTION (cfun)->lr_slot_known = 1; + } + if (!epilogue_p) frame_move_insn (mem, reg); else if (n >= MAX_EPIPHANY_PARM_REGS || !crtl->args.pretend_args_size) @@ -1667,7 +1689,7 @@ epiphany_expand_prologue (void) gen_rtx_REG (DImode, GPR_0)); frame_move_insn (gen_rtx_REG (SImode, GPR_0), gen_rtx_REG (word_mode, STATUS_REGNUM)); - frame_move_insn (gen_rtx_REG (SImode, GPR_0+1), + frame_move_insn (gen_rtx_REG (SImode, GPR_1), gen_rtx_REG (word_mode, IRET_REGNUM)); mem = gen_frame_mem (BLKmode, stack_pointer_rtx); off = GEN_INT (-current_frame_info.first_slot_offset); @@ -1843,7 +1865,7 @@ epiphany_expand_epilogue (int sibcall_p) emit_move_insn (gen_rtx_REG (word_mode, STATUS_REGNUM), gen_rtx_REG (SImode, GPR_0)); emit_move_insn (gen_rtx_REG (word_mode, IRET_REGNUM), - gen_rtx_REG (SImode, GPR_0+1)); + gen_rtx_REG (SImode, GPR_1)); addr = plus_constant (Pmode, stack_pointer_rtx, - (HOST_WIDE_INT) 2 * UNITS_PER_WORD); emit_move_insn (gen_rtx_REG (DImode, GPR_0), |