Hi! As the testcase below shows, we generate awful code for double word additions/subtractions if the last argument is a constant that has the whole low word 0 (and only nonzero some of the upper bits). In that case, there is no point doing useless addl $0, ... followed by adcl $something, ... because the addition won't change anything and the carry flag will be also clear; we can just add the high word to the high part.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-04-01 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/70467 * config/i386/i386.md (*add<dwi>3_doubleword, *sub<dwi>3_doubleword): If low word of the last operand is 0, just emit addition/subtraction for the high word. * gcc.target/i386/pr70467-2.c: New test. --- gcc/config/i386/i386.md.jj 2016-03-29 19:31:23.000000000 +0200 +++ gcc/config/i386/i386.md 2016-03-31 17:33:36.848167239 +0200 @@ -5449,7 +5449,14 @@ (define_insn_and_split "*add<dwi>3_doubl (match_dup 4)) (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] - "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") +{ + split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]); + if (operands[2] == const0_rtx) + { + ix86_expand_binary_operator (PLUS, <MODE>mode, &operands[3]); + DONE; + } +}) (define_insn "*add<mode>_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") @@ -6379,7 +6386,14 @@ (define_insn_and_split "*sub<dwi>3_doubl (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] - "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") +{ + split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]); + if (operands[2] == const0_rtx) + { + ix86_expand_binary_operator (MINUS, <MODE>mode, &operands[3]); + DONE; + } +}) (define_insn "*sub<mode>_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") --- gcc/testsuite/gcc.target/i386/pr70467-2.c.jj 2016-04-01 12:29:15.611785157 +0200 +++ gcc/testsuite/gcc.target/i386/pr70467-2.c 2016-04-01 12:31:19.980092446 +0200 @@ -0,0 +1,20 @@ +/* PR rtl-optimization/70467 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +unsigned long long +foo (unsigned long long x) +{ + return x + 0x12345600000000ULL; +} + +unsigned long long +bar (unsigned long long x) +{ + return x - 0x12345600000000ULL; +} + +/* { dg-final { scan-assembler-not "addl\[ \t\]*.0," { target ia32 } } } */ +/* { dg-final { scan-assembler-not "subl\[ \t\]*.0," { target ia32 } } } */ +/* { dg-final { scan-assembler-not "adcl\[^\n\r\]*%" { target ia32 } } } */ +/* { dg-final { scan-assembler-not "sbbl\[^\n\r\]*%" { target ia32 } } } */ Jakub