===================================================================
@@ -235,7 +235,9 @@
extern bool sh_is_nott_insn (const rtx_insn* i);
extern rtx sh_movt_set_dest (const rtx_insn* i);
+extern rtx sh_movt_set_dest (const_rtx i);
extern rtx sh_movrt_set_dest (const rtx_insn* i);
+extern rtx sh_movrt_set_dest (const_rtx i);
inline bool sh_is_movt_insn (const rtx_insn* i)
{
===================================================================
@@ -3208,6 +3208,10 @@
/ mov_insn_size (mode, TARGET_SH2A));
return true;
}
+
+ if (sh_movt_set_dest (x) != NULL || sh_movrt_set_dest (x) != NULL)
+ return COSTS_N_INSNS (1);
+
return false;
/* The cost of a mem access is mainly the cost of the address mode. */
@@ -11703,13 +11707,15 @@
rtx
sh_movt_set_dest (const rtx_insn* i)
{
- if (i == NULL)
- return NULL;
+ return i == NULL ? NULL : sh_movt_set_dest (PATTERN (i));
+}
- const_rtx p = PATTERN (i);
- return GET_CODE (p) == SET
- && arith_reg_dest (XEXP (p, 0), SImode)
- && t_reg_operand (XEXP (p, 1), VOIDmode) ? XEXP (p, 0) : NULL;
+rtx
+sh_movt_set_dest (const_rtx pat)
+{
+ return GET_CODE (pat) == SET
+ && arith_reg_dest (XEXP (pat, 0), SImode)
+ && t_reg_operand (XEXP (pat, 1), VOIDmode) ? XEXP (pat, 0) : NULL;
}
/* Given an insn, check whether it's a 'movrt' kind of insn, i.e. an insn
@@ -11718,18 +11724,20 @@
rtx
sh_movrt_set_dest (const rtx_insn* i)
{
- if (i == NULL)
- return NULL;
+ return i == NULL ? NULL : sh_movrt_set_dest (PATTERN (i));
+}
- const_rtx p = PATTERN (i);
-
+rtx
+sh_movrt_set_dest (const_rtx pat)
+{
/* The negc movrt replacement is inside a parallel. */
- if (GET_CODE (p) == PARALLEL)
- p = XVECEXP (p, 0, 0);
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
- return GET_CODE (p) == SET
- && arith_reg_dest (XEXP (p, 0), SImode)
- && negt_reg_operand (XEXP (p, 1), VOIDmode) ? XEXP (p, 0) : NULL;
+ return GET_CODE (pat) == SET
+ && arith_reg_dest (XEXP (pat, 0), SImode)
+ && negt_reg_operand (XEXP (pat, 1), VOIDmode) ? XEXP (pat, 0) : NULL;
+
}
/* Given an insn and a reg number, tell whether the reg dies or is unused
===================================================================
@@ -8524,6 +8524,24 @@
[(set_attr "type" "arith") ;; poor approximation
(set_attr "length" "4")])
+(define_insn_and_split "*cset_zero"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (if_then_else:SI (match_operand 1 "treg_set_expr_not_const01")
+ (match_dup 0) (const_int 0)))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1 && TARGET_ZDCBRANCH && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (if_then_else:SI (match_dup 1) (match_dup 0) (const_int 0)))]
+{
+ sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
+ if (ti.remove_trailing_nott ())
+ operands[1] = gen_rtx_EQ (SImode, get_t_reg_rtx (), const0_rtx);
+ else
+ operands[1] = gen_rtx_EQ (SImode, get_t_reg_rtx (), const1_rtx);
+})
+
(define_expand "cstoresf4"
[(set (match_operand:SI 0 "register_operand")
(match_operator:SI 1 "ordered_comparison_operator"
===================================================================
@@ -1,8 +1,11 @@
/* Check that zero-displacement branches are used instead of branch-free
- execution patterns. */
+ execution patterns.
+ This is usually handled by the *cset_zero patterns. */
/* { dg-do compile } */
-/* { dg-options "-O1 -mzdcbranch" } */
-/* { dg-final { scan-assembler-not "subc|and" } } */
+/* { dg-options "-O1 -mzdcbranch" } */
+/* { dg-final { scan-assembler-not "subc|and|bra" } } */
+/* { dg-final { scan-assembler-times "bf\t0f" 1 } } */
+/* { dg-final { scan-assembler-times "bt\t0f" 1 } } */
int*
test_00 (int* s)