This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [SH] PR 39423
- From: Oleg Endo <oleg dot endo at t-online dot de>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Henderson <rth at redhat dot com>
- Date: Thu, 09 Aug 2012 00:12:08 +0200
- Subject: Re: [SH] PR 39423
- References: <1343602608.2304.15.camel@yam-132-YW-E178-FTW> <5016A826.5040405@redhat.com>
On Mon, 2012-07-30 at 08:28 -0700, Richard Henderson wrote:
> On 2012-07-29 15:56, Oleg Endo wrote:
> > + "&& can_create_pseudo_p ()"
> > + [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
> > + (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
> > + (set (match_dup 0) (mem:SI (plus:SI (match_dup 6) (match_dup 4))))]
>
> Don't create new mems like this -- you've lost alias info.
> You need to use replace_equiv_address or something on the
> original memory. Which means you have to actually capture
> the memory operand somehow.
>
> Better to use a custom predicate to match these memories with
> these complex addresses, rather than list them out each time:
>
> [(set (match_operand:SI 0 "arith_reg_dest" "=r")
> (match_operand:SI 1 "mem_index_disp_operand" "m"))]
How about the attached patch?
Is that way of dealing with the mems OK?
What could be a possible test case for the alias info issue?
Tested on rev 190151 with
make -k check RUNTESTFLAGS="--target_board=sh-sim
\{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and no new failures.
Cheers,
Oleg
ChangeLog:
PR target/39423
* config/sh/predicates.md (mem_index_disp_operand): New
predicate.
* config/sh/sh.md (*movsi_index_disp): Rewrite insns to use the
new mem_index_disp_operand predicate.
testsuite/ChangeLog:
PR target/39423
* gcc.target/sh/pr39423-1.c: New.
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 190151)
+++ gcc/config/sh/sh.md (working copy)
@@ -5119,114 +5119,116 @@
;; FIXME: Combine never tries this kind of patterns for DImode.
(define_insn_and_split "*movsi_index_disp"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (mem:SI
- (plus:SI
- (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand"))
- (match_operand:SI 3 "arith_reg_operand" "r"))
- (match_operand:SI 4 "const_int_operand"))))]
- "TARGET_SH1 && sh_legitimate_index_p (SImode, operands[4], TARGET_SH2A, true)
- && exact_log2 (INTVAL (operands[2])) > 0"
+ (match_operand:SI 1 "mem_index_disp_operand" "m"))]
+ "TARGET_SH1"
"#"
"&& can_create_pseudo_p ()"
[(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
- (set (match_dup 0) (mem:SI (plus:SI (match_dup 6) (match_dup 4))))]
+ (set (match_dup 0) (match_dup 7))]
{
+ rtx mem = operands[1];
+ rtx plus0_rtx = XEXP (mem, 0);
+ rtx plus1_rtx = XEXP (plus0_rtx, 0);
+ rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+ operands[1] = XEXP (mult_rtx, 0);
+ operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+ operands[3] = XEXP (plus1_rtx, 1);
+ operands[4] = XEXP (plus0_rtx, 1);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+ operands[7] =
+ replace_equiv_address (mem,
+ gen_rtx_PLUS (SImode, operands[6], operands[4]));
})
(define_insn_and_split "*movhi_index_disp"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (sign_extend:SI
- (mem:HI
- (plus:SI
- (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand"))
- (match_operand:SI 3 "arith_reg_operand" "r"))
- (match_operand:SI 4 "const_int_operand")))))]
- "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
- && exact_log2 (INTVAL (operands[2])) > 0"
+ (sign_extend:SI (match_operand:HI 1 "mem_index_disp_operand" "m")))]
+ "TARGET_SH1"
"#"
"&& can_create_pseudo_p ()"
[(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
- (set (match_dup 0)
- (sign_extend:SI (mem:HI (plus:SI (match_dup 6) (match_dup 4)))))]
+ (set (match_dup 0) (sign_extend:SI (match_dup 7)))]
{
+ rtx mem = operands[1];
+ rtx plus0_rtx = XEXP (mem, 0);
+ rtx plus1_rtx = XEXP (plus0_rtx, 0);
+ rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+ operands[1] = XEXP (mult_rtx, 0);
+ operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+ operands[3] = XEXP (plus1_rtx, 1);
+ operands[4] = XEXP (plus0_rtx, 1);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+ operands[7] =
+ replace_equiv_address (mem,
+ gen_rtx_PLUS (SImode, operands[6], operands[4]));
})
-(define_insn_and_split "*movhi_index_disp"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (zero_extend:SI
- (mem:HI
- (plus:SI
- (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand"))
- (match_operand:SI 3 "arith_reg_operand" "r"))
- (match_operand:SI 4 "const_int_operand")))))]
- "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
- && exact_log2 (INTVAL (operands[2])) > 0"
- "#"
- "&& can_create_pseudo_p ()"
- [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
- (set (match_dup 7)
- (sign_extend:SI (mem:HI (plus:SI (match_dup 6) (match_dup 4)))))
- (set (match_dup 0) (zero_extend:SI (match_dup 8)))]
+(define_split
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (zero_extend:SI (match_operand:HI 1 "mem_index_disp_operand")))]
+ "TARGET_SH1"
+ [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+ (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
{
- operands[5] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (SImode);
- operands[7] = gen_reg_rtx (SImode);
- operands[8] = gen_lowpart (HImode, operands[7]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+ operands[2] = gen_lowpart (HImode, operands[0]);
})
(define_insn_and_split "*movsi_index_disp"
- [(set (mem:SI
- (plus:SI
- (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand"))
- (match_operand:SI 3 "arith_reg_operand" "r"))
- (match_operand:SI 4 "const_int_operand")))
- (match_operand:SI 0 "arith_reg_operand" "r"))]
- "TARGET_SH1 && sh_legitimate_index_p (SImode, operands[4], TARGET_SH2A, true)
- && exact_log2 (INTVAL (operands[2])) > 0"
+ [(set (match_operand:SI 0 "mem_index_disp_operand" "=m")
+ (match_operand:SI 1 "arith_reg_operand" "r"))]
+ "TARGET_SH1"
"#"
"&& can_create_pseudo_p ()"
- [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
+ [(set (match_dup 5) (ashift:SI (match_dup 0) (match_dup 2)))
(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
- (set (mem:SI (plus:SI (match_dup 6) (match_dup 4))) (match_dup 0))]
+ (set (match_dup 7) (match_dup 1))]
{
+ rtx mem = operands[0];
+ rtx plus0_rtx = XEXP (mem, 0);
+ rtx plus1_rtx = XEXP (plus0_rtx, 0);
+ rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+ operands[0] = XEXP (mult_rtx, 0);
+ operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+ operands[3] = XEXP (plus1_rtx, 1);
+ operands[4] = XEXP (plus0_rtx, 1);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+ operands[7] =
+ replace_equiv_address (mem,
+ gen_rtx_PLUS (SImode, operands[6], operands[4]));
})
-(define_insn_and_split "*movhi_index_disp"
- [(set (mem:HI
- (plus:SI
- (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand"))
- (match_operand:SI 3 "arith_reg_operand" "r"))
- (match_operand:SI 4 "const_int_operand")))
- (match_operand:HI 0 "arith_reg_operand" "r"))]
- "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
- && exact_log2 (INTVAL (operands[2])) > 0"
+(define_insn_and_split "*movsi_index_disp"
+ [(set (match_operand:HI 0 "mem_index_disp_operand" "=m")
+ (match_operand:HI 1 "arith_reg_operand" "r"))]
+ "TARGET_SH1"
"#"
"&& can_create_pseudo_p ()"
- [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
+ [(set (match_dup 5) (ashift:SI (match_dup 0) (match_dup 2)))
(set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
- (set (mem:HI (plus:SI (match_dup 6) (match_dup 4))) (match_dup 0))]
+ (set (match_dup 7) (match_dup 1))]
{
+ rtx mem = operands[0];
+ rtx plus0_rtx = XEXP (mem, 0);
+ rtx plus1_rtx = XEXP (plus0_rtx, 0);
+ rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+ operands[0] = XEXP (mult_rtx, 0);
+ operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+ operands[3] = XEXP (plus1_rtx, 1);
+ operands[4] = XEXP (plus0_rtx, 1);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+ operands[7] =
+ replace_equiv_address (mem,
+ gen_rtx_PLUS (SImode, operands[6], operands[4]));
})
;; Define additional pop for SH1 and SH2 so it does not get
Index: gcc/config/sh/predicates.md
===================================================================
--- gcc/config/sh/predicates.md (revision 190151)
+++ gcc/config/sh/predicates.md (working copy)
@@ -523,6 +523,31 @@
return 0;
})
+;; Returns 1 if OP is a MEM that can be used in "index_disp" combiner
+;; patterns.
+(define_predicate "mem_index_disp_operand"
+ (match_code "mem")
+{
+ rtx plus0_rtx, plus1_rtx, mult_rtx;
+
+ plus0_rtx = XEXP (op, 0);
+ if (GET_CODE (plus0_rtx) != PLUS)
+ return 0;
+
+ plus1_rtx = XEXP (plus0_rtx, 0);
+ if (GET_CODE (plus1_rtx) != PLUS)
+ return 0;
+
+ mult_rtx = XEXP (plus1_rtx, 0);
+ if (GET_CODE (mult_rtx) != MULT)
+ return 0;
+
+ return REG_P (XEXP (mult_rtx, 0)) && CONST_INT_P (XEXP (mult_rtx, 1))
+ && exact_log2 (INTVAL (XEXP (mult_rtx, 1))) > 0
+ && REG_P (XEXP (plus1_rtx, 1))
+ && sh_legitimate_index_p (mode, XEXP (plus0_rtx, 1), TARGET_SH2A, true);
+})
+
;; TODO: Add a comment here.
(define_predicate "greater_comparison_operator"
Index: gcc/testsuite/gcc.target/sh/pr39423-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr39423-1.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr39423-1.c (revision 0)
@@ -0,0 +1,48 @@
+/* Check that displacement addressing is used for indexed addresses with a
+ small offset, instead of re-calculating the index. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-not "add\t#1" } } */
+
+int
+test_00 (int tab[], int index)
+{
+ return tab[index + 1];
+}
+
+int
+test_01 (short tab[], int index)
+{
+ return tab[index + 1];
+}
+
+int
+test_02 (unsigned short tab[], int index)
+{
+ return tab[index + 1];
+}
+
+int
+test_03 (long long tab[], int index)
+{
+ return (int)tab[index + 1];
+}
+
+void
+test_04 (int tab[], int index, int val)
+{
+ tab[index + 1] = val;
+}
+
+void
+test_05 (short tab[], int index, int val)
+{
+ tab[index + 1] = (short)val;
+}
+
+void
+test_06 (unsigned short tab[], int index, int val)
+{
+ tab[index + 1] = (unsigned short)val;
+}