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