diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2012-08-09 15:58:04 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2012-08-09 15:58:04 +0000 |
commit | b67b3838e94c69f500c84ff58ffa44720a0ec79c (patch) | |
tree | 73061df4766994376ae31743dea39a322ad56681 | |
parent | 78ff60c1ad15e72b056fe888a0b0d509c5e563a9 (diff) | |
download | gcc-b67b3838e94c69f500c84ff58ffa44720a0ec79c.zip gcc-b67b3838e94c69f500c84ff58ffa44720a0ec79c.tar.gz gcc-b67b3838e94c69f500c84ff58ffa44720a0ec79c.tar.bz2 |
re PR target/39423 ([SH] performance regression: lost mov @(disp,Rn))
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.
PR target/39423
* gcc.target/sh/pr39423-1.c: New.
From-SVN: r190259
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/sh/predicates.md | 25 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 142 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/pr39423-1.c | 48 |
5 files changed, 157 insertions, 70 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 318278a..dc96a3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2012-08-09 Oleg Endo <olegendo@gcc.gnu.org> + 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. + +2012-08-09 Oleg Endo <olegendo@gcc.gnu.org> + PR target/51244 * config/sh/sh.md: Add negc extu sequence peephole. (movrt, movnegt, movrt_negc, nott): Use t_reg_operand predicate. diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 588e25c..209ff29 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -507,6 +507,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" diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index c95c904..e96ff7d 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -5119,114 +5119,116 @@ label: ;; 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cffdd0b..790921f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2012-08-09 Oleg Endo <olegendo@gcc.gnu.org> + PR target/39423 + * gcc.target/sh/pr39423-1.c: New. + +2012-08-09 Oleg Endo <olegendo@gcc.gnu.org> + PR target/51244 * gcc.target/sh/pr51244-5: New. * gcc.target/sh/pr51244-6: New. diff --git a/gcc/testsuite/gcc.target/sh/pr39423-1.c b/gcc/testsuite/gcc.target/sh/pr39423-1.c new file mode 100644 index 0000000..dac0f89 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr39423-1.c @@ -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; +} |