From fe241a29e33e5c7474471e6d2a410b04d2487bbe Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Mon, 6 Jun 1994 13:14:03 +0000 Subject: [PATCH] (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 --- gcc/config/arm/arm.md | 236 +++++++++++++++++++++++++++++------------- 1 file changed, 166 insertions(+), 70 deletions(-) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2c9a8aeefc32..d860edabe09c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1983,30 +1983,69 @@ } ") -;; Subroutine to store a half word integer constant into memory. -;; Operand 0 is the constant -;; Operand 1 is the destination address in a register (SImode) - -(define_expand "storeinthi" - [;; store the low byte - (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" "")) - ;; store the high byte - (set (mem:QI (match_dup 3)) (match_dup 2))] +(define_expand "storehi_bigend" + [(set (mem:QI (match_dup 4)) (match_dup 3)) + (set (match_dup 2) + (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) + (set (mem:QI (match_operand 1 "" "")) + (subreg:QI (match_dup 2) 0))] "" " { - int value = INTVAL (operands[0]); enum rtx_code code = GET_CODE (operands[1]); - if ((code == PLUS || code == MINUS) && (GET_CODE (XEXP (operands[1], 1)) == 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[2] = force_reg (QImode, - gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255)); - operands[3] = plus_constant (operands[1], 1); + operands[4] = plus_constant (operands[1], 1); + operands[3] = gen_lowpart (QImode, operands[0]); + operands[0] = gen_lowpart (SImode, operands[0]); + 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 @@ { rtx insn; - if (reload_in_progress || reload_completed) - insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]); - else + if (! (reload_in_progress || reload_completed)) { if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_INT) - { - insn = gen_storeinthi (operands[1], XEXP (operands[0],0)); - } + emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1])); else { if (GET_CODE (operands[1]) == MEM) 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 - && !(const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))) + /* Sign extend a constant, and keep it in an SImode reg. */ + else if (GET_CODE (operands[1]) == CONST_INT) { - 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. - The top sixteen bits should be all zeros or all ones. */ - 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 + /* If the constant is already valid, leave it alone. */ + if (! const_ok_for_arm (val)) { - emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), - GEN_INT (INTVAL (operands[1]) & 0xff00))); - emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg, - GEN_INT (INTVAL (operands[1]) & 0x00ff))); + /* If setting all the top bits will make the constant + loadable in a single instruction, then set them. + Otherwise, sign extend the number. */ + + 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); - DONE; -}") +(define_expand "movhi_bigend" + [(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 (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") - (match_operand:HI 1 "general_operand" "rI,K,m,r"))] - "(register_operand (operands[0], HImode) - && (GET_CODE (operands[1]) != CONST_INT - || const_ok_for_arm (INTVAL (operands[1])) - || const_ok_for_arm (~INTVAL (operands[1])))) - || register_operand (operands[1], HImode)" + [(set (match_operand:HI 0 "general_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 - bogus code str%?\\t%1, %0\\t%@ movhi" -[(set_attr "type" "*,*,load,store1")]) + ldr%?\\t%0, %1\\t%@ movhi" +[(set_attr "type" "*,*,load")]) + +(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" [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o") @@ -2106,10 +2176,11 @@ if (!(reload_in_progress || reload_completed)) { - rtx reg; 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); } } @@ -4335,7 +4406,7 @@ "* { rtx ldm[3]; - rtx arith[3]; + rtx arith[4]; int val1 = 0, val2 = 0; if (REGNO (operands[0]) > REGNO (operands[4])) @@ -4353,6 +4424,7 @@ if (GET_CODE (XEXP (operands[3], 0)) != REG) val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1)); arith[0] = operands[0]; + arith[3] = operands[1]; if (val1 < val2) { arith[1] = ldm[1]; @@ -4391,7 +4463,7 @@ else 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 \"\"; } " @@ -4546,7 +4618,8 @@ (match_operand:SI 2 "index_operand" "rJ")))) (set (match_operand:SI 0 "s_register_operand" "=r") (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 && (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" @@ -4559,7 +4632,8 @@ (match_operand:SI 2 "s_register_operand" "r")))) (set (match_operand:SI 0 "s_register_operand" "=r") (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 && (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != FRAME_POINTER_REGNUM)" @@ -4695,7 +4769,8 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)]) (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[3]) != FRAME_POINTER_REGNUM" "ldr%?\\t%5, [%0, %3, %S2]!\\t%@ loadhi" @@ -4710,7 +4785,8 @@ (set (match_operand:SI 0 "s_register_operand" "=r") (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) (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[3]) != FRAME_POINTER_REGNUM" "ldr%?\\t%5, [%0, -%3, %S2]!\\t%@ loadhi" @@ -4730,7 +4806,7 @@ (set (match_dup 0) (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 [(set (match_operand:QI 0 "s_register_operand" "=r") @@ -4755,7 +4831,8 @@ (mem:HI (match_operand:SI 1 "s_register_operand" "+r"))) (set (match_dup 1) (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 || REGNO(operands[0]) != REGNO (operands[2]))" "ldr%?\\t%0, [%1], %2\\t%@ loadhi") @@ -4770,6 +4847,25 @@ || REGNO(operands[0]) != REGNO (operands[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 (define_peephole -- 2.47.2