From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bernd Schmidt To: egcs@cygnus.com Subject: DImode speedup on i386 Date: Wed, 18 Feb 1998 04:16:00 -0000 Message-id: X-SW-Source: 1998-02/msg00870.html 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"