+Tue Aug 25 05:48:18 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
+
+ * config/sparc/sparc.c (arith_4096_operand, arith_add_operand,
+ arith_double_4096_operand, arith_double_add_operand): New
+ predicates.
+ * config/sparc/sparc.h (PREDICATE_CODES): Add them, declare them.
+ * config/sparc/sparc.md (adddi3, addsi3, subdi3, subsi3): Use
+ them to transform add/sub 4096 into add/sub -4096.
+
Mon Aug 24 23:31:03 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
* loop.c (scan_loop): Allocate some slop to handle pseudos
return SPARC_SIMM13_P (val);
}
+/* Return true if OP is a constant 4096 */
+
+int
+arith_4096_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int val;
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+ val = INTVAL (op) & 0xffffffff;
+ return val == 4096;
+}
+
+/* Return true if OP is suitable as second operand for add/sub */
+
+int
+arith_add_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return arith_operand (op, mode) || arith_4096_operand (op, mode);
+}
+
/* Return true if OP is a CONST_INT or a CONST_DOUBLE which can fit in the
immediate field of OR and XOR instructions. Used for 64-bit
constant formation patterns. */
&& (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
}
+/* Return true if OP is a constant 4096 for DImode on ARCH64 */
+
+int
+arith_double_4096_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (TARGET_ARCH64 &&
+ ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
+ (GET_CODE (op) == CONST_DOUBLE &&
+ CONST_DOUBLE_LOW (op) == 4096 &&
+ CONST_DOUBLE_HIGH (op) == 0)));
+}
+
+/* Return true if OP is suitable as second operand for add/sub in DImode */
+
+int
+arith_double_add_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
+}
+
/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
can fit in an 11 bit immediate field. This is an acceptable DImode
operand for the movcc instructions. */
{"cc_arithop", {AND, IOR, XOR}}, \
{"cc_arithopn", {AND, IOR}}, \
{"arith_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
+{"arith_add_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
{"arith11_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
{"arith10_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT}}, \
{"arith_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
+{"arith_double_add_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}},\
{"arith11_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
{"arith10_double_operand", {SUBREG, REG, CONSTANT_P_RTX, CONST_INT, CONST_DOUBLE}}, \
{"small_int", {CONST_INT, CONSTANT_P_RTX}}, \
extern int arith11_double_operand ();
extern int arith11_operand ();
extern int arith_double_operand ();
+extern int arith_double_4096_operand ();
+extern int arith_double_add_operand ();
extern int arith_operand ();
+extern int arith_4096_operand ();
+extern int arith_add_operand ();
extern int call_operand_address ();
extern int input_operand ();
extern int zero_operand ();
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
""
"
{
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
+ if (arith_double_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (DImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
}")
(define_insn "adddi3_insn_sp32"
[(set_attr "type" "binary")
(set_attr "length" "1")])
-(define_insn "addsi3"
+(define_expand "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,d")))]
+ ""
+ "
+{
+ if (arith_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_MINUS (SImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
+}")
+
+(define_insn "*addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
(plus:SI (match_operand:SI 1 "arith_operand" "%r,d")
(match_operand:SI 2 "arith_operand" "rI,d")))]
(define_expand "subdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_double_add_operand" "rHI")))]
""
"
{
gen_rtx_REG (CCmode, SPARC_ICC_REG)))));
DONE;
}
+ if (arith_double_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (DImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
}")
(define_insn "*subdi3_sp32"
[(set_attr "type" "binary")
(set_attr "length" "1")])
-(define_insn "subsi3"
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,d")
+ (match_operand:SI 2 "arith_add_operand" "rI,d")))]
+ ""
+ "
+{
+ if (arith_4096_operand(operands[2], DImode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (SImode, operands[1],
+ GEN_INT(-4096))));
+ DONE;
+ }
+}")
+
+(define_insn "*subsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d")
(minus:SI (match_operand:SI 1 "register_operand" "r,d")
(match_operand:SI 2 "arith_operand" "rI,d")))]