Commit fe241a29 by Richard Earnshaw

(storehi_bigend): New expansion pattern.

(storeinthi): Rework to generate better code, add big-endian support.
(movhi): Add support for processors running in big-endian mode.
(movhi_bigend): New expansion pattern.
(matcher for movhi): Remove incorrect alternative for storing HImode to
memory.  Only match when little endian.
(matcher for big-endian movhi): New pattern.
(matchers/peepholes for extended pre/post increment HImode loads): Only
match when little-endian.
(matcher for operating on adjacent memory locations): Load operation into
arith operands.
(peepholes for extended pre-increment byte loads): New patterns.

From-SVN: r7448
parent 9c872872
...@@ -1983,30 +1983,69 @@ ...@@ -1983,30 +1983,69 @@
} }
") ")
;; Subroutine to store a half word integer constant into memory. (define_expand "storehi_bigend"
;; Operand 0 is the constant [(set (mem:QI (match_dup 4)) (match_dup 3))
;; Operand 1 is the destination address in a register (SImode) (set (match_dup 2)
(ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
(define_expand "storeinthi" (set (mem:QI (match_operand 1 "" ""))
[;; store the low byte (subreg:QI (match_dup 2) 0))]
(set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
;; store the high byte
(set (mem:QI (match_dup 3)) (match_dup 2))]
"" ""
" "
{ {
int value = INTVAL (operands[0]);
enum rtx_code code = GET_CODE (operands[1]); enum rtx_code code = GET_CODE (operands[1]);
if ((code == PLUS || code == MINUS) if ((code == PLUS || code == MINUS)
&& (GET_CODE (XEXP (operands[1], 1)) == REG && (GET_CODE (XEXP (operands[1], 1)) == REG
|| GET_CODE (XEXP (operands[1], 0)) != REG)) || GET_CODE (XEXP (operands[1], 0)) != REG))
operands[1] = force_reg (SImode, operands[1]); operands[1] = force_reg (SImode, operands[1]);
operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255)); operands[4] = plus_constant (operands[1], 1);
operands[2] = force_reg (QImode, operands[3] = gen_lowpart (QImode, operands[0]);
gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255)); operands[0] = gen_lowpart (SImode, operands[0]);
operands[3] = plus_constant (operands[1], 1); operands[2] = gen_reg_rtx (SImode);
}
")
;; Subroutine to store a half word integer constant into memory.
(define_expand "storeinthi"
[(set (mem:QI (match_operand:SI 0 "" ""))
(subreg:QI (match_operand 1 "" "") 0))
(set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
""
"
{
HOST_WIDE_INT value = INTVAL (operands[1]);
enum rtx_code code = GET_CODE (operands[0]);
if ((code == PLUS || code == MINUS)
&& (GET_CODE (XEXP (operands[0], 1)) == REG
|| GET_CODE (XEXP (operands[0], 0)) != REG))
operands[0] = force_reg (SImode, operands[0]);
operands[1] = gen_reg_rtx (SImode);
if (BYTES_BIG_ENDIAN)
{
emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
if ((value & 255) == ((value >> 8) & 255))
operands[2] = operands[1];
else
{
operands[2] = gen_reg_rtx (SImode);
emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
}
}
else
{
emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
if ((value & 255) == ((value >> 8) & 255))
operands[2] = operands[1];
else
{
operands[2] = gen_reg_rtx (SImode);
emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
}
}
operands[3] = plus_constant (operands[0], 1);
} }
") ")
...@@ -2018,74 +2057,105 @@ ...@@ -2018,74 +2057,105 @@
{ {
rtx insn; rtx insn;
if (reload_in_progress || reload_completed) if (! (reload_in_progress || reload_completed))
insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
else
{ {
if (GET_CODE (operands[0]) == MEM) if (GET_CODE (operands[0]) == MEM)
{ {
if (GET_CODE (operands[1]) == CONST_INT) if (GET_CODE (operands[1]) == CONST_INT)
{ emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
insn = gen_storeinthi (operands[1], XEXP (operands[0],0));
}
else else
{ {
if (GET_CODE (operands[1]) == MEM) if (GET_CODE (operands[1]) == MEM)
operands[1] = force_reg (HImode, operands[1]); operands[1] = force_reg (HImode, operands[1]);
insn = gen_storehi (operands[1], XEXP (operands[0], 0)); if (BYTES_BIG_ENDIAN)
emit_insn (gen_storehi_bigend (operands[1],
XEXP (operands[0], 0)));
else
emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
} }
DONE;
} }
else if (GET_CODE (operands[1]) == CONST_INT /* Sign extend a constant, and keep it in an SImode reg. */
&& !(const_ok_for_arm (INTVAL (operands[1])) else if (GET_CODE (operands[1]) == CONST_INT)
|| const_ok_for_arm (~INTVAL (operands[1]))))
{ {
rtx reg, reg2; rtx reg = gen_reg_rtx (SImode);
HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
/* no need to be clever, this will always take two insns. /* If the constant is already valid, leave it alone. */
The top sixteen bits should be all zeros or all ones. */ if (! const_ok_for_arm (val))
if (INTVAL (operands[1]) < 0)
{
emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
GEN_INT (INTVAL (operands[1])
| ~(0x0ff00))));
emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
GEN_INT (-((~INTVAL (operands[1]))
& 0xff))));
}
else
{ {
emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), /* If setting all the top bits will make the constant
GEN_INT (INTVAL (operands[1]) & 0xff00))); loadable in a single instruction, then set them.
emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg, Otherwise, sign extend the number. */
GEN_INT (INTVAL (operands[1]) & 0x00ff)));
if (const_ok_for_arm (~ (val | ~0xffff)))
val |= ~0xffff;
else if (val & 0x8000)
val |= ~0xffff;
} }
insn = gen_rtx (SET, HImode, operands[0],
gen_rtx (SUBREG, HImode, reg2, 0)); emit_insn (gen_movsi (reg, GEN_INT (val)));
operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
}
else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
{
emit_insn (gen_movhi_bigend (operands[0], operands[1]));
DONE;
} }
else
insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
} }
}
")
emit_insn (insn); (define_expand "movhi_bigend"
DONE; [(set (match_dup 2)
}") (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
(const_int 16)))
(set (match_dup 3)
(ashiftrt:SI (match_dup 2) (const_int 16)))
(set (match_operand:HI 0 "s_register_operand" "")
(subreg:HI (match_dup 3) 0))]
""
"
operands[2] = gen_reg_rtx (SImode);
operands[3] = gen_reg_rtx (SImode);
")
;; Pattern to recognise insn generated default case above ;; Pattern to recognise insn generated default case above
(define_insn "" (define_insn ""
[(set (match_operand:HI 0 "general_operand" "=r,r,r,m") [(set (match_operand:HI 0 "general_operand" "=r,r,r")
(match_operand:HI 1 "general_operand" "rI,K,m,r"))] (match_operand:HI 1 "general_operand" "rI,K,m"))]
"(register_operand (operands[0], HImode) "(! BYTES_BIG_ENDIAN)
&& (GET_CODE (operands[1]) != CONST_INT && (GET_CODE (operands[1]) != CONST_INT
|| const_ok_for_arm (INTVAL (operands[1])) || const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1])))) || const_ok_for_arm (~INTVAL (operands[1])))"
|| register_operand (operands[1], HImode)"
"@ "@
mov%?\\t%0, %1\\t%@ movhi mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi mvn%?\\t%0, #%B1\\t%@ movhi
ldr%?\\t%0, %1\\t%@ movhi ldr%?\\t%0, %1\\t%@ movhi"
bogus code str%?\\t%1, %0\\t%@ movhi" [(set_attr "type" "*,*,load")])
[(set_attr "type" "*,*,load,store1")])
(define_insn ""
[(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
(match_operand:HI 1 "general_operand" "rI,K,m"))]
"BYTES_BIG_ENDIAN
&& (GET_CODE (operands[1]) != CONST_INT
|| const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1])))"
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi
ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
[(set_attr "type" "*,*,load")
(set_attr "length" "4,4,8")])
(define_insn ""
[(set (match_operand:SI 0 "s_register_operand" "=r")
(rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
(const_int 16)))]
"BYTES_BIG_ENDIAN"
"ldr%?\\t%0, %1\\t%@ movhi_bigend"
[(set_attr "type" "load")])
(define_expand "reload_outhi" (define_expand "reload_outhi"
[(parallel [(match_operand:HI 0 "reload_memory_operand" "=o") [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
...@@ -2106,10 +2176,11 @@ ...@@ -2106,10 +2176,11 @@
if (!(reload_in_progress || reload_completed)) if (!(reload_in_progress || reload_completed))
{ {
rtx reg;
if (GET_CODE (operands[1]) == CONST_INT) if (GET_CODE (operands[1]) == CONST_INT)
{ {
emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), operands[1])); rtx reg = gen_reg_rtx (SImode);
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_rtx (SUBREG, QImode, reg, 0); operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
} }
} }
...@@ -4335,7 +4406,7 @@ ...@@ -4335,7 +4406,7 @@
"* "*
{ {
rtx ldm[3]; rtx ldm[3];
rtx arith[3]; rtx arith[4];
int val1 = 0, val2 = 0; int val1 = 0, val2 = 0;
if (REGNO (operands[0]) > REGNO (operands[4])) if (REGNO (operands[0]) > REGNO (operands[4]))
...@@ -4353,6 +4424,7 @@ ...@@ -4353,6 +4424,7 @@
if (GET_CODE (XEXP (operands[3], 0)) != REG) if (GET_CODE (XEXP (operands[3], 0)) != REG)
val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
arith[0] = operands[0]; arith[0] = operands[0];
arith[3] = operands[1];
if (val1 < val2) if (val1 < val2)
{ {
arith[1] = ldm[1]; arith[1] = ldm[1];
...@@ -4391,7 +4463,7 @@ ...@@ -4391,7 +4463,7 @@
else else
output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm); output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
} }
output_asm_insn (\"%I1%?\\t%0, %1, %2\", arith); output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
return \"\"; return \"\";
} }
" "
...@@ -4546,7 +4618,8 @@ ...@@ -4546,7 +4618,8 @@
(match_operand:SI 2 "index_operand" "rJ")))) (match_operand:SI 2 "index_operand" "rJ"))))
(set (match_operand:SI 0 "s_register_operand" "=r") (set (match_operand:SI 0 "s_register_operand" "=r")
(plus:SI (match_dup 1) (match_dup 2)))] (plus:SI (match_dup 1) (match_dup 2)))]
"REGNO (operands[0]) != FRAME_POINTER_REGNUM "(! BYTES_BIG_ENDIAN)
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM && REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& (GET_CODE (operands[2]) != REG && (GET_CODE (operands[2]) != REG
|| REGNO (operands[2]) != FRAME_POINTER_REGNUM)" || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
...@@ -4559,7 +4632,8 @@ ...@@ -4559,7 +4632,8 @@
(match_operand:SI 2 "s_register_operand" "r")))) (match_operand:SI 2 "s_register_operand" "r"))))
(set (match_operand:SI 0 "s_register_operand" "=r") (set (match_operand:SI 0 "s_register_operand" "=r")
(minus:SI (match_dup 1) (match_dup 2)))] (minus:SI (match_dup 1) (match_dup 2)))]
"REGNO (operands[0]) != FRAME_POINTER_REGNUM "(!BYTES_BIG_ENDIAN)
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM && REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& (GET_CODE (operands[2]) != REG && (GET_CODE (operands[2]) != REG
|| REGNO (operands[2]) != FRAME_POINTER_REGNUM)" || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
...@@ -4695,7 +4769,8 @@ ...@@ -4695,7 +4769,8 @@
(set (match_operand:SI 0 "s_register_operand" "=r") (set (match_operand:SI 0 "s_register_operand" "=r")
(plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
(match_dup 1)))] (match_dup 1)))]
"REGNO (operands[0]) != FRAME_POINTER_REGNUM "(! BYTES_BIG_ENDIAN)
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM && REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& REGNO (operands[3]) != FRAME_POINTER_REGNUM" && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
"ldr%?\\t%5, [%0, %3, %S2]!\\t%@ loadhi" "ldr%?\\t%5, [%0, %3, %S2]!\\t%@ loadhi"
...@@ -4710,7 +4785,8 @@ ...@@ -4710,7 +4785,8 @@
(set (match_operand:SI 0 "s_register_operand" "=r") (set (match_operand:SI 0 "s_register_operand" "=r")
(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
(match_dup 4)])))] (match_dup 4)])))]
"REGNO (operands[0]) != FRAME_POINTER_REGNUM "(! BYTES_BIG_ENDIAN)
&& REGNO (operands[0]) != FRAME_POINTER_REGNUM
&& REGNO (operands[1]) != FRAME_POINTER_REGNUM && REGNO (operands[1]) != FRAME_POINTER_REGNUM
&& REGNO (operands[3]) != FRAME_POINTER_REGNUM" && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
"ldr%?\\t%5, [%0, -%3, %S2]!\\t%@ loadhi" "ldr%?\\t%5, [%0, -%3, %S2]!\\t%@ loadhi"
...@@ -4730,7 +4806,7 @@ ...@@ -4730,7 +4806,7 @@
(set (match_dup 0) (set (match_dup 0)
(plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))] (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
"" ""
"strb\\t%2, [%0], %1") "str%?b\\t%2, [%0], %1")
(define_peephole (define_peephole
[(set (match_operand:QI 0 "s_register_operand" "=r") [(set (match_operand:QI 0 "s_register_operand" "=r")
...@@ -4755,7 +4831,8 @@ ...@@ -4755,7 +4831,8 @@
(mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
(set (match_dup 1) (set (match_dup 1)
(plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))] (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
"REGNO(operands[0]) != REGNO(operands[1]) "(! BYTES_BIG_ENDIAN)
&& REGNO(operands[0]) != REGNO(operands[1])
&& (GET_CODE (operands[2]) != REG && (GET_CODE (operands[2]) != REG
|| REGNO(operands[0]) != REGNO (operands[2]))" || REGNO(operands[0]) != REGNO (operands[2]))"
"ldr%?\\t%0, [%1], %2\\t%@ loadhi") "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
...@@ -4770,6 +4847,25 @@ ...@@ -4770,6 +4847,25 @@
|| REGNO(operands[0]) != REGNO (operands[2]))" || REGNO(operands[0]) != REGNO (operands[2]))"
"ldr%?\\t%0, [%1], %2") "ldr%?\\t%0, [%1], %2")
(define_peephole
[(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
(match_operand:SI 1 "index_operand" "rJ")))
(match_operand:QI 2 "s_register_operand" "r"))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
""
"str%?b\\t%2, [%0, %1]!")
(define_peephole
[(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
[(match_operand:SI 0 "s_register_operand" "r")
(match_operand 1 "const_int_operand" "n")])
(match_operand:SI 2 "s_register_operand" "+r")))
(match_operand:QI 3 "s_register_operand" "r"))
(set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
(match_dup 2)))]
""
"str%?b\\t%3, [%2, %0, %S4]!")
; This pattern is never tried by combine, so do it as a peephole ; This pattern is never tried by combine, so do it as a peephole
(define_peephole (define_peephole
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment