DImode speedup on i386
Bernd Schmidt
crux@pool.informatik.rwth-aachen.de
Wed Feb 18 04:16:00 GMT 1998
The following patch improves performance of DImode operations on the i386.
For the chess program Crafty, which relies heavily upon those operations,
this patch improved the "nodes per second" count in the built-in benchmark
from 79558 to 93047. It also made the executable 12000 bytes smaller.
Bernd
* i386/i386.c (ix86_logical_operator): New function.
(split_di): When splitting a MEM, make sure the new MEMs have
SImode.
* i386/i386.md (xordi3, anddi3, iordi3): New patterns.
Add a define_split to implement them.
Index: config/i386//i386.c
===================================================================
RCS file: /usr/local/cvs/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.1.3.7
diff -c -p -r1.1.3.7 i386.c
*** i386.c 1998/02/16 19:05:44 1.1.3.7
--- i386.c 1998/02/17 10:06:33
*************** arithmetic_comparison_operator (op, mode
*** 1698,1703 ****
--- 1698,1712 ----
return (code != GT && code != LE);
}
+
+ int
+ ix86_logical_operator (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+ {
+ return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;
+ }
+
/* Returns 1 if OP contains a symbol reference */
*************** split_di (operands, num, lo_half, hi_hal
*** 3697,3704 ****
split_double (operands[num], &lo_half[num], &hi_half[num]);
else if (offsettable_memref_p (operands[num]))
{
! lo_half[num] = operands[num];
! hi_half[num] = adj_offsettable_operand (operands[num], 4);
}
else
abort();
--- 3706,3713 ----
split_double (operands[num], &lo_half[num], &hi_half[num]);
else if (offsettable_memref_p (operands[num]))
{
! lo_half[num] = gen_rtx (MEM, SImode, XEXP (operands[num], 0));
! hi_half[num] = gen_rtx (MEM, SImode, XEXP (adj_offsettable_operand (operands[num], 4), 0));
}
else
abort();
Index: config/i386//i386.md
===================================================================
RCS file: /usr/local/cvs/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.1.3.6
diff -c -p -r1.1.3.6 i386.md
*** i386.md 1998/02/16 19:05:47 1.1.3.6
--- i386.md 1998/02/17 10:06:33
*************** byte_xor_operation:
*** 4241,4246 ****
--- 4241,4346 ----
""
"* return AS2 (xor%B0,%2,%0);")
+ ;; logical operations for DImode
+
+ (define_insn "anddi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o")
+ (and:DI (match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o")))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))]
+ ""
+ "#")
+
+ (define_insn "iordi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o")
+ (ior:DI (match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o")))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))]
+ ""
+ "#")
+
+ (define_insn "xordi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o")
+ (xor:DI (match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o")))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))]
+ ""
+ "#")
+
+ (define_split
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o")
+ (match_operator:DI 4 "ix86_logical_operator"
+ [(match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o")]))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+ {
+ rtx low[3], high[3], xops[7], temp;
+ rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3
+ : GET_CODE (operands[4]) == IOR ? gen_iorsi3
+ : GET_CODE (operands[4]) == XOR ? gen_xorsi3
+ : 0);
+
+ if (rtx_equal_p (operands[0], operands[2]))
+ {
+ temp = operands[1];
+ operands[1] = operands[2];
+ operands[2] = temp;
+ }
+
+ split_di (operands, 3, low, high);
+ if (!rtx_equal_p (operands[0], operands[1]))
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[1];
+ xops[3] = low[1];
+
+ if (GET_CODE (operands[0]) != MEM)
+ {
+ emit_insn (gen_movsi (xops[1], xops[3]));
+ emit_insn (gen_movsi (xops[0], xops[2]));
+ }
+ else
+ {
+ xops[4] = high[2];
+ xops[5] = low[2];
+ xops[6] = operands[3];
+ emit_insn (gen_movsi (xops[6], xops[3]));
+ emit_insn ((*genfunc) (xops[6], xops[6], xops[5]));
+ emit_insn (gen_movsi (xops[1], xops[6]));
+ emit_insn (gen_movsi (xops[6], xops[2]));
+ emit_insn ((*genfunc) (xops[6], xops[6], xops[4]));
+ emit_insn (gen_movsi (xops[0], xops[6]));
+ DONE;
+ }
+ }
+
+ if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
+ {
+ xops[0] = high[0];
+ xops[1] = low[0];
+ xops[2] = high[2];
+ xops[3] = low[2];
+ xops[4] = operands[3];
+
+ emit_insn (gen_movsi (xops[4], xops[3]));
+ emit_insn ((*genfunc) (xops[1], xops[1], xops[4]));
+ emit_insn (gen_movsi (xops[4], xops[2]));
+ emit_insn ((*genfunc) (xops[0], xops[0], xops[4]));
+ }
+
+ else
+ {
+ emit_insn ((*genfunc) (low[0], low[0], low[2]));
+ emit_insn ((*genfunc) (high[0], high[0], high[2]));
+ }
+
+ DONE;
+ }")
+
;;- negation instructions
(define_insn "negdi2"
More information about the Gcc
mailing list