Commit 1646cf41 by Richard Earnshaw

ChangeLog

From-SVN: r37798
parent 4211a8fb
...@@ -4126,6 +4126,13 @@ arm_gen_rotated_half_load (memref) ...@@ -4126,6 +4126,13 @@ arm_gen_rotated_half_load (memref)
return gen_rtx_ROTATE (SImode, base, GEN_INT (16)); return gen_rtx_ROTATE (SImode, base, GEN_INT (16));
} }
/* Select a dominance comparison mode if possible. We support three forms.
COND_OR == 0 => (X && Y)
COND_OR == 1 => ((! X( || Y)
COND_OR == 2 => (X || Y)
If we are unable to support a dominance comparsison we return CC mode.
This will then fail to match for the RTL expressions that generate this
call. */
static enum machine_mode static enum machine_mode
select_dominance_cc_mode (x, y, cond_or) select_dominance_cc_mode (x, y, cond_or)
rtx x; rtx x;
...@@ -4144,7 +4151,10 @@ select_dominance_cc_mode (x, y, cond_or) ...@@ -4144,7 +4151,10 @@ select_dominance_cc_mode (x, y, cond_or)
!= CCmode)) != CCmode))
return CCmode; return CCmode;
if (cond_or) /* The if_then_else variant of this tests the second condition if the
first passes, but is true if the first fails. Reverse the first
condition to get a true "inclusive-or" expression. */
if (cond_or == 1)
cond1 = reverse_condition (cond1); cond1 = reverse_condition (cond1);
/* If the comparisons are not equal, and one doesn't dominate the other, /* If the comparisons are not equal, and one doesn't dominate the other,
...@@ -4296,6 +4306,29 @@ arm_select_cc_mode (op, x, y) ...@@ -4296,6 +4306,29 @@ arm_select_cc_mode (op, x, y)
&& GET_CODE (y) == CONST_INT) && GET_CODE (y) == CONST_INT)
return CC_Zmode; return CC_Zmode;
/* A construct for a conditional compare, if the false arm contains
0, then both conditions must be true, otherwise either condition
must be true. Not all conditions are possible, so CCmode is
returned if it can't be done. */
if (GET_CODE (x) == IF_THEN_ELSE
&& (XEXP (x, 2) == const0_rtx
|| XEXP (x, 2) == const1_rtx)
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
INTVAL (XEXP (x, 2)));
/* Alternate canonicalizations of the above. These are somewhat cleaner. */
if (GET_CODE (x) == AND
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), 0);
if (GET_CODE (x) == IOR
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1), 2);
/* An operation that sets the condition codes as a side-effect, the /* An operation that sets the condition codes as a side-effect, the
V flag is not set correctly, so we can only use comparisons where V flag is not set correctly, so we can only use comparisons where
this doesn't matter. (For LT and GE we can use "mi" and "pl" this doesn't matter. (For LT and GE we can use "mi" and "pl"
...@@ -4312,18 +4345,6 @@ arm_select_cc_mode (op, x, y) ...@@ -4312,18 +4345,6 @@ arm_select_cc_mode (op, x, y)
|| GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT)) || GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT))
return CC_NOOVmode; return CC_NOOVmode;
/* A construct for a conditional compare, if the false arm contains
0, then both conditions must be true, otherwise either condition
must be true. Not all conditions are possible, so CCmode is
returned if it can't be done. */
if (GET_CODE (x) == IF_THEN_ELSE
&& (XEXP (x, 2) == const0_rtx
|| XEXP (x, 2) == const1_rtx)
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
&& GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
return select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
INTVAL (XEXP (x, 2)));
if (GET_MODE (x) == QImode && (op == EQ || op == NE)) if (GET_MODE (x) == QImode && (op == EQ || op == NE))
return CC_Zmode; return CC_Zmode;
......
...@@ -7130,6 +7130,76 @@ ...@@ -7130,6 +7130,76 @@
(set_attr "length" "8")] (set_attr "length" "8")]
) )
(define_insn "*cmp_and"
[(set (match_operand 6 "dominant_cc_register" "")
(compare
(and:SI
(match_operator 4 "arm_comparison_operator"
[(match_operand:SI 0 "s_register_operand" "r,r,r,r")
(match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
(match_operator:SI 5 "arm_comparison_operator"
[(match_operand:SI 2 "s_register_operand" "r,r,r,r")
(match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
(const_int 0)))]
"TARGET_ARM"
"*
{
const char * opcodes[4][2] =
{
{\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
{\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
{\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
{\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
};
int swap =
comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
return opcodes[which_alternative][swap];
}"
[(set_attr "conds" "set")
(set_attr "predicable" "no")
(set_attr "length" "8")]
)
(define_insn "*cmp_ior"
[(set (match_operand 6 "dominant_cc_register" "")
(compare
(ior:SI
(match_operator 4 "arm_comparison_operator"
[(match_operand:SI 0 "s_register_operand" "r,r,r,r")
(match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
(match_operator:SI 5 "arm_comparison_operator"
[(match_operand:SI 2 "s_register_operand" "r,r,r,r")
(match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
(const_int 0)))]
"TARGET_ARM"
"*
{
const char * opcodes[4][2] =
{
{\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
\"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
{\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
\"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
{\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
\"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
{\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
\"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
};
int swap =
comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
return opcodes[which_alternative][swap];
}
"
[(set_attr "conds" "set")
(set_attr "length" "8")]
)
(define_insn "*negscc" (define_insn "*negscc"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(set (match_operand:SI 0 "s_register_operand" "=r")
(neg:SI (match_operator 3 "arm_comparison_operator" (neg:SI (match_operator 3 "arm_comparison_operator"
...@@ -8598,29 +8668,6 @@ ...@@ -8598,29 +8668,6 @@
(define_split (define_split
[(set (match_operand:SI 0 "s_register_operand" "") [(set (match_operand:SI 0 "s_register_operand" "")
(if_then_else:SI (match_operator 1 "arm_comparison_operator" (if_then_else:SI (match_operator 1 "arm_comparison_operator"
[(match_operand 2 "" "") (match_operand 3 "" "")])
(match_operand 4 "" "")
(match_operand 5 "" "")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM && reload_completed && 0"
[(set (match_dup 6) (match_dup 7))
(set (match_dup 0)
(if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
(match_dup 4)
(match_dup 5)))]
"
{
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
operands[2], operands[3]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM);
operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
}"
)
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(if_then_else:SI (match_operator 1 "arm_comparison_operator"
[(match_operand:SI 2 "s_register_operand" "") [(match_operand:SI 2 "s_register_operand" "")
(match_operand:SI 3 "arm_add_operand" "")]) (match_operand:SI 3 "arm_add_operand" "")])
(match_operand:SI 4 "arm_rhs_operand" "") (match_operand:SI 4 "arm_rhs_operand" "")
...@@ -8629,17 +8676,24 @@ ...@@ -8629,17 +8676,24 @@
(clobber (reg:CC CC_REGNUM))] (clobber (reg:CC CC_REGNUM))]
"TARGET_ARM && reload_completed" "TARGET_ARM && reload_completed"
[(set (match_dup 6) (match_dup 7)) [(set (match_dup 6) (match_dup 7))
(set (match_dup 0) (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
(if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)]) (set (match_dup 0) (match_dup 4)))
(match_dup 4) (cond_exec (match_dup 8)
(not:SI (match_dup 5))))] (set (match_dup 0) (not:SI (match_dup 5))))]
" "
{ {
enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
operands[2], operands[3]); operands[2], operands[3]);
enum rtx_code rc = GET_CODE (operands[1]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM); operands[6] = gen_rtx_REG (mode, CC_REGNUM);
operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]); operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
if (mode == CCFPmode || mode == CCFPEmode)
rc = reverse_condition_maybe_unordered (rc);
else
rc = reverse_condition (rc);
operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
}" }"
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment