aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@freesoft.cz>1999-12-17 01:45:03 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>1999-12-17 00:45:03 +0000
commite9e808584efc60a8d2de1327cc2217b33dae4b32 (patch)
tree992641373226966909b1c51495ad6577b0174238
parenta1cbdd7f515eb1b2b444e3d1b5c8ac64df62042e (diff)
downloadgcc-e9e808584efc60a8d2de1327cc2217b33dae4b32.zip
gcc-e9e808584efc60a8d2de1327cc2217b33dae4b32.tar.gz
gcc-e9e808584efc60a8d2de1327cc2217b33dae4b32.tar.bz2
i386.md (HI to SImode promoting splitters): Rewrite.
* i386.md (HI to SImode promoting splitters): Rewrite. (pushsf mem peep2): New. (testhi to andhi peep2): Remove. * i386.h (x86_promote_QImode): New. (TARGET_PROMOTE_QImode): New. (PREDICATE_CODES): Add promotable_binary_operator. * i386.c (x86_promote_QImode0: New. (promotable_binary_operator): New. * i386-protos.h (promotable_binary_operator): New. From-SVN: r30985
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c25
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/config/i386/i386.md231
5 files changed, 153 insertions, 117 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a261619..cef71f4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
Fri Dec 17 01:32:38 MET 1999 Jan Hubicka <hubicka@freesoft.cz>
+ * i386.md (HI to SImode promoting splitters): Rewrite.
+ (pushsf mem peep2): New.
+ (testhi to andhi peep2): Remove.
+ * i386.h (x86_promote_QImode): New.
+ (TARGET_PROMOTE_QImode): New.
+ (PREDICATE_CODES): Add promotable_binary_operator.
+ * i386.c (x86_promote_QImode0: New.
+ (promotable_binary_operator): New.
+ * i386-protos.h (promotable_binary_operator): New.
+
* i386.md (test?i_1): Use "nonmemory_operand" predicate, simplify
condition.
(one_cmpl?i*): Pass "NOT" to unary_operator_ok.
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 3ab97a7..d95dbb6 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -60,6 +60,7 @@ extern int binary_fp_operator PROTO((rtx, enum machine_mode));
extern int mult_operator PROTO((rtx, enum machine_mode));
extern int div_operator PROTO((rtx, enum machine_mode));
extern int arith_or_logical_operator PROTO((rtx, enum machine_mode));
+extern int promotable_binary_operator PROTO((rtx, enum machine_mode));
extern int memory_displacement_operand PROTO((rtx, enum machine_mode));
extern int cmpsi_operand PROTO((rtx, enum machine_mode));
extern int long_memory_operand PROTO((rtx, enum machine_mode));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 513b81b..74d67c2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -205,6 +205,7 @@ const int x86_use_cltd = ~(m_PENT | m_K6);
const int x86_read_modify_write = ~m_PENT;
const int x86_read_modify = ~(m_PENT | m_PPRO);
const int x86_split_long_moves = m_PPRO;
+const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486;
#define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx))
@@ -1177,6 +1178,30 @@ fcmov_comparison_operator (op, mode)
&& GET_CODE (op) == unsigned_condition (GET_CODE (op)));
}
+/* Return 1 if OP is a binary operator that can be promoted to wider mode. */
+
+int
+promotable_binary_operator (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ switch (GET_CODE (op))
+ {
+ case MULT:
+ /* Modern CPUs have same latency for HImode and SImode multiply,
+ but 386 and 486 do HImode multiply faster. */
+ return ix86_cpu > PROCESSOR_I486;
+ case PLUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case ASHIFT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/* Nearly general operand, but accept any const_double, since we wish
to be able to drop them into memory rather than have them get pulled
into registers. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 5640b66..7cdfe37 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -161,6 +161,7 @@ extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
extern const int x86_use_loop, x86_use_fiop, x86_use_mov0;
extern const int x86_use_cltd, x86_read_modify_write;
extern const int x86_read_modify, x86_split_long_moves;
+extern const int x86_promote_QImode;
#define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
#define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
@@ -182,6 +183,7 @@ extern const int x86_read_modify, x86_split_long_moves;
#define TARGET_SPLIT_LONG_MOVES (x86_split_long_moves & CPUMASK)
#define TARGET_READ_MODIFY_WRITE (x86_read_modify_write & CPUMASK)
#define TARGET_READ_MODIFY (x86_read_modify & CPUMASK)
+#define TARGET_PROMOTE_QImode (x86_promote_QImode & CPUMASK)
#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
@@ -2437,6 +2439,7 @@ do { long l; \
UMIN, UMAX, COMPARE, MINUS, DIV, MOD, \
UDIV, UMOD, ASHIFT, ROTATE, ASHIFTRT, \
LSHIFTRT, ROTATERT}}, \
+ {"promotable_binary_operator", {PLUS, MULT, AND, IOR, XOR, ASHIFT}}, \
{"memory_displacement_operand", {MEM}}, \
{"cmpsi_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
LABEL_REF, SUBREG, REG, MEM, AND}}, \
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d2b3945..bd2304f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -3344,19 +3344,6 @@
(const_string "incdec")
(const_string "alu")))])
-;; If we know we're not touching memory, promote HImode references to SImode.
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (plus:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);")
-
(define_insn "*addhi_2"
[(set (reg:CCNO 17)
(compare:CCNO
@@ -4456,18 +4443,6 @@
}"
[(set_attr "type" "alu,alu,imovx")])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (and:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);")
-
(define_insn "*andhi_2"
[(set (reg:CCNO 17)
(compare:CCNO (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
@@ -4479,23 +4454,6 @@
"and{w}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")])
-(define_split
- [(set (reg:CCNO 17)
- (compare:CCNO (and:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "immediate_operand" ""))
- (const_int 0)))
- (set (match_operand:HI 0 "register_operand" "")
- (and:HI (match_dup 1) (match_dup 2)))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (reg:CCNO 17)
- (compare:CCNO (and:SI (match_dup 1) (match_dup 2))
- (const_int 0)))
- (set (match_dup 0)
- (and:SI (match_dup 1) (match_dup 2)))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);")
-
(define_expand "andqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(and:QI (match_operand:QI 1 "nonimmediate_operand" "")
@@ -4661,18 +4619,6 @@
"or{w}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (ior:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);")
-
(define_insn "*iorhi_2"
[(set (reg:CCNO 17)
(compare:CCNO (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
@@ -4766,18 +4712,6 @@
"xor{w}\\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (xor:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_lowpart (SImode, operands[2]);")
-
(define_insn "*xorhi_2"
[(set (reg:CCNO 17)
(compare:CCNO (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
@@ -5396,16 +5330,6 @@
"not{w}\\t%0"
[(set_attr "type" "negnot")])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (not:HI (match_operand:HI 1 "register_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (not:SI (match_dup 1)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);")
-
(define_insn "*one_cmplhi2_2"
[(set (reg:CCNO 17)
(compare:CCNO (not:HI (match_operand:HI 1 "nonimmediate_operand" "0"))
@@ -5746,17 +5670,6 @@
]
(const_string "ishift")))])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (ashift:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:QI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 17))]
- "! TARGET_PARTIAL_REG_STALL && reload_completed"
- [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC 17))])]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);")
-
(define_insn "*ashlhi3_cmpno"
[(set (reg:CCNO 17)
(compare:CCNO
@@ -8277,19 +8190,6 @@
cmov%c1\\t{%3, %0|%0, %3}"
[(set_attr "type" "icmov")])
-(define_split
- [(set (match_operand:HI 0 "register_operand" "")
- (if_then_else:HI (match_operator 1 "comparison_operator"
- [(reg 17) (const_int 0)])
- (match_operand:HI 2 "register_operand" "")
- (match_operand:HI 3 "register_operand" "")))]
- "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE"
- [(set (match_dup 0)
- (if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[2] = gen_lowpart (SImode, operands[2]);
- operands[3] = gen_lowpart (SImode, operands[3]);")
-
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
(if_then_else:SF (match_operand 1 "comparison_operator" "")
@@ -8436,6 +8336,107 @@
DONE;
}")
+;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (match_operator 3 "promotable_binary_operator"
+ [(match_operand 1 "register_operand" "")
+ (match_operand 2 "nonmemory_operand" "")]))
+ (clobber (reg:CC 17))]
+ "! TARGET_PARTIAL_REG_STALL && reload_completed
+ && ((GET_MODE (operands[0]) == HImode
+ && (!optimize_size || GET_CODE (operands[2]) != CONST_INT
+ || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(parallel [(set (match_dup 0)
+ (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ if (GET_CODE (operands[3]) != ASHIFT)
+ operands[2] = gen_lowpart (SImode, operands[2]);
+ GET_MODE (operands[3]) = SImode;")
+
+(define_split
+ [(set (reg:CCNO 17)
+ (compare:CCNO (and (match_operand 1 "register_operand" "")
+ (match_operand 2 "immediate_operand" ""))
+ (const_int 0)))
+ (set (match_operand 0 "register_operand" "")
+ (and (match_dup 1) (match_dup 2)))]
+ "! TARGET_PARTIAL_REG_STALL && reload_completed
+ && (GET_MODE (operands[0]) == HImode
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(parallel [(set (reg:CCNO 17)
+ (compare:CCNO (and:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0)
+ (and:SI (match_dup 1) (match_dup 2)))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_lowpart (SImode, operands[2]);")
+
+(define_split
+ [(set (reg:CCNO 17)
+ (compare:CCNO (and (match_operand 0 "register_operand" "")
+ (match_operand 1 "immediate_operand" ""))
+ (const_int 0)))]
+ "! TARGET_PARTIAL_REG_STALL && reload_completed
+ && (GET_MODE (operands[0]) == HImode
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(set (reg:CCNO 17)
+ (compare:CCNO (and:SI (match_dup 0) (match_dup 1))
+ (const_int 0)))]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (neg (match_operand 1 "register_operand" "")))
+ (clobber (reg:CC 17))]
+ "! TARGET_PARTIAL_REG_STALL && reload_completed
+ && (GET_MODE (operands[0]) == HImode
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(parallel [(set (match_dup 0)
+ (neg:SI (match_dup 1)))
+ (clobber (reg:CC 17))])]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (not (match_operand 1 "register_operand" "")))]
+ "! TARGET_PARTIAL_REG_STALL && reload_completed
+ && (GET_MODE (operands[0]) == HImode
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(set (match_dup 0)
+ (not:SI (match_dup 1)))]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);")
+
+(define_split
+ [(set (match_operand 0 "register_operand" "")
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(reg 17) (const_int 0)])
+ (match_operand 2 "register_operand" "")
+ (match_operand 3 "register_operand" "")))]
+ "! TARGET_PARTIAL_REG_STALL && TARGET_CMOVE
+ && (GET_MODE (operands[0]) == HImode
+ || (GET_MODE (operands[0]) == QImode
+ && (TARGET_PROMOTE_QImode || optimize_size)))"
+ [(set (match_dup 0)
+ (if_then_else:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
+ "operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[2] = gen_lowpart (SImode, operands[2]);
+ operands[3] = gen_lowpart (SImode, operands[3]);")
+
+
;; RTL Peephole optimizations, run before sched2. These primarily look to
;; transform a complex memory operation into two memory to register operations.
@@ -8449,6 +8450,17 @@
(set (match_dup 0) (match_dup 2))]
"")
+;; We need to handle SFmode only, because DFmode and XFmode is split to
+;; SImode pushes.
+(define_peephole2
+ [(set (match_operand:SF 0 "push_operand" "")
+ (match_operand:SF 1 "memory_operand" ""))
+ (match_scratch:SF 2 "r")]
+ "! optimize_size && ! TARGET_PUSH_MEMORY"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (match_dup 2))]
+ "")
+
(define_peephole2
[(set (match_operand:HI 0 "push_operand" "")
(match_operand:HI 1 "memory_operand" ""))
@@ -8626,23 +8638,8 @@
(and:SI (match_dup 0) (match_dup 1)))])]
"")
-(define_peephole2
- [(set (reg:CCNO 17)
- (compare:CCNO (and:HI (match_operand:HI 0 "register_operand" "")
- (match_operand:HI 1 "immediate_operand" ""))
- (const_int 0)))]
- "! TARGET_PARTIAL_REG_STALL
- && (true_regnum (operands[0]) != 0
- || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K'))
- && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
- [(parallel
- [(set (reg:CCNO 17)
- (compare:CCNO (and:HI (match_dup 0)
- (match_dup 1))
- (const_int 0)))
- (set (match_dup 0)
- (and:HI (match_dup 0) (match_dup 1)))])]
- "")
+;; We don't need to handle HImode case, because it will be promoted to SImode
+;; on ! TARGET_PARTIAL_REG_STALL
(define_peephole2
[(set (reg:CCNO 17)