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; +}