diff options
Diffstat (limited to 'gcc/config/s390/s390.c')
-rw-r--r-- | gcc/config/s390/s390.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 8921f6d82f5..9e7fd2b04dd 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -937,6 +937,8 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, continue; } + /* A memory operand is rejected by the memory_operand predicate. + Try making the address legal by copying it into a register. */ if (MEM_P (op[arity]) && insn_op->predicate == memory_operand && (GET_MODE (XEXP (op[arity], 0)) == Pmode @@ -960,10 +962,14 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, { op[arity] = tmp_rtx; } - else if (GET_MODE (op[arity]) == insn_op->mode - || GET_MODE (op[arity]) == VOIDmode - || (insn_op->predicate == address_operand - && GET_MODE (op[arity]) == Pmode)) + + /* The predicate rejects the operand although the mode is fine. + Copy the operand to register. */ + if (!insn_op->predicate (op[arity], insn_op->mode) + && (GET_MODE (op[arity]) == insn_op->mode + || GET_MODE (op[arity]) == VOIDmode + || (insn_op->predicate == address_operand + && GET_MODE (op[arity]) == Pmode))) { /* An address_operand usually has VOIDmode in the expander so we cannot use this. */ @@ -10106,6 +10112,21 @@ s390_register_info () s390_register_info_stdarg_gpr (); } +/* Return true if REGNO is a global register, but not one + of the special ones that need to be saved/restored in anyway. */ + +static inline bool +global_not_special_regno_p (int regno) +{ + return (global_regs[regno] + /* These registers are special and need to be + restored in any case. */ + && !(regno == STACK_POINTER_REGNUM + || regno == RETURN_REGNUM + || regno == BASE_REGNUM + || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM))); +} + /* This function is called by s390_optimize_prologue in order to get rid of unnecessary GPR save/restore instructions. The register info for the GPRs is re-computed and the ranges are re-calculated. */ @@ -10121,8 +10142,10 @@ s390_optimize_register_info () s390_regs_ever_clobbered (clobbered_regs); + /* Global registers do not need to be saved and restored unless it + is one of our special regs. (r12, r13, r14, or r15). */ for (i = 0; i < 32; i++) - clobbered_regs[i] = clobbered_regs[i] && !global_regs[i]; + clobbered_regs[i] = clobbered_regs[i] && !global_not_special_regno_p (i); /* There is still special treatment needed for cases invisible to s390_regs_ever_clobbered. */ @@ -10876,21 +10899,6 @@ restore_fpr (rtx base, int offset, int regnum) return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr); } -/* Return true if REGNO is a global register, but not one - of the special ones that need to be saved/restored in anyway. */ - -static inline bool -global_not_special_regno_p (int regno) -{ - return (global_regs[regno] - /* These registers are special and need to be - restored in any case. */ - && !(regno == STACK_POINTER_REGNUM - || regno == RETURN_REGNUM - || regno == BASE_REGNUM - || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM))); -} - /* Generate insn to save registers FIRST to LAST into the register save area located at offset OFFSET relative to register BASE. */ |