re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
PR target/51244 * config/sh/sh.c (sh_expand_t_scc): Remove SH2A special case and use unified expansion logic. * config/sh/sh.md (xorsi3_movrt): Rename to movrt. Move closer to the existing movt insn. (negc): Rename insn to *negc. Add new expander. (movnegt): Use xor pattern for T bit negation. Reserve helper constant for negc pattern. (*movnegt): New insn and splitter. PR target/51244 * gcc.target/sh/pr51244-1.c: New. * gcc.target/sh/pr51244-2.c: New. * gcc.target/sh/pr51244-3.c: New. From-SVN: r184966
This commit is contained in:
parent
5de724244f
commit
9747719a9c
|
@ -1,3 +1,15 @@
|
|||
2012-03-06 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
* config/sh/sh.c (sh_expand_t_scc): Remove SH2A special case
|
||||
and use unified expansion logic.
|
||||
* config/sh/sh.md (xorsi3_movrt): Rename to movrt. Move
|
||||
closer to the existing movt insn.
|
||||
(negc): Rename insn to *negc. Add new expander.
|
||||
(movnegt): Use xor pattern for T bit negation. Reserve helper
|
||||
constant for negc pattern.
|
||||
(*movnegt): New insn and splitter.
|
||||
|
||||
2012-03-05 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
* c-typeck.c (pointer_diff): Check for POINTER_PLUS_EXPR, not
|
||||
|
|
|
@ -11888,15 +11888,8 @@ sh_expand_t_scc (rtx operands[])
|
|||
val = INTVAL (op1);
|
||||
if ((code == EQ && val == 1) || (code == NE && val == 0))
|
||||
emit_insn (gen_movt (result));
|
||||
else if (TARGET_SH2A && ((code == EQ && val == 0)
|
||||
|| (code == NE && val == 1)))
|
||||
emit_insn (gen_xorsi3_movrt (result));
|
||||
else if ((code == EQ && val == 0) || (code == NE && val == 1))
|
||||
{
|
||||
emit_clobber (result);
|
||||
emit_insn (gen_subc (result, result, result));
|
||||
emit_insn (gen_addsi3 (result, result, const1_rtx));
|
||||
}
|
||||
emit_insn (gen_movnegt (result));
|
||||
else if (code == EQ || code == NE)
|
||||
emit_insn (gen_move_insn (result, GEN_INT (code == NE)));
|
||||
else
|
||||
|
|
|
@ -3354,15 +3354,6 @@ label:
|
|||
xori %1, %2, %0"
|
||||
[(set_attr "type" "arith_media")])
|
||||
|
||||
;; Store the complements of the T bit in a register.
|
||||
(define_insn "xorsi3_movrt"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(xor:SI (reg:SI T_REG)
|
||||
(const_int 1)))]
|
||||
"TARGET_SH2A"
|
||||
"movrt\\t%0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_insn "xordi3"
|
||||
[(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
|
||||
(xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r")
|
||||
|
@ -4387,7 +4378,17 @@ label:
|
|||
;; Unary arithmetic
|
||||
;; -------------------------------------------------------------------------
|
||||
|
||||
(define_insn "negc"
|
||||
(define_expand "negc"
|
||||
[(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||
(neg:SI (plus:SI (reg:SI T_REG)
|
||||
(match_operand:SI 1 "arith_reg_operand" ""))))
|
||||
(set (reg:SI T_REG)
|
||||
(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
|
||||
(const_int 0)))])]
|
||||
""
|
||||
"")
|
||||
|
||||
(define_insn "*negc"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(neg:SI (plus:SI (reg:SI T_REG)
|
||||
(match_operand:SI 1 "arith_reg_operand" "r"))))
|
||||
|
@ -9528,6 +9529,13 @@ mov.l\\t1f,r0\\n\\
|
|||
"movt %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_insn "movrt"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(xor:SI (reg:SI T_REG) (const_int 1)))]
|
||||
"TARGET_SH2A"
|
||||
"movrt %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_expand "cstore4_media"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(match_operator:SI 1 "sh_float_comparison_operator"
|
||||
|
@ -9654,40 +9662,55 @@ mov.l\\t1f,r0\\n\\
|
|||
DONE;
|
||||
")
|
||||
|
||||
;; sne moves the complement of the T reg to DEST like this:
|
||||
;; cmp/eq ...
|
||||
;; mov #-1,temp
|
||||
;; negc temp,dest
|
||||
;; This is better than xoring compare result with 1 because it does
|
||||
;; not require r0 and further, the -1 may be CSE-ed or lifted out of a
|
||||
;; loop.
|
||||
;; Move the complement of the T reg to a reg.
|
||||
;; On SH2A the movrt insn can be used.
|
||||
;; On anything else than SH2A this has to be done with multiple instructions.
|
||||
;; One obvious way would be:
|
||||
;; cmp/eq ...
|
||||
;; movt r0
|
||||
;; xor #1,r0
|
||||
;;
|
||||
;; However, this puts pressure on r0 in most cases and thus the following is
|
||||
;; more appealing:
|
||||
;; cmp/eq ...
|
||||
;; mov #-1,temp
|
||||
;; negc temp,dest
|
||||
;;
|
||||
;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
|
||||
;; becomes a one instruction operation. Moreover, care must be taken that
|
||||
;; the insn can still be combined with inverted compare and branch code
|
||||
;; around it.
|
||||
;; The expander will reserve the constant -1, the insn makes the whole thing
|
||||
;; combinable, the splitter finally emits the insn if it was not combined
|
||||
;; away.
|
||||
;; Notice that when using the negc variant the T bit also gets inverted.
|
||||
|
||||
(define_expand "movnegt"
|
||||
[(set (match_dup 1) (const_int -1))
|
||||
(parallel [(set (match_operand:SI 0 "" "")
|
||||
(neg:SI (plus:SI (reg:SI T_REG)
|
||||
(match_dup 1))))
|
||||
(set (reg:SI T_REG)
|
||||
(ne:SI (ior:SI (reg:SI T_REG) (match_dup 1))
|
||||
(const_int 0)))])]
|
||||
(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||
(xor:SI (reg:SI T_REG) (const_int 1)))
|
||||
(use (match_dup 1))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
operands[1] = gen_reg_rtx (SImode);
|
||||
}")
|
||||
})
|
||||
|
||||
;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
|
||||
;; This prevents a regression that occurred when we switched from xor to
|
||||
;; mov/neg for sne.
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "")
|
||||
(plus:SI (reg:SI T_REG)
|
||||
(const_int -1)))]
|
||||
(define_insn_and_split "*movnegt"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(xor:SI (reg:SI T_REG) (const_int 1)))
|
||||
(use (match_operand:SI 1 "arith_reg_operand" "r"))]
|
||||
"TARGET_SH1"
|
||||
[(set (match_dup 0) (eq:SI (reg:SI T_REG) (const_int 1)))
|
||||
(set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
|
||||
"")
|
||||
"#"
|
||||
"&& 1"
|
||||
[(const_int 0)]
|
||||
{
|
||||
if (TARGET_SH2A)
|
||||
emit_insn (gen_movrt (operands[0]));
|
||||
else
|
||||
emit_insn (gen_negc (operands[0], operands[1]));
|
||||
DONE;
|
||||
}
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_expand "cstoresf4"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2012-03-06 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
* gcc.target/sh/pr51244-1.c: New.
|
||||
* gcc.target/sh/pr51244-2.c: New.
|
||||
* gcc.target/sh/pr51244-3.c: New.
|
||||
|
||||
2012-03-05 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/51930
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/* Check that the following code compiles without errors. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1" } */
|
||||
|
||||
enum { nrrdCenterUnknown, nrrdCenterNode, nrrdCenterCell, nrrdCenterLast };
|
||||
typedef struct { int size; int center; } NrrdAxis;
|
||||
typedef struct { int dim; NrrdAxis axis[10]; } Nrrd;
|
||||
typedef struct { } NrrdKernel;
|
||||
typedef struct { const NrrdKernel *kernel[10]; int samples[10]; } Info;
|
||||
|
||||
void
|
||||
foo (Nrrd *nout, Nrrd *nin, const NrrdKernel *kernel, const double *parm,
|
||||
const int *samples, const double *scalings)
|
||||
{
|
||||
Info *info;
|
||||
int d, p, np, center;
|
||||
for (d=0; d<nin->dim; d++)
|
||||
{
|
||||
info->kernel[d] = kernel;
|
||||
if (samples)
|
||||
info->samples[d] = samples[d];
|
||||
else
|
||||
{
|
||||
center = _nrrdCenter(nin->axis[d].center);
|
||||
if (nrrdCenterCell == center)
|
||||
info->samples[d] = nin->axis[d].size*scalings[d];
|
||||
else
|
||||
info->samples[d] = (nin->axis[d].size - 1)*scalings[d] + 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* Check that inverted conditional branch logic does not generate
|
||||
unnecessary explicit T bit extractions, inversions and
|
||||
test instructions. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1 -mbranch-cost=2" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
|
||||
/* { dg-final { scan-assembler-not "tst|negc|extu" } } */
|
||||
|
||||
int
|
||||
testfunc_00 (int a, int b, int c, int d)
|
||||
{
|
||||
return (a != b || a != d) ? b : c;
|
||||
}
|
||||
|
||||
int
|
||||
testfunc_01 (int a, char* p, int b, int c)
|
||||
{
|
||||
return (a == b && a == c) ? b : c;
|
||||
}
|
||||
|
||||
int
|
||||
testfunc_02 (int a, char* p, int b, int c)
|
||||
{
|
||||
return (a == b && a == c) ? b : c;
|
||||
}
|
||||
|
||||
int
|
||||
testfunc_03 (int a, char* p, int b, int c)
|
||||
{
|
||||
return (a != b && a != c) ? b : c;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
/* Check that when taking the complement of the T bit using the negc
|
||||
instruction pattern, the constant -1 is loaded only once.
|
||||
On SH2A this test is skipped because the movrt instruction is used
|
||||
to get the complement of the T bit. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1 -mbranch-cost=2" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" "-m2a*" } { "" } } */
|
||||
/* { dg-final { scan-assembler-times "mov\t#-1" 1 } } */
|
||||
|
||||
void
|
||||
testfunc_00 (int* a, int* b, int c, int d)
|
||||
{
|
||||
b[0] = a[0] != c;
|
||||
b[1] = a[1] != d;
|
||||
b[2] = a[2] != c;
|
||||
b[3] = a[3] != d;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* Check that when taking the complement of the T bit on SH2A,
|
||||
the movrt instruction is being generated. */
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1 -mbranch-cost=2" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "*" } { "-m2a*" } } */
|
||||
/* { dg-final { scan-assembler-times "movrt" 4 } } */
|
||||
|
||||
void
|
||||
testfunc_00 (int* a, int* b, int c, int d)
|
||||
{
|
||||
b[0] = a[0] != c;
|
||||
b[1] = a[1] != d;
|
||||
b[2] = a[2] != c;
|
||||
b[3] = a[3] != d;
|
||||
}
|
||||
|
Loading…
Reference in New Issue