only do so if indexing is safe.
Indexing is safe when the second operand for the outer PLUS
- is a REG, SUBREG, SYMBOL_REF or the like.
+ is a REG, SUBREG, SYMBOL_REF or the like. */
- For 2.5, indexing is also safe for (plus (symbol_ref) (const_int))
- if the integer is > 0. */
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
reg1));
}
+ /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
+
+ Only do so for floating point modes since this is more speculative
+ and we lose if it's an integer store. */
+ if ((mode == DFmode || mode == SFmode)
+ && GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
+ && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))))
+ {
+ rtx regx1, regx2;
+
+ /* Add the two unscaled terms B and C; only force them into registers
+ if it's absolutely necessary. */
+ regx1 = XEXP (XEXP (x, 0), 1);
+ if (! (GET_CODE (regx1) == REG
+ || (GET_CODE (regx1) == CONST_INT
+ && INT_14_BITS (regx1))))
+ regx1 = force_reg (Pmode, force_operand (XEXP (XEXP (x, 0), 1), 0));
+
+ regx2 = XEXP (x, 1);
+ if (! (GET_CODE (regx2) == REG
+ || (GET_CODE (regx2) == CONST_INT
+ && INT_14_BITS (regx2))))
+ regx2 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));
+
+ /* Add them, make sure the result is in canonical form. */
+ if (GET_CODE (regx1) == REG)
+ regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regx2));
+ else if (GET_CODE (regx2) == REG)
+ regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, regx2, regx1));
+ else
+ regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ force_reg (Pmode, regx1),
+ regx2));
+
+ /* Get the term to scale in a register. */
+ regx2 = XEXP (XEXP (XEXP (x, 0), 0), 0);
+ if (GET_CODE (regx2) != REG)
+ regx2 = force_reg (Pmode, force_operand (regx2, 0));
+
+ /* And make an indexed address. */
+ regx2 = gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, regx2,
+ XEXP (XEXP (XEXP (x, 0), 0), 1)),
+ regx1);
+
+ /* Return it. */
+ return force_reg (Pmode, regx2);
+ }
+
/* Uh-oh. We might have an address for x[n-100000]. This needs
- special handling. */
+ special handling.
+
+ This is common enough that we want to try and rearrange the terms
+ so that we can use indexing for these addresses too. Again, only
+ do the optimization for floatint point modes. */
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
to access memory, or better yet have the MI parts of the compiler
handle this. */
- rtx regx1, regy1, regy2, y;
+ rtx regx1, regx2, regy1, regy2, y;
/* Strip off any CONST. */
y = XEXP (x, 1);
if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
{
- regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
- regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
- regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
- regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
- return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+ /* See if this looks like
+ (plus (mult (reg) (shadd_const))
+ (const (plus (symbol_ref) (const_int))))
+
+ Where const_int can be divided evenly by shadd_const and
+ added to (reg). This allows more scaled indexed addresses. */
+ if ((mode == DFmode || mode == SFmode)
+ && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (y, 1)) == CONST_INT
+ && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0)
+ {
+ regx1
+ = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
+ / INTVAL (XEXP (XEXP (x, 0), 1))));
+ regx2 = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (regx2) != REG)
+ regx2 = force_reg (Pmode, force_operand (regx2, 0));
+ regx2 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode,
+ regx2, regx1));
+ return force_reg (Pmode,
+ gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, regx2,
+ XEXP (XEXP (x, 0), 1)),
+ force_reg (Pmode, XEXP (y, 0))));
+ }
+ else
+ {
+ /* Doesn't look like one we can optimize. */
+ regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
+ regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
+ regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
+ regx1 = force_reg (Pmode,
+ gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+ }
}
}
emit_move_insn (tmpreg, frame_pointer_rtx);
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
if (VAL_14_BITS_P (actual_fsize))
- emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx, tmpreg));
+ emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, size_rtx));
else
{
/* It is incorrect to store the saved frame pointer at *sp,
So instead use stwm to store at *sp and post-increment the
stack pointer as an atomic operation. Then increment sp to
finish allocating the new frame. */
- emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (64), tmpreg));
+ emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, GEN_INT (64)));
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
actual_fsize - 64);
{
merge_sp_adjust_with_store = 0;
emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-offset),
- gen_rtx (REG, SImode, i)));
+ gen_rtx (REG, SImode, i),
+ GEN_INT (-offset)));
}
else
store_reg (i, offset, STACK_POINTER_REGNUM);
stream, doing so avoids some very obscure problems. */
emit_insn (gen_blockage ());
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
- emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-64), frame_pointer_rtx));
+ emit_insn (gen_pre_ldwm (frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-64)));
}
/* If we were deferring a callee register restore, do it now. */
else if (! frame_pointer_needed && merge_sp_adjust_with_load)
- emit_insn (gen_pre_ldwm (stack_pointer_rtx,
+ emit_insn (gen_pre_ldwm (gen_rtx (REG, SImode,
+ merge_sp_adjust_with_load),
stack_pointer_rtx,
- GEN_INT (- actual_fsize),
- gen_rtx (REG, SImode,
- merge_sp_adjust_with_load)));
+ GEN_INT (- actual_fsize)));
else if (actual_fsize != 0)
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
;; Load or store with base-register modification.
(define_insn "pre_ldwm"
- [(set (match_operand:SI 3 "register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "pre_cint_operand" ""))))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
""
"*
{
if (INTVAL (operands[2]) < 0)
- return \"ldwm %2(0,%0),%3\";
- return \"ldws,mb %2(0,%0),%3\";
+ return \"ldwm %2(0,%1),%0\";
+ return \"ldws,mb %2(0,%1),%0\";
}"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn "pre_stwm"
- [(set (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "pre_cint_operand" "")))
- (match_operand:SI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "pre_cint_operand" "")))
+ (match_operand:SI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
""
"*
{
- if (INTVAL (operands[2]) < 0)
- return \"stwm %r3,%2(0,%0)\";
- return \"stws,mb %r3,%2(0,%0)\";
+ if (INTVAL (operands[1]) < 0)
+ return \"stwm %r2,%1(0,%0)\";
+ return \"stws,mb %r2,%1(0,%0)\";
}"
[(set_attr "type" "store")
(set_attr "length" "4")])
(define_insn "post_ldwm"
- [(set (match_operand:SI 3 "register_operand" "r")
- (mem:SI (match_operand:SI 1 "register_operand" "0")))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1)
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (match_operand:SI 1 "register_operand" "=r")))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
(match_operand:SI 2 "post_cint_operand" "")))]
""
"*
{
if (INTVAL (operands[2]) > 0)
- return \"ldwm %2(0,%0),%3\";
- return \"ldws,ma %2(0,%0),%3\";
+ return \"ldwm %2(0,%1),%0\";
+ return \"ldws,ma %2(0,%1),%1\";
}"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn "post_stwm"
- [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
- (match_operand:SI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1)
+ [(set (mem:SI (match_operand:SI 0 "register_operand" "=r"))
+ (match_operand:SI 1 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
(match_operand:SI 2 "post_cint_operand" "")))]
""
"*
{
if (INTVAL (operands[2]) > 0)
- return \"stwm %r3,%2(0,%0)\";
- return \"stws,ma %r3,%2(0,%0)\";
+ return \"stwm %r1,%2(0,%0)\";
+ return \"stws,ma %r1,%2(0,%0)\";
}"
[(set_attr "type" "store")
(set_attr "length" "4")])
(set_attr "length" "4")])
(define_insn ""
- [(set (match_operand:HI 3 "register_operand" "=r")
- (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "int5_operand" "L"))))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldhs,mb %2(0,%0),%3"
+ "ldhs,mb %2(0,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn ""
- [(set (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "int5_operand" "L")))
- (match_operand:HI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "int5_operand" "L")))
+ (match_operand:HI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
""
- "sths,mb %r3,%2(0,%0)"
+ "sths,mb %r2,%1(0,%0)"
[(set_attr "type" "store")
(set_attr "length" "4")])
(set_attr "length" "4")])
(define_insn ""
- [(set (match_operand:QI 3 "register_operand" "=r")
- (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "int5_operand" "L"))))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldbs,mb %2(0,%0),%3"
+ "ldbs,mb %2(0,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn ""
- [(set (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "int5_operand" "L")))
- (match_operand:QI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "int5_operand" "L")))
+ (match_operand:QI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
""
- "stbs,mb %r3,%2(0,%0)"
+ "stbs,mb %r2,%1(0,%0)"
[(set_attr "type" "store")
(set_attr "length" "4")])