diff options
author | Jan Hubicka <hubicka@freesoft.cz> | 1999-12-17 01:45:03 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 1999-12-17 00:45:03 +0000 |
commit | e9e808584efc60a8d2de1327cc2217b33dae4b32 (patch) | |
tree | 992641373226966909b1c51495ad6577b0174238 | |
parent | a1cbdd7f515eb1b2b444e3d1b5c8ac64df62042e (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 25 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 231 |
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) |