Conditional addition for i386
Jan Hubicka
jh@suse.cz
Tue Jan 7 20:44:00 GMT 2003
> > On Wed, Nov 27, 2002 at 01:26:58PM +0100, Jan Hubicka wrote:
> > > http://gcc.gnu.org/ml/gcc-patches/2002-10/msg01819.html
> > > (PR target/8213)
> >
> > Ok.
> >
> > > http://gcc.gnu.org/ml/gcc-patches/2002-10/msg00166.html
> > > (PR 7782)
> >
> > Ok.
> >
> > > http://gcc.gnu.org/ml/gcc-patches/2002-10/msg01831.html
> > > (SSE fix 33 - PR target/8322 II)
> >
> > Ok.
> >
> > > http://gcc.gnu.org/ml/gcc-patches/2002-11/msg01333.html
> > > (Add conditional addition patterns)
> >
> > Ok.
> Thanks a lot!
> I did have code to use this in i386.c. Did I sent this one?
Probably I didn't but found it on the disc :)
Hi,
this patch adds conditional increment/decrement support for i386.
The speed of the attached testcase is improved about 4 times.
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -march=athlon" } */
/* { dg-final { scan-assembler "sbb" } } */
/* Conditional increment is best done using sbb $-1, val. */
int t[]={0,0,0,0,1,1,1,1,1,1};
q()
{
int sum=0;
int i;
for (i=0;i<10;i++)
if (t[i])
sum++;
if (sum != 6)
abort ();
}
main()
{
int i;
for (i=0;i<10000000;i++)
q();
}
Honza
Fri Nov 22 01:36:03 CET 2002 Jan Hubicka <jh@suse.cz>
* i386.md (adddi3_carry_rex64, subdi3_carry_rex64): Name pattern.
(addhi3_carry, addqi3_carry, subhi3_carry, subqi3_carry): New patterns.
*** i386.md.old Thu Nov 21 23:10:32 2002
--- i386.md Fri Nov 22 01:04:57 2002
***************
*** 5035,5041 ****
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
! (define_insn "*adddi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
--- 5035,5041 ----
split_di (operands+1, 1, operands+1, operands+4);
split_di (operands+2, 1, operands+2, operands+5);")
! (define_insn "adddi3_carry_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
(plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
(match_operand:DI 1 "nonimmediate_operand" "%0,0"))
***************
*** 5060,5066 ****
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
! (define_insn "*addsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
--- 5060,5092 ----
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
! (define_insn "addqi3_carry"
! [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
! (plus:QI (plus:QI (ltu:QI (reg:CC 17) (const_int 0))
! (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
! (match_operand:QI 2 "general_operand" "ri,rm")))
! (clobber (reg:CC 17))]
! "ix86_binary_operator_ok (PLUS, QImode, operands)"
! "adc{b}\t{%2, %0|%0, %2}"
! [(set_attr "type" "alu")
! (set_attr "pent_pair" "pu")
! (set_attr "mode" "QI")
! (set_attr "ppro_uops" "few")])
!
! (define_insn "addhi3_carry"
! [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
! (plus:HI (plus:HI (ltu:HI (reg:CC 17) (const_int 0))
! (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
! (match_operand:HI 2 "general_operand" "ri,rm")))
! (clobber (reg:CC 17))]
! "ix86_binary_operator_ok (PLUS, HImode, operands)"
! "adc{w}\t{%2, %0|%0, %2}"
! [(set_attr "type" "alu")
! (set_attr "pent_pair" "pu")
! (set_attr "mode" "HI")
! (set_attr "ppro_uops" "few")])
!
! (define_insn "addsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
(plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
(match_operand:SI 1 "nonimmediate_operand" "%0,0"))
***************
*** 6737,6742 ****
--- 6763,6793 ----
[(set_attr "type" "alu")
(set_attr "mode" "DI")])
+ (define_insn "subqi3_carry"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
+ (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
+ (plus:QI (ltu:QI (reg:CC 17) (const_int 0))
+ (match_operand:QI 2 "general_operand" "ri,rm"))))
+ (clobber (reg:CC 17))]
+ "ix86_binary_operator_ok (MINUS, QImode, operands)"
+ "sbb{q}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "pent_pair" "pu")
+ (set_attr "ppro_uops" "few")
+ (set_attr "mode" "QI")])
+
+ (define_insn "subhi3_carry"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
+ (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
+ (plus:HI (ltu:HI (reg:CC 17) (const_int 0))
+ (match_operand:HI 2 "general_operand" "ri,rm"))))
+ (clobber (reg:CC 17))]
+ "ix86_binary_operator_ok (MINUS, HImode, operands)"
+ "sbb{w}\t{%2, %0|%0, %2}"
+ [(set_attr "type" "alu")
+ (set_attr "pent_pair" "pu")
+ (set_attr "ppro_uops" "few")
+ (set_attr "mode" "HI")])
(define_insn "subsi3_carry"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
*** i386.c.old Thu Nov 21 23:10:28 2002
--- i386.c Fri Nov 22 01:19:02 2002
*************** ix86_expand_fp_movcc (operands)
*** 9820,9825 ****
--- 9890,9958 ----
return 1;
}
+ /* Expand conditional increment or decrement using adb/sbb instructions.
+ The default case using setcc followed by the conditional move can be
+ done by generic code. */
+ int
+ ix86_expand_int_addcc (operands)
+ rtx operands[];
+ {
+ enum rtx_code code = GET_CODE (operands[1]);
+ rtx compare_op;
+ rtx val = const0_rtx;
+
+ if (operands[3] != const1_rtx
+ && operands[3] != constm1_rtx)
+ return 0;
+ if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0,
+ ix86_compare_op1, &compare_op))
+ return 0;
+ if (GET_CODE (compare_op) != LTU)
+ val = constm1_rtx;
+ if ((GET_CODE (compare_op) == LTU) == (operands[1] == const1_rtx))
+ {
+ switch (GET_MODE (operands[0]))
+ {
+ case QImode:
+ emit_insn (gen_subqi3_carry (operands[0], operands[2], val));
+ break;
+ case HImode:
+ emit_insn (gen_subhi3_carry (operands[0], operands[2], val));
+ break;
+ case SImode:
+ emit_insn (gen_subsi3_carry (operands[0], operands[2], val));
+ break;
+ case DImode:
+ emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val));
+ break;
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ switch (GET_MODE (operands[0]))
+ {
+ case QImode:
+ emit_insn (gen_addqi3_carry (operands[0], operands[2], val));
+ break;
+ case HImode:
+ emit_insn (gen_addhi3_carry (operands[0], operands[2], val));
+ break;
+ case SImode:
+ emit_insn (gen_addsi3_carry (operands[0], operands[2], val));
+ break;
+ case DImode:
+ emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val));
+ break;
+ default:
+ abort ();
+ }
+ }
+ return 1; /* DONE */
+ }
+
+
/* Split operands 0 and 1 into SImode parts. Similar to split_di, but
works for floating pointer parameters and nonoffsetable memories.
For pushes, it returns just stack offsets; the values will be saved
*** i386-protos.h.old Fri Nov 22 01:06:09 2002
--- i386-protos.h Fri Nov 22 01:06:19 2002
*************** extern void ix86_expand_branch PARAMS ((
*** 138,143 ****
--- 138,144 ----
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
+ extern int ix86_expand_int_addcc PARAMS ((rtx[]));
extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx, int));
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
More information about the Gcc-patches
mailing list