aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2011-01-17 10:22:04 -0800
committerRichard Henderson <rth@gcc.gnu.org>2011-01-17 10:22:04 -0800
commit8a5b54490034f3b5a56298ba27ca70206a4dd37a (patch)
treed4b57ae1533dcba8650db3f94092d77be04ed5bc /gcc
parent784f69be19ef920218a7b05d6fb2569596864afb (diff)
downloadgcc-8a5b54490034f3b5a56298ba27ca70206a4dd37a.zip
gcc-8a5b54490034f3b5a56298ba27ca70206a4dd37a.tar.gz
gcc-8a5b54490034f3b5a56298ba27ca70206a4dd37a.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/rx/predicates.md49
-rw-r--r--gcc/config/rx/rx.md216
3 files changed, 225 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8683ed3..e7f9d74 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
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.
diff --git a/gcc/config/rx/predicates.md b/gcc/config/rx/predicates.md
index 5ae5d22..608fca5 100644
--- a/gcc/config/rx/predicates.md
+++ b/gcc/config/rx/predicates.md
@@ -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:
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index a3db92c..d8cd66d 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -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")