re PR target/54236 ([SH] Improve addc and subc insn utilization)
PR target/54236 * config/sh/sh.md (*addc): Rename existing variations to ... (*addc_r_r_1, *addc_2r_1, *addc_r_1): ... these. (*addc_r_lsb, *addc_r_r_lsb, *addc_r_lsb_r, *addc_2r_lsb, *addc_r_msb, *addc_r_r_msb, *addc_2r_msb): New insn_and_split patterns. * config/sh/sh.c (addsubcosts): Handle some addc special cases. PR target/54236 * gcc.target/sh/pr54236-2: New. * gcc.target/sh/pr54089-6: Add another rotl special case. From-SVN: r204180
This commit is contained in:
parent
c6a684e36c
commit
dd331dd0b5
|
@ -1,3 +1,12 @@
|
|||
2013-10-29 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/54236
|
||||
* config/sh/sh.md (*addc): Rename existing variations to ...
|
||||
(*addc_r_r_1, *addc_2r_1, *addc_r_1): ... these.
|
||||
(*addc_r_lsb, *addc_r_r_lsb, *addc_r_lsb_r, *addc_2r_lsb, *addc_r_msb,
|
||||
*addc_r_r_msb, *addc_2r_msb): New insn_and_split patterns.
|
||||
* config/sh/sh.c (addsubcosts): Handle some addc special cases.
|
||||
|
||||
2013-10-29 Teresa Johnson <tejohnson@google.com>
|
||||
|
||||
PR ipa/58862
|
||||
|
|
|
@ -3159,6 +3159,35 @@ and_xor_ior_costs (rtx x, int code)
|
|||
static inline int
|
||||
addsubcosts (rtx x)
|
||||
{
|
||||
if (GET_MODE (x) == SImode)
|
||||
{
|
||||
/* The addc or subc patterns will eventually become one or two
|
||||
instructions. Below are some costs for some of the patterns
|
||||
which combine would reject because the costs of the individual
|
||||
insns in the patterns are lower.
|
||||
|
||||
FIXME: It would be much easier if we had something like insn cost
|
||||
attributes and the cost calculation machinery used those attributes
|
||||
in the first place. This would eliminate redundant recog-like C
|
||||
code to calculate costs of complex patterns. */
|
||||
rtx op0 = XEXP (x, 0);
|
||||
rtx op1 = XEXP (x, 1);
|
||||
|
||||
if (GET_CODE (x) == PLUS)
|
||||
{
|
||||
if (GET_CODE (op0) == AND
|
||||
&& XEXP (op0, 1) == const1_rtx
|
||||
&& (GET_CODE (op1) == PLUS
|
||||
|| (GET_CODE (op1) == MULT && XEXP (op1, 1) == const2_rtx)))
|
||||
return 1;
|
||||
|
||||
if (GET_CODE (op0) == MULT && XEXP (op0, 1) == const2_rtx
|
||||
&& GET_CODE (op1) == LSHIFTRT
|
||||
&& CONST_INT_P (XEXP (op1, 1)) && INTVAL (XEXP (op1, 1)) == 31)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* On SH1-4 we have only max. SImode operations.
|
||||
Double the cost for modes > SImode. */
|
||||
const int cost_scale = !TARGET_SHMEDIA
|
||||
|
|
|
@ -1841,7 +1841,7 @@
|
|||
|
||||
;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled
|
||||
;; better, if the sett insn can be done early.
|
||||
(define_insn_and_split "*addc"
|
||||
(define_insn_and_split "*addc_r_r_1"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||
(plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
|
||||
(match_operand:SI 2 "arith_reg_operand" ""))
|
||||
|
@ -1857,7 +1857,7 @@
|
|||
|
||||
;; Left shifts by one are usually done with an add insn to avoid T_REG
|
||||
;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'.
|
||||
(define_insn_and_split "*addc"
|
||||
(define_insn_and_split "*addc_2r_1"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 2))
|
||||
|
@ -1897,7 +1897,7 @@
|
|||
;; can be scheduled much better since the load of the constant can be
|
||||
;; done earlier, before any comparison insns that store the result in
|
||||
;; the T bit.
|
||||
(define_insn_and_split "*addc"
|
||||
(define_insn_and_split "*addc_r_1"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||
(plus:SI (match_operand:SI 1 "t_reg_operand" "")
|
||||
(match_operand:SI 2 "arith_reg_operand" "")))
|
||||
|
@ -1910,6 +1910,126 @@
|
|||
(match_dup 1)))
|
||||
(clobber (reg:SI T_REG))])])
|
||||
|
||||
;; Use shlr-addc to do 'reg + (reg & 1)'.
|
||||
(define_insn_and_split "*addc_r_lsb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 1))
|
||||
(match_operand:SI 2 "arith_reg_operand")))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
|
||||
(clobber (reg:SI T_REG))])]
|
||||
{
|
||||
emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
|
||||
})
|
||||
|
||||
;; Use shlr-addc to do 'reg + reg + (reg & 1)'.
|
||||
(define_insn_and_split "*addc_r_r_lsb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 1))
|
||||
(match_operand:SI 2 "arith_reg_operand"))
|
||||
(match_operand:SI 3 "arith_reg_operand")))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
|
||||
(reg:SI T_REG)))
|
||||
(clobber (reg:SI T_REG))])]
|
||||
{
|
||||
emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1]));
|
||||
})
|
||||
|
||||
;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'.
|
||||
(define_insn_and_split "*addc_r_lsb_r"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 1))
|
||||
(plus:SI (match_operand:SI 2 "arith_reg_operand")
|
||||
(match_operand:SI 3 "arith_reg_operand"))))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
|
||||
(match_dup 2))
|
||||
(match_dup 3)))
|
||||
(clobber (reg:SI T_REG))])])
|
||||
|
||||
;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'.
|
||||
(define_insn_and_split "*addc_2r_lsb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 1))
|
||||
(mult:SI (match_operand:SI 2 "arith_reg_operand")
|
||||
(const_int 2))))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1))
|
||||
(match_dup 2))
|
||||
(match_dup 2)))
|
||||
(clobber (reg:SI T_REG))])])
|
||||
|
||||
;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'.
|
||||
(define_insn_and_split "*addc_r_msb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 31))
|
||||
(match_operand:SI 2 "arith_reg_operand")))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2)))
|
||||
(clobber (reg:SI T_REG))])]
|
||||
{
|
||||
emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
|
||||
})
|
||||
|
||||
;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'.
|
||||
(define_insn_and_split "*addc_r_r_msb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 31))
|
||||
(match_operand:SI 2 "arith_reg_operand"))
|
||||
(match_operand:SI 3 "arith_reg_operand")))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3))
|
||||
(reg:SI T_REG)))
|
||||
(clobber (reg:SI T_REG))])]
|
||||
{
|
||||
emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1]));
|
||||
})
|
||||
|
||||
;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)'
|
||||
;; into 'reg + reg + (reg & 1)'.
|
||||
(define_insn_and_split "*addc_2r_msb"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest")
|
||||
(plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand")
|
||||
(const_int 2))
|
||||
(lshiftrt:SI (match_operand:SI 2 "arith_reg_operand")
|
||||
(const_int 31))))
|
||||
(clobber (reg:SI T_REG))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
"&& can_create_pseudo_p ()"
|
||||
[(parallel [(set (match_dup 0)
|
||||
(plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31))
|
||||
(match_dup 1))
|
||||
(match_dup 1)))
|
||||
(clobber (reg:SI T_REG))])])
|
||||
|
||||
(define_expand "addsi3"
|
||||
[(set (match_operand:SI 0 "arith_reg_operand" "")
|
||||
(plus:SI (match_operand:SI 1 "arith_operand" "")
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2013-10-29 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/54236
|
||||
* gcc.target/sh/pr54236-2: New.
|
||||
* gcc.target/sh/pr54089-6: Add another rotl special case.
|
||||
|
||||
2013-10-29 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran 58793
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/* { dg-options "-O1" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */
|
||||
/* { dg-final { scan-assembler-times "rotr" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "rotl" 2 } } */
|
||||
/* { dg-final { scan-assembler-times "rotl" 3 } } */
|
||||
|
||||
int
|
||||
test_00 (int a)
|
||||
|
@ -28,3 +28,9 @@ test_03 (int a)
|
|||
{
|
||||
return ((a >> 1) & 0x7FFFFFFF) | (a << 31);
|
||||
}
|
||||
|
||||
int
|
||||
test_04 (int a)
|
||||
{
|
||||
return a + a + ((a >> 31) & 1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
/* Tests to check the utilization of the addc instruction in special cases.
|
||||
If everything works as expected we won't see any movt instructions in
|
||||
these cases. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
|
||||
/* { dg-final { scan-assembler-times "addc" 37 } } */
|
||||
/* { dg-final { scan-assembler-times "shlr" 23 } } */
|
||||
/* { dg-final { scan-assembler-times "shll" 14 } } */
|
||||
/* { dg-final { scan-assembler-times "add\t" 12 } } */
|
||||
/* { dg-final { scan-assembler-not "movt" } } */
|
||||
|
||||
int
|
||||
test_000 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + (b & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_001 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + b + (c & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_002 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + b + c + (d & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_003 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return (b & 1) + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_004 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + (c & 1) + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_005 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + b + (d & 1) + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_006 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return (c & 1) + a + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_007 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + (d & 1) + b + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_008 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return (d & 1) + a + b + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_009 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + b + (b & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_010 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + (b & 1) + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_011 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return (b & 1) + a + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_012 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + b + d + (b & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_013 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + d + (b & 1) + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_014 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return a + (b & 1) + d + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_015 (int a, int c, int b, int d)
|
||||
{
|
||||
// 1x shlr, 1x add, 1x addc
|
||||
return (b & 1) + a + d + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_016 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + (a & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_017 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + a + (a & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_018 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return a + (a & 1) + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_019 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return (a & 1) + a + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_020 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return b + b + (a & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_021 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return b + (a & 1) + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_022 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shlr, 1x addc
|
||||
return (a & 1) + b + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_023 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + ((b >> 31) & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_024 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return ((b >> 31) & 1) + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_025 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return ((a >> 31) & 1) + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_026 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + ((a >> 31) & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_027 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + b + ((c >> 31) & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_028 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + ((c >> 31) & 1) + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_029 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return ((c >> 31) & 1) + a + b;
|
||||
}
|
||||
|
||||
int
|
||||
test_030 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc, 1x add
|
||||
return a + b + c + ((d >> 31) & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_031 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc, 1x add
|
||||
return a + b + ((d >> 31) & 1) + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_032 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc, 1x add
|
||||
return a + ((d >> 31) & 1) + b + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_033 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc, 1x add
|
||||
return ((d >> 31) & 1) + a + b + c;
|
||||
}
|
||||
|
||||
int
|
||||
test_034 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + a + ((d >> 31) & 1);
|
||||
}
|
||||
|
||||
int
|
||||
test_035 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return a + ((d >> 31) & 1) + a;
|
||||
}
|
||||
|
||||
int
|
||||
test_036 (int a, int b, int c, int d)
|
||||
{
|
||||
// 1x shll, 1x addc
|
||||
return ((d >> 31) & 1) + a + a;
|
||||
}
|
Loading…
Reference in New Issue