mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 04:10:29 +08:00
re PR target/51244 ([SH] Inefficient conditional branch and code around T bit)
PR target/51244 * config/sh/predicates.md (t_reg_operand, negt_reg_operand): New predicates. * config/sh/sh-protos.h (get_t_reg_rtx): New prototype. * config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking gen_branch_true and gen_branch_false. * config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and gen_branch_false. (branch_true, branch_false): Use t_reg_operand predicate. (*branch_true, *branch_false): Delete. (movt): Use t_reg_operand predicate. (*negnegt): Use negt_reg_operand predicate and fold little and big endian variants. (*movtt): Use t_reg_operand and fold little and big endian variants. (*movt_qi): Delete. PR target/51244 * gcc.target/sh/pr51244-1.c: Check that movt insn is not generated. From-SVN: r189177
This commit is contained in:
parent
73a1569582
commit
f031c3441f
@ -1,3 +1,21 @@
|
||||
2012-07-02 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
* config/sh/predicates.md (t_reg_operand, negt_reg_operand): New
|
||||
predicates.
|
||||
* config/sh/sh-protos.h (get_t_reg_rtx): New prototype.
|
||||
* config/sh/sh.c (get_t_reg_rtx): New function. Use it when invoking
|
||||
gen_branch_true and gen_branch_false.
|
||||
* config/sh/sh.md: Use get_t_reg_rtx when invoking gen_branch_true and
|
||||
gen_branch_false.
|
||||
(branch_true, branch_false): Use t_reg_operand predicate.
|
||||
(*branch_true, *branch_false): Delete.
|
||||
(movt): Use t_reg_operand predicate.
|
||||
(*negnegt): Use negt_reg_operand predicate and fold little and big
|
||||
endian variants.
|
||||
(*movtt): Use t_reg_operand and fold little and big endian variants.
|
||||
(*movt_qi): Delete.
|
||||
|
||||
2012-07-02 Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
* stmt.c (emit_case_bit_tests): Remove.
|
||||
|
@ -898,3 +898,42 @@
|
||||
(match_test "mode != HImode")
|
||||
(match_test "TARGET_SH4A_ARCH"))))
|
||||
|
||||
;; A predicate describing the T bit register in any form.
|
||||
(define_predicate "t_reg_operand"
|
||||
(match_code "reg,subreg,sign_extend,zero_extend")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case REG:
|
||||
return REGNO (op) == T_REG;
|
||||
|
||||
case SUBREG:
|
||||
return REGNO (SUBREG_REG (op)) == T_REG;
|
||||
|
||||
case ZERO_EXTEND:
|
||||
case SIGN_EXTEND:
|
||||
return GET_CODE (XEXP (op, 0)) == SUBREG
|
||||
&& REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
|
||||
;; A predicate describing a negated T bit register.
|
||||
(define_predicate "negt_reg_operand"
|
||||
(match_code "subreg,xor")
|
||||
{
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case XOR:
|
||||
return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
|
||||
&& satisfies_constraint_M (XEXP (op, 1));
|
||||
|
||||
case SUBREG:
|
||||
return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
|
@ -109,6 +109,7 @@ extern bool sh_vector_mode_supported_p (enum machine_mode);
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
extern const char *output_jump_label_table (void);
|
||||
extern rtx get_t_reg_rtx (void);
|
||||
extern rtx get_fpscr_rtx (void);
|
||||
extern int sh_media_register_for_return (void);
|
||||
extern void sh_expand_prologue (void);
|
||||
|
@ -1874,7 +1874,7 @@ prepare_cbranch_operands (rtx *operands, enum machine_mode mode,
|
||||
void
|
||||
expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
|
||||
{
|
||||
rtx (*branch_expander) (rtx) = gen_branch_true;
|
||||
rtx (*branch_expander) (rtx, rtx) = gen_branch_true;
|
||||
rtx jump;
|
||||
|
||||
comparison = prepare_cbranch_operands (operands, SImode, comparison);
|
||||
@ -1888,7 +1888,7 @@ expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int probability)
|
||||
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (SImode, T_REG),
|
||||
gen_rtx_fmt_ee (comparison, SImode,
|
||||
operands[1], operands[2])));
|
||||
jump = emit_jump_insn (branch_expander (operands[3]));
|
||||
jump = emit_jump_insn (branch_expander (operands[3], get_t_reg_rtx ()));
|
||||
if (probability >= 0)
|
||||
add_reg_note (jump, REG_BR_PROB, GEN_INT (probability));
|
||||
|
||||
@ -1941,7 +1941,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
|
||||
if (TARGET_CMPEQDI_T)
|
||||
{
|
||||
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
|
||||
emit_jump_insn (gen_branch_true (operands[3]));
|
||||
emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
|
||||
return true;
|
||||
}
|
||||
msw_skip = NE;
|
||||
@ -1969,7 +1969,7 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
|
||||
if (TARGET_CMPEQDI_T)
|
||||
{
|
||||
emit_insn (gen_cmpeqdi_t (operands[1], operands[2]));
|
||||
emit_jump_insn (gen_branch_false (operands[3]));
|
||||
emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
|
||||
return true;
|
||||
}
|
||||
msw_taken = NE;
|
||||
@ -2304,9 +2304,9 @@ sh_emit_compare_and_branch (rtx *operands, enum machine_mode mode)
|
||||
sh_emit_set_t_insn (gen_ieee_ccmpeqsf_t (op0, op1), mode);
|
||||
|
||||
if (branch_code == code)
|
||||
emit_jump_insn (gen_branch_true (operands[3]));
|
||||
emit_jump_insn (gen_branch_true (operands[3], get_t_reg_rtx ()));
|
||||
else
|
||||
emit_jump_insn (gen_branch_false (operands[3]));
|
||||
emit_jump_insn (gen_branch_false (operands[3], get_t_reg_rtx ()));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2340,7 +2340,7 @@ sh_emit_compare_and_set (rtx *operands, enum machine_mode mode)
|
||||
{
|
||||
lab = gen_label_rtx ();
|
||||
sh_emit_scc_to_t (EQ, op0, op1);
|
||||
emit_jump_insn (gen_branch_true (lab));
|
||||
emit_jump_insn (gen_branch_true (lab, get_t_reg_rtx ()));
|
||||
code = GT;
|
||||
}
|
||||
else
|
||||
@ -3360,7 +3360,7 @@ gen_shifty_op (int code, rtx *operands)
|
||||
if (code == LSHIFTRT)
|
||||
{
|
||||
emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
|
||||
emit_insn (gen_movt (operands[0]));
|
||||
emit_insn (gen_movt (operands[0], get_t_reg_rtx ()));
|
||||
return;
|
||||
}
|
||||
else if (code == ASHIFT)
|
||||
@ -9504,6 +9504,15 @@ reg_unused_after (rtx reg, rtx insn)
|
||||
|
||||
#include "ggc.h"
|
||||
|
||||
static GTY(()) rtx t_reg_rtx;
|
||||
rtx
|
||||
get_t_reg_rtx (void)
|
||||
{
|
||||
if (! t_reg_rtx)
|
||||
t_reg_rtx = gen_rtx_REG (SImode, T_REG);
|
||||
return t_reg_rtx;
|
||||
}
|
||||
|
||||
static GTY(()) rtx fpscr_rtx;
|
||||
rtx
|
||||
get_fpscr_rtx (void)
|
||||
@ -12049,7 +12058,7 @@ sh_expand_t_scc (rtx operands[])
|
||||
result = gen_reg_rtx (SImode);
|
||||
val = INTVAL (op1);
|
||||
if ((code == EQ && val == 1) || (code == NE && val == 0))
|
||||
emit_insn (gen_movt (result));
|
||||
emit_insn (gen_movt (result, get_t_reg_rtx ()));
|
||||
else if ((code == EQ && val == 0) || (code == NE && val == 1))
|
||||
emit_insn (gen_movnegt (result));
|
||||
else if (code == EQ || code == NE)
|
||||
|
@ -4450,8 +4450,8 @@ label:
|
||||
emit_insn (gen_movsi (operands[0], operands[1]));
|
||||
|
||||
emit_jump_insn (INTVAL (operands[3])
|
||||
? gen_branch_true (skip_neg_label)
|
||||
: gen_branch_false (skip_neg_label));
|
||||
? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
|
||||
: gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
|
||||
|
||||
emit_label_after (skip_neg_label,
|
||||
emit_insn (gen_negsi2 (operands[0], operands[1])));
|
||||
@ -4519,8 +4519,8 @@ label:
|
||||
emit_insn (gen_movsi (high_dst, high_src));
|
||||
|
||||
emit_jump_insn (INTVAL (operands[3])
|
||||
? gen_branch_true (skip_neg_label)
|
||||
: gen_branch_false (skip_neg_label));
|
||||
? gen_branch_true (skip_neg_label, get_t_reg_rtx ())
|
||||
: gen_branch_false (skip_neg_label, get_t_reg_rtx ()));
|
||||
|
||||
if (!INTVAL (operands[3]))
|
||||
emit_insn (gen_clrt ());
|
||||
@ -7195,7 +7195,8 @@ label:
|
||||
;; ------------------------------------------------------------------------
|
||||
|
||||
(define_insn "branch_true"
|
||||
[(set (pc) (if_then_else (ne (reg:SI T_REG) (const_int 0))
|
||||
[(set (pc) (if_then_else (ne (match_operand 1 "t_reg_operand" "")
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1"
|
||||
@ -7204,31 +7205,9 @@ label:
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
;; The *branch_true patterns help combine when trying to invert conditions.
|
||||
(define_insn "*branch_true"
|
||||
[(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1 && TARGET_LITTLE_ENDIAN"
|
||||
{
|
||||
return output_branch (1, insn, operands);
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
(define_insn "*branch_true"
|
||||
[(set (pc) (if_then_else (ne (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
|
||||
{
|
||||
return output_branch (1, insn, operands);
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
(define_insn "branch_false"
|
||||
[(set (pc) (if_then_else (eq (reg:SI T_REG) (const_int 0))
|
||||
[(set (pc) (if_then_else (eq (match_operand 1 "t_reg_operand" "")
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1"
|
||||
@ -7237,29 +7216,6 @@ label:
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
;; The *branch_false patterns help combine when trying to invert conditions.
|
||||
(define_insn "*branch_false"
|
||||
[(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1 && TARGET_LITTLE_ENDIAN"
|
||||
{
|
||||
return output_branch (0, insn, operands);
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
(define_insn "*branch_false"
|
||||
[(set (pc) (if_then_else (eq (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_SH1 && ! TARGET_LITTLE_ENDIAN"
|
||||
{
|
||||
return output_branch (0, insn, operands);
|
||||
}
|
||||
[(set_attr "type" "cbranch")])
|
||||
|
||||
;; Patterns to prevent reorg from re-combining a condbranch with a branch
|
||||
;; which destination is too far away.
|
||||
;; The const_int_operand is distinct for each branch target; it avoids
|
||||
@ -9672,7 +9628,7 @@ label:
|
||||
|
||||
(define_insn "movt"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(eq:SI (reg:SI T_REG) (const_int 1)))]
|
||||
(match_operand:SI 1 "t_reg_operand"))]
|
||||
"TARGET_SH1"
|
||||
"movt %0"
|
||||
[(set_attr "type" "arith")])
|
||||
@ -9854,62 +9810,25 @@ label:
|
||||
"negc %1,%0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
;; The *negnegt patterns help the combine pass to figure out how to fold
|
||||
;; The *negnegt pattern helps the combine pass to figure out how to fold
|
||||
;; an explicit double T bit negation.
|
||||
(define_insn_and_split "*negnegt"
|
||||
[(set (reg:SI T_REG)
|
||||
(eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3)
|
||||
(const_int 0)))]
|
||||
"! TARGET_LITTLE_ENDIAN"
|
||||
(eq:SI (match_operand 0 "negt_reg_operand" "") (const_int 0)))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
""
|
||||
[(const_int 0)])
|
||||
|
||||
(define_insn_and_split "*negnegt"
|
||||
[(set (reg:SI T_REG)
|
||||
(eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0)
|
||||
(const_int 0)))]
|
||||
"TARGET_LITTLE_ENDIAN"
|
||||
"#"
|
||||
""
|
||||
[(const_int 0)])
|
||||
|
||||
;; The *movtt patterns eliminate redundant T bit to T bit moves / tests.
|
||||
;; The *movtt pattern eliminates redundant T bit to T bit moves / tests.
|
||||
(define_insn_and_split "*movtt"
|
||||
[(set (reg:SI T_REG)
|
||||
(eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
|
||||
(const_int 1)))]
|
||||
"! TARGET_LITTLE_ENDIAN"
|
||||
(eq:SI (match_operand 0 "t_reg_operand" "") (const_int 1)))]
|
||||
"TARGET_SH1"
|
||||
"#"
|
||||
""
|
||||
[(const_int 0)])
|
||||
|
||||
(define_insn_and_split "*movtt"
|
||||
[(set (reg:SI T_REG)
|
||||
(eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
|
||||
(const_int 1)))]
|
||||
"TARGET_LITTLE_ENDIAN"
|
||||
"#"
|
||||
""
|
||||
[(const_int 0)])
|
||||
|
||||
;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern
|
||||
;; into a movt Rn, xor #1 Rn pattern. This can happen when e.g. a function
|
||||
;; returns the inverted T bit value.
|
||||
(define_insn "*movt_qi"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))]
|
||||
"! TARGET_LITTLE_ENDIAN"
|
||||
"movt %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_insn "*movt_qi"
|
||||
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
|
||||
(zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))]
|
||||
"TARGET_LITTLE_ENDIAN"
|
||||
"movt %0"
|
||||
[(set_attr "type" "arith")])
|
||||
|
||||
(define_expand "cstoresf4"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(match_operator:SI 1 "sh_float_comparison_operator"
|
||||
@ -13960,7 +13879,7 @@ label:
|
||||
else
|
||||
{
|
||||
emit_insn (gen_stack_protect_test_si (operands[0], operands[1]));
|
||||
emit_jump_insn (gen_branch_true (operands[2]));
|
||||
emit_jump_insn (gen_branch_true (operands[2], get_t_reg_rtx ()));
|
||||
}
|
||||
|
||||
DONE;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2012-07-02 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
PR target/51244
|
||||
* gcc.target/sh/pr51244-1.c: Check that movt insn is not generated.
|
||||
|
||||
2012-07-02 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/53821
|
||||
|
@ -4,7 +4,7 @@
|
||||
/* { dg-do compile { target "sh*-*-*" } } */
|
||||
/* { dg-options "-O1 -mbranch-cost=2" } */
|
||||
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
|
||||
/* { dg-final { scan-assembler-not "tst|negc|extu" } } */
|
||||
/* { dg-final { scan-assembler-not "movt|tst|negc|extu" } } */
|
||||
|
||||
int
|
||||
testfunc_00 (int a, int b, int c, int d)
|
||||
|
Loading…
x
Reference in New Issue
Block a user