re PR target/50751 (SH Target: Displacement addressing does not work for QImode and HImode)

PR target/50751
	* config/sh/constraints.md (Sra): New constraint.
	* config/sh/predicates.md (simple_mem_operand,
	displacement_mem_operand, zero_extend_movu_operand): New predicates.
	(zero_extend_operand): Check zero_extend_movu_operand for SH2A.
	* config/sh/sh.md (*zero_extendqisi2_disp_mem,
	*zero_extendhisi2_disp_mem): Add new insns and two new related
	peephole2 patterns.

	PR target/50751
	* gcc.target/sh/pr50751-8.c: New.

From-SVN: r190395
This commit is contained in:
Oleg Endo 2012-08-14 17:54:28 +00:00
parent bbeffd6b40
commit 24c18ad8f1
6 changed files with 226 additions and 1 deletions

View File

@ -1,3 +1,14 @@
2012-08-14 Oleg Endo <olegendo@gcc.gnu.org>
PR target/50751
* config/sh/constraints.md (Sra): New constraint.
* config/sh/predicates.md (simple_mem_operand,
displacement_mem_operand, zero_extend_movu_operand): New predicates.
(zero_extend_operand): Check zero_extend_movu_operand for SH2A.
* config/sh/sh.md (*zero_extendqisi2_disp_mem,
*zero_extendhisi2_disp_mem): Add new insns and two new related
peephole2 patterns.
2012-08-14 Steven Bosscher <steven@gcc.gnu.org>
* graphite-scop-detection.c (create_sese_edges): Compute dominance

View File

@ -49,6 +49,7 @@
;; Sbw: QImode address with 12 bit displacement
;; Snd: address without displacement
;; Sdd: address with displacement
;; Sra: simple register address
;; W: vector
;; Z: zero in any mode
;;
@ -307,3 +308,8 @@
(match_test "GET_MODE (op) == QImode")
(match_test "satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))")))
(define_memory_constraint "Sra"
"A memory reference that uses a simple register addressing."
(and (match_test "MEM_P (op)")
(match_test "REG_P (XEXP (op, 0))")))

View File

@ -368,12 +368,33 @@
: nonimmediate_operand) (op, mode);
})
;; Returns 1 if OP is a simple register address.
(define_predicate "simple_mem_operand"
(and (match_code "mem")
(match_test "arith_reg_operand (XEXP (op, 0), SImode)")))
;; Returns 1 if OP is a valid displacement address.
(define_predicate "displacement_mem_operand"
(and (match_code "mem")
(match_test "GET_CODE (XEXP (op, 0)) == PLUS")
(match_test "arith_reg_operand (XEXP (XEXP (op, 0), 0), SImode)")
(match_test "sh_legitimate_index_p (GET_MODE (op),
XEXP (XEXP (op, 0), 1),
TARGET_SH2A, true)")))
;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn.
(define_predicate "zero_extend_movu_operand"
(and (match_operand 0 "displacement_mem_operand")
(match_test "GET_MODE (op) == QImode || GET_MODE (op) == HImode")))
;; Returns 1 if the operand can be used in a zero_extend.
(define_predicate "zero_extend_operand"
(ior (and (match_test "TARGET_SHMEDIA")
(match_operand 0 "general_extend_operand"))
(and (match_test "! TARGET_SHMEDIA")
(match_operand 0 "arith_reg_operand"))))
(match_operand 0 "arith_reg_operand"))
(and (match_test "TARGET_SH2A")
(match_operand 0 "zero_extend_movu_operand"))))
;; Returns 1 if OP can be source of a simple move operation. Same as
;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as

View File

@ -4842,6 +4842,88 @@ label:
"extu.b %1,%0"
[(set_attr "type" "arith")])
;; SH2A supports two zero extending load instructions: movu.b and movu.w.
;; They could also be used for simple memory addresses like @Rn by setting
;; the displacement value to zero. However, doing so too early results in
;; missed opportunities for other optimizations such as post-inc or index
;; addressing loads.
;; Although the 'zero_extend_movu_operand' predicate does not allow simple
;; register addresses (an address without a displacement, index, post-inc),
;; zero-displacement addresses might be generated during reload, wich are
;; simplified to simple register addresses in turn. Thus, we have to
;; provide the Sdd and Sra alternatives in the patterns.
(define_insn "*zero_extendqisi2_disp_mem"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
(zero_extend:SI
(match_operand:QI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
"TARGET_SH2A"
"@
movu.b %1,%0
movu.b @(0,%t1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn "*zero_extendhisi2_disp_mem"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
(zero_extend:SI
(match_operand:HI 1 "zero_extend_movu_operand" "Sdd,Sra")))]
"TARGET_SH2A"
"@
movu.w %1,%0
movu.w @(0,%t1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
;; Convert the zero extending loads in sequences such as:
;; movu.b @(1,r5),r0 movu.w @(2,r5),r0
;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
;;
;; back to sign extending loads like:
;; mov.b @(1,r5),r0 mov.w @(2,r5),r0
;; mov.b r0,@(1,r4) mov.b r0,@(1,r4)
;;
;; if the extension type is irrelevant. The sign extending mov.{b|w} insn
;; is only 2 bytes in size if the displacement is {K04|K05}.
;; If the displacement is greater it doesn't matter, so we convert anyways.
(define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "")
(zero_extend:SI (match_operand 1 "displacement_mem_operand" "")))
(set (match_operand 2 "general_operand" "")
(match_operand 3 "arith_reg_operand" ""))]
"TARGET_SH2A
&& REGNO (operands[0]) == REGNO (operands[3])
&& peep2_reg_dead_p (2, operands[0])
&& GET_MODE_SIZE (GET_MODE (operands[2]))
<= GET_MODE_SIZE (GET_MODE (operands[1]))"
[(set (match_dup 0) (sign_extend:SI (match_dup 1)))
(set (match_dup 2) (match_dup 3))])
;; Fold sequences such as
;; mov.b @r3,r7
;; extu.b r7,r7
;; into
;; movu.b @(0,r3),r7
;; This does not reduce the code size but the number of instructions is
;; halved, which results in faster code.
(define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI (match_operand 1 "simple_mem_operand" "")))
(set (match_operand:SI 2 "arith_reg_dest" "")
(zero_extend:SI (match_operand 3 "arith_reg_operand" "")))]
"TARGET_SH2A
&& GET_MODE (operands[1]) == GET_MODE (operands[3])
&& (GET_MODE (operands[1]) == QImode || GET_MODE (operands[1]) == HImode)
&& REGNO (operands[0]) == REGNO (operands[3])
&& (REGNO (operands[2]) == REGNO (operands[0])
|| peep2_reg_dead_p (2, operands[0]))"
[(set (match_dup 2) (zero_extend:SI (match_dup 4)))]
{
operands[4]
= replace_equiv_address (operands[1],
gen_rtx_PLUS (SImode, XEXP (operands[1], 0),
const0_rtx));
})
;; -------------------------------------------------------------------------
;; Sign extension instructions
;; -------------------------------------------------------------------------

View File

@ -1,3 +1,8 @@
2012-08-14 Oleg Endo <olegendo@gcc.gnu.org>
PR target/50751
* gcc.target/sh/pr50751-8.c: New.
2012-08-14 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/47586

View File

@ -0,0 +1,100 @@
/* Check that on SH2A the 4 byte movu.b and movu.w displacement insns are
generated. This has to be checked with -O2 because some of the patterns
rely on peepholes. */
/* { dg-do compile { target "sh*-*-*" } } */
/* { dg-options "-O2" } */
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
/* { dg-final { scan-assembler-times "movu.b" 4 } } */
/* { dg-final { scan-assembler-times "movu.w" 3 } } */
int
test_00 (unsigned char* x)
{
/* 1x movu.b */
return x[0];
}
int
test_01 (unsigned short* x)
{
/* 1x movu.w */
return x[0];
}
int
test_02 (unsigned char* x)
{
/* 1x movu.b */
return x[1];
}
int
test_03 (unsigned char* x)
{
/* 1x movu.b */
return x[32];
}
int
test_04 (unsigned char* x)
{
/* 1x movu.b */
return x[9000];
}
int
test_05 (unsigned short* x)
{
/* 1x movu.w */
return x[9000];
}
int
test_06 (unsigned char* x, int i)
{
/* No movu.b expected here. Should use mov.b (r0,r4) + extu.b instead. */
return x[i];
}
int
test_07 (unsigned short* x, int i)
{
/* No movu.w expected here. Should use mov.w (r0,r4) + extu.w instead. */
return x[i];
}
int
test_08 (unsigned char* x, int c)
{
/* No movu.b expected here. Should use post-inc addressing instead. */
int s = 0;
int i;
for (i = 0; i < c; ++i)
s += x[i];
return s;
}
void
test_09 (unsigned char* x, unsigned char* y)
{
/* No movu.b expected here, since the zero-extension is irrelevant. */
x[1] = y[1];
x[2] = y[2];
}
void
test_10 (unsigned char* x, unsigned short* y)
{
/* No movu.w expected here, since the zero-extension is irrelevant. */
x[1] = y[1];
x[2] = y[2];
}
int
test_11 (unsigned char* x, unsigned short* y)
{
/* 1x movu.w */
int yy = y[1];
x[1] = yy;
return yy;
}