diff options
Diffstat (limited to 'contrib/gcc/config/alpha/alpha.c')
-rw-r--r-- | contrib/gcc/config/alpha/alpha.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c index 9657e56..42b57e1 100644 --- a/contrib/gcc/config/alpha/alpha.c +++ b/contrib/gcc/config/alpha/alpha.c @@ -2949,12 +2949,8 @@ alpha_expand_mov (mode, operands) compiled at the end of compilation. In the meantime, someone can re-encode-section-info on some symbol changing it e.g. from global to local-not-small. If this happens, we'd have emitted a plain - load rather than a high+losum load and not recognize the insn. - - So if rtl inlining is in effect, we delay the global/not-global - decision until rest_of_compilation by wrapping it in an - UNSPEC_SYMBOL. */ - if (TARGET_EXPLICIT_RELOCS && flag_inline_functions + load rather than a high+losum load and not recognize the insn. */ + if (TARGET_EXPLICIT_RELOCS && rtx_equal_function_value_matters && global_symbolic_operand (operands[1], mode)) { @@ -3336,10 +3332,10 @@ alpha_emit_conditional_branch (code) if (op1 == const0_rtx) cmp_code = NIL, branch_code = code; - /* We want to use cmpcc/bcc when we can, since there is a zero delay - bypass between logicals and br/cmov on EV5. But we don't want to - force valid immediate constants into registers needlessly. */ - else if (GET_CODE (op1) == CONST_INT) + /* If the constants doesn't fit into an immediate, but can + be generated by lda/ldah, we adjust the argument and + compare against zero, so we can use beq/bne directly. */ + else if (GET_CODE (op1) == CONST_INT && (code == EQ || code == NE)) { HOST_WIDE_INT v = INTVAL (op1), n = -v; @@ -6748,14 +6744,21 @@ alpha_sa_mask (imaskP, fmaskP) /* We need to restore these for the handler. */ if (current_function_calls_eh_return) - for (i = 0; ; ++i) - { - unsigned regno = EH_RETURN_DATA_REGNO (i); - if (regno == INVALID_REGNUM) - break; - imask |= 1L << regno; - } - + { + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + imask |= 1L << regno; + } + + /* Glibc likes to use $31 as an unwind stopper for crt0. To + avoid hackery in unwind-dw2.c, we need to actively store a + zero in the prologue of _Unwind_RaiseException et al. */ + imask |= 1UL << 31; + } + /* If any register spilled, then spill the return address also. */ /* ??? This is required by the Digital stack unwind specification and isn't needed if we're doing Dwarf2 unwinding. */ @@ -7210,7 +7213,7 @@ alpha_expand_prologue () } /* Now save any other registers required to be saved. */ - for (i = 0; i < 32; i++) + for (i = 0; i < 31; i++) if (imask & (1L << i)) { mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); @@ -7219,7 +7222,25 @@ alpha_expand_prologue () reg_offset += 8; } - for (i = 0; i < 32; i++) + /* Store a zero if requested for unwinding. */ + if (imask & (1UL << 31)) + { + rtx insn, t; + + mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); + set_mem_alias_set (mem, alpha_sr_alias_set); + insn = emit_move_insn (mem, const0_rtx); + + RTX_FRAME_RELATED_P (insn) = 1; + t = gen_rtx_REG (Pmode, 31); + t = gen_rtx_SET (VOIDmode, mem, t); + t = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, t, REG_NOTES (insn)); + REG_NOTES (insn) = t; + + reg_offset += 8; + } + + for (i = 0; i < 31; i++) if (fmask & (1L << i)) { mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset)); @@ -7625,7 +7646,7 @@ alpha_expand_epilogue () reg_offset += 8; imask &= ~(1L << REG_RA); - for (i = 0; i < 32; ++i) + for (i = 0; i < 31; ++i) if (imask & (1L << i)) { if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer) @@ -7639,7 +7660,10 @@ alpha_expand_epilogue () reg_offset += 8; } - for (i = 0; i < 32; ++i) + if (imask & (1UL << 31)) + reg_offset += 8; + + for (i = 0; i < 31; ++i) if (fmask & (1L << i)) { mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset)); |