Commit 8a5b5449 by Richard Henderson Committed by Richard Henderson

rx: Split adddi3 and subdi3 after reload.

The formulation of the pre-reload pattern allows the lower_subreg
pass to properly split the patterns.  This also required re-writing
rx_source_operand and related predicates to accept subregs.

From-SVN: r168929
parent 784f69be
2011-01-17 Richard Henderson <rth@redhat.com>
* config/rx/predicates.md (rx_constshift_operand): Use match_test.
(rx_restricted_mem_operand): New.
(rx_shift_operand): Use register_operand.
(rx_source_operand, rx_compare_operand): Likewise.
* config/rx/rx.md (addsi3_flags): New expander.
(adddi3): Rewrite as expander.
(adc_internal, *adc_flags, adddi3_internal): New patterns.
(subsi3_flags): New expander.
(subdi3): Rewrite as expander.
(sbb_internal, *sbb_flags, subdi3_internal): New patterns.
* config/rx/rx.c (RX_BUILTIN_SAT): Remove.
(rx_init_builtins): Remove sat builtin.
(rx_expand_builtin): Likewise.
......
......@@ -37,19 +37,19 @@
;; Only small integers or a value in a register are permitted.
(define_predicate "rx_shift_operand"
(match_code "const_int,reg")
{
if (CONST_INT_P (op))
return IN_RANGE (INTVAL (op), 0, 31);
return true;
}
(ior (match_operand 0 "register_operand")
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 31)")))
)
(define_predicate "rx_constshift_operand"
(match_code "const_int")
{
return IN_RANGE (INTVAL (op), 0, 31);
}
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 31)"))
)
(define_predicate "rx_restricted_mem_operand"
(and (match_code "mem")
(match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
)
;; Check that the operand is suitable as the source operand
......@@ -57,20 +57,9 @@
;; and a restricted subset of memory addresses are allowed.
(define_predicate "rx_source_operand"
(match_code "const_int,const_double,const,symbol_ref,label_ref,reg,mem")
{
if (CONSTANT_P (op))
return rx_is_legitimate_constant (op);
if (! MEM_P (op))
return true;
/* Do not allow size conversions whilst accessing memory. */
if (GET_MODE (op) != mode)
return false;
return rx_is_restricted_memory_address (XEXP (op, 0), mode);
}
(ior (match_operand 0 "register_operand")
(match_operand 0 "immediate_operand")
(match_operand 0 "rx_restricted_mem_operand"))
)
;; Check that the operand is suitable as the source operand
......@@ -79,16 +68,8 @@
;; CONST_INTs are not.
(define_predicate "rx_compare_operand"
(match_code "subreg,reg,mem")
{
if (GET_CODE (op) == SUBREG)
return REG_P (XEXP (op, 0));
if (! MEM_P (op))
return true;
return rx_is_restricted_memory_address (XEXP (op, 0), mode);
}
(ior (match_operand 0 "register_operand")
(match_operand 0 "rx_restricted_mem_operand"))
)
;; Return true if OP is a store multiple operation. This looks like:
......
......@@ -988,17 +988,127 @@
(set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
)
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
(plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0,0")
(match_operand:DI 2 "rx_source_operand"
"r,Sint08,Sint16,Sint24,i,Q")))
;; A helper to expand the above with the CC_MODE filled in.
(define_expand "addsi3_flags"
[(parallel [(set (match_operand:SI 0 "register_operand")
(plus:SI (match_operand:SI 1 "register_operand")
(match_operand:SI 2 "rx_source_operand")))
(set (reg:CC_ZSC CC_REG)
(compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
(const_int 0)))])]
)
(define_insn "adc_internal"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
(plus:SI
(plus:SI
(ltu:SI (reg:CC CC_REG) (const_int 0))
(match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
(match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
(clobber (reg:CC CC_REG))]
"reload_completed"
"adc %2,%0"
[(set_attr "timings" "11,11,11,11,11,33")
(set_attr "length" "3,4,5,6,7,6")]
)
(define_insn "*adc_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
(plus:SI
(plus:SI
(ltu:SI (reg:CC CC_REG) (const_int 0))
(match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
(match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
(set (reg CC_REG)
(compare
(plus:SI
(plus:SI
(ltu:SI (reg:CC CC_REG) (const_int 0))
(match_dup 1))
(match_dup 2))
(const_int 0)))]
"reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
"adc %2,%0"
[(set_attr "timings" "11,11,11,11,11,33")
(set_attr "length" "3,4,5,6,7,6")]
)
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "rx_source_operand" "")))]
""
{
rtx op0l, op0h, op1l, op1h, op2l, op2h;
op0l = gen_lowpart (SImode, operands[0]);
op1l = gen_lowpart (SImode, operands[1]);
op2l = gen_lowpart (SImode, operands[2]);
op0h = gen_highpart (SImode, operands[0]);
op1h = gen_highpart (SImode, operands[1]);
op2h = gen_highpart_mode (SImode, DImode, operands[2]);
emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
DONE;
})
(define_insn_and_split "adddi3_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "rx_source_operand" "riQ")))
(set (match_operand:SI 1 "register_operand" "=r")
(plus:SI
(plus:SI
(ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
(match_operand:SI 4 "register_operand" "%1"))
(match_operand:SI 5 "rx_source_operand" "riQ")))
(clobber (match_scratch:SI 6 "=&r"))
(clobber (reg:CC CC_REG))]
""
"add\t%L2, %L0\n\tadc\t%H2, %H0"
[(set_attr "timings" "22,22,22,22,22,44")
(set_attr "length" "5,7,9,11,13,11")]
)
"#"
"reload_completed"
[(const_int 0)]
{
rtx op0l = operands[0];
rtx op0h = operands[1];
rtx op1l = operands[2];
rtx op2l = operands[3];
rtx op1h = operands[4];
rtx op2h = operands[5];
rtx scratch = operands[6];
rtx x;
if (reg_overlap_mentioned_p (op0l, op1h))
{
emit_move_insn (scratch, op0l);
op1h = scratch;
if (reg_overlap_mentioned_p (op0l, op2h))
op2h = scratch;
}
else if (reg_overlap_mentioned_p (op0l, op2h))
{
emit_move_insn (scratch, op0l);
op2h = scratch;
}
if (rtx_equal_p (op0l, op1l))
;
else if (rtx_equal_p (op0l, op2l))
x = op1l, op1l = op2l, op2l = x;
emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
if (rtx_equal_p (op0h, op1h))
;
else if (rtx_equal_p (op0h, op2h))
x = op1h, op1h = op2h, op2h = x;
else
{
emit_move_insn (op0h, op1h);
op1h = op0h;
}
emit_insn (gen_adc_internal (op0h, op1h, op2h));
DONE;
})
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
......@@ -1445,16 +1555,88 @@
(set_attr "length" "2,2,6,3,5")]
)
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(minus:DI (match_operand:DI 1 "register_operand" "0,0")
(match_operand:DI 2 "rx_source_operand" "r,Q")))
;; A helper to expand the above with the CC_MODE filled in.
(define_expand "subsi3_flags"
[(parallel [(set (match_operand:SI 0 "register_operand")
(minus:SI (match_operand:SI 1 "register_operand")
(match_operand:SI 2 "rx_source_operand")))
(set (reg:CC_ZSC CC_REG)
(compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
(const_int 0)))])]
)
(define_insn "sbb_internal"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI
(minus:SI
(match_operand:SI 1 "register_operand" " 0,0")
(match_operand:SI 2 "rx_compare_operand" " r,Q"))
(geu:SI (reg:CC CC_REG) (const_int 0))))
(clobber (reg:CC CC_REG))]
"reload_completed"
"sbb\t%2, %0"
[(set_attr "timings" "11,33")
(set_attr "length" "3,6")]
)
(define_insn "*sbb_flags"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(minus:SI
(minus:SI
(match_operand:SI 1 "register_operand" " 0,0")
(match_operand:SI 2 "rx_compare_operand" " r,Q"))
(geu:SI (reg:CC CC_REG) (const_int 0))))
(set (reg CC_REG)
(compare
(minus:SI
(minus:SI (match_dup 1) (match_dup 2))
(geu:SI (reg:CC CC_REG) (const_int 0)))
(const_int 0)))]
"reload_completed"
"sbb\t%2, %0"
[(set_attr "timings" "11,33")
(set_attr "length" "3,6")]
)
(define_expand "subdi3"
[(set (match_operand:DI 0 "register_operand" "")
(minus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "rx_source_operand" "")))]
""
{
rtx op0l, op0h, op1l, op1h, op2l, op2h;
op0l = gen_lowpart (SImode, operands[0]);
op1l = gen_lowpart (SImode, operands[1]);
op2l = gen_lowpart (SImode, operands[2]);
op0h = gen_highpart (SImode, operands[0]);
op1h = gen_highpart (SImode, operands[1]);
op2h = gen_highpart_mode (SImode, DImode, operands[2]);
emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
DONE;
})
(define_insn_and_split "subdi3_internal"
[(set (match_operand:SI 0 "register_operand" "=&r,&r")
(minus:SI (match_operand:SI 2 "register_operand" " 0, r")
(match_operand:SI 3 "rx_source_operand" "rnQ, r")))
(set (match_operand:SI 1 "register_operand" "= r, r")
(minus:SI
(minus:SI
(match_operand:SI 4 "register_operand" " 1, 1")
(match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
(geu:SI (match_dup 2) (match_dup 3))))
(clobber (reg:CC CC_REG))]
""
"sub\t%L2, %L0\n\tsbb\t%H2, %H0"
[(set_attr "timings" "22,44")
(set_attr "length" "5,11")]
)
"#"
"reload_completed"
[(const_int 0)]
{
emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
DONE;
})
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
......
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