aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/s390/s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/s390/s390.c')
-rw-r--r--gcc/config/s390/s390.c48
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. */