Hi, Along with intrinsics for adcx/adox (supported since 4.8) ICC also added intrinsics for adc/sbb [1]. This patch adds them. Bootstraps/passes make-check. Ok for trunk?
[1] http://www.xlsoft.com/jp/products/intel/compilers/ccm/2013/Release_Notes_u3.pdf ChangeLog below: gcc/ 2014-09-02 Ilya Tocar <ilya.to...@intel.com> * config/i386/adxintrin.h (_subborrow_u32): New. (_addcarry_u32): Ditto. (_subborrow_u64): Ditto. (_addcarry_u64): Ditto. * config/i386/i386.c (ix86_builtins): Add IX86_BUILTIN_SBB32, IX86_BUILTIN_SBB64. (ix86_init_mmx_sse_builtins): Handle __builtin_ia32_sbb_u32, __builtin_ia32_sbb_u64 testsuite/ 2014-09-02 Ilya Tocar <ilya.to...@intel.com> * gcc.target/i386/adx-addcarryx32-1.c: Test addcarry, subborrow. * gcc.target/i386/adx-addcarryx32-2.c: Ditto. * gcc.target/i386/adx-addcarryx32-3.c: Ditto. * gcc.target/i386/adx-addcarryx64-1.c: Ditto. * gcc.target/i386/adx-addcarryx64-2.c: Ditto. * gcc.target/i386/adx-addcarryx64-3.c: Ditto. --- gcc/config/i386/adxintrin.h | 32 +++++++++++++++++++++++ gcc/config/i386/i386.c | 22 ++++++++++++++++ gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c | 5 +++- gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c | 27 +++++++++++++++++++ gcc/testsuite/gcc.target/i386/adx-addcarryx32-3.c | 5 +++- gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c | 5 +++- gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c | 27 +++++++++++++++++++ gcc/testsuite/gcc.target/i386/adx-addcarryx64-3.c | 5 +++- 8 files changed, 124 insertions(+), 4 deletions(-) diff --git a/gcc/config/i386/adxintrin.h b/gcc/config/i386/adxintrin.h index 6118900..8f2c01a 100644 --- a/gcc/config/i386/adxintrin.h +++ b/gcc/config/i386/adxintrin.h @@ -30,6 +30,22 @@ extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_subborrow_u32 (unsigned char __CF, unsigned int __X, + unsigned int __Y, unsigned int *__P) +{ + return __builtin_ia32_sbb_u32 (__CF, __Y, __X, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarry_u32 (unsigned char __CF, unsigned int __X, + unsigned int __Y, unsigned int *__P) +{ + return __builtin_ia32_addcarryx_u32 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) _addcarryx_u32 (unsigned char __CF, unsigned int __X, unsigned int __Y, unsigned int *__P) { @@ -39,6 +55,22 @@ _addcarryx_u32 (unsigned char __CF, unsigned int __X, #ifdef __x86_64__ extern __inline unsigned char __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_subborrow_u64 (unsigned char __CF, unsigned long __X, + unsigned long __Y, unsigned long long *__P) +{ + return __builtin_ia32_sbb_u64 (__CF, __Y, __X, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_addcarry_u64 (unsigned char __CF, unsigned long __X, + unsigned long __Y, unsigned long long *__P) +{ + return __builtin_ia32_addcarryx_u64 (__CF, __X, __Y, __P); +} + +extern __inline unsigned char +__attribute__((__gnu_inline__, __always_inline__, __artificial__)) _addcarryx_u64 (unsigned char __CF, unsigned long __X, unsigned long __Y, unsigned long long *__P) { diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3e4c93e..91b5d06 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -28778,6 +28778,10 @@ enum ix86_builtins IX86_BUILTIN_ADDCARRYX32, IX86_BUILTIN_ADDCARRYX64, + /* ADC/SBB instructions. */ + IX86_BUILTIN_SBB32, + IX86_BUILTIN_SBB64, + /* FSGSBASE instructions. */ IX86_BUILTIN_RDFSBASE32, IX86_BUILTIN_RDFSBASE64, @@ -31213,6 +31217,14 @@ ix86_init_mmx_sse_builtins (void) UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG, IX86_BUILTIN_ADDCARRYX64); + /* ADX/SBB */ + def_builtin (0, "__builtin_ia32_sbb_u32", + UCHAR_FTYPE_UCHAR_UINT_UINT_PUNSIGNED, IX86_BUILTIN_SBB32); + def_builtin (OPTION_MASK_ISA_64BIT, + "__builtin_ia32_sbb_u64", + UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG, + IX86_BUILTIN_SBB64); + /* Read/write FLAGS. */ def_builtin (~OPTION_MASK_ISA_64BIT, "__builtin_ia32_readeflags_u32", UNSIGNED_FTYPE_VOID, IX86_BUILTIN_READ_FLAGS); @@ -35617,6 +35629,16 @@ rdseed_step: emit_insn (gen_zero_extendqisi2 (target, op2)); return target; + case IX86_BUILTIN_SBB32: + icode = CODE_FOR_subsi3_carry; + mode0 = SImode; + goto addcarryx; + + case IX86_BUILTIN_SBB64: + icode = CODE_FOR_subdi3_carry; + mode0 = DImode; + goto addcarryx; + case IX86_BUILTIN_ADDCARRYX32: icode = TARGET_ADX ? CODE_FOR_adcxsi3 : CODE_FOR_addsi3_carry; mode0 = SImode; diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c index daf5779..9fff611 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-madx -O2" } */ -/* { dg-final { scan-assembler "adcx" } } */ +/* { dg-final { scan-assembler-times "adcx" 2 } } */ +/* { dg-final { scan-assembler-times "sbbl" 1 } } */ #include <x86intrin.h> @@ -12,4 +13,6 @@ void extern adx_test (void) { c = _addcarryx_u32 (c, x, y, sum); + c = _addcarry_u32 (c, x, y, sum); + c = _subborrow_u32 (c, x, y, sum); } diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c index d38d7ee..b1da555 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-2.c @@ -24,4 +24,31 @@ adx_test (void) if (x != sum_ref) abort (); + + c = 0; + x = y = 0xFFFFFFFF; + sum_ref = 0xFFFFFFFE; + + /* X = 0xFFFFFFFF, Y = 0xFFFFFFFF, C = 0. */ + c = _addcarry_u32 (c, x, y, &x); + /* X = 0xFFFFFFFE, Y = 0xFFFFFFFF, C = 1. */ + c = _addcarry_u32 (c, x, y, &x); + /* X = 0xFFFFFFFE, Y = 0xFFFFFFFF, C = 1. */ + + if (x != sum_ref) + abort (); + + c = 0; + x = 1; + y = 0; + sum_ref = 0x0; + + /* X = 0x00000001, Y = 0x00000000, C = 0. */ + c = _subborrow_u32 (c, x, y, &x); + /* X = 0xFFFFFFFF, Y = 0x00000000, C = 1. */ + c = _subborrow_u32 (c, x, y, &x); + /* X = 0xFFFFFFFF, Y = 0xFFFFFFFF, C = 1. */ + + if (x != sum_ref) + abort (); } diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-3.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-3.c index 0ed33a9..d804867 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-3.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-3.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-mno-adx -O2" } */ -/* { dg-final { scan-assembler "adcl" } } */ +/* { dg-final { scan-assembler-times "adcl" 2 } } */ +/* { dg-final { scan-assembler-times "sbbl" 1 } } */ #include <x86intrin.h> @@ -12,4 +13,6 @@ void extern adx_test (void) { c = _addcarryx_u32 (c, x, y, sum); + c = _addcarry_u32 (c, x, y, sum); + c = _subborrow_u32 (c, x, y, sum); } diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c index 45beca8..3608dea 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c @@ -1,6 +1,7 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-madx -O2" } */ -/* { dg-final { scan-assembler "adcx" } } */ +/* { dg-final { scan-assembler-times "adcx" 2 } } */ +/* { dg-final { scan-assembler-times "sbbq" 1 } } */ #include <x86intrin.h> @@ -12,4 +13,6 @@ void extern adx_test (void) { c = _addcarryx_u64 (c, x, y, sum); + c = _addcarry_u64 (c, x, y, sum); + c = _subborrow_u64 (c, x, y, sum); } diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c index 6aa2539..b326291 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-2.c @@ -24,4 +24,31 @@ adx_test (void) if (x != sum_ref) abort (); + + c = 0; + x = y = 0xFFFFFFFFFFFFFFFFLL; + sum_ref = 0xFFFFFFFFFFFFFFFELL; + + /* X = 0xFFFFFFFFFFFFFFFF, Y = 0xFFFFFFFFFFFFFFFF, C = 0. */ + c = _addcarry_u64 (c, x, y, &x); + /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ + c = _addcarry_u64 (c, x, y, &x); + /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ + + if (x != sum_ref) + abort (); + + c = 0; + x = 1LL; + y = 0LL; + sum_ref = 0x0LL; + + /* X = 0x0000000000000001, Y = 0x0000000000000000, C = 0. */ + c = _subborrow_u64 (c, x, y, &x); + /* X = 0xFFFFFFFFFFFFFFFF, Y = 0x0000000000000000, C = 1. */ + c = _subborrow_u64 (c, x, y, &x); + /* X = 0x0000000000000000, Y = 0x0000000000000000, C = 1. */ + + if (x != sum_ref) + abort (); } diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-3.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-3.c index 4bbf74b..9d9809d 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-3.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-3.c @@ -1,6 +1,7 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-mno-adx -O2" } */ -/* { dg-final { scan-assembler "adcq" } } */ +/* { dg-final { scan-assembler-times "adcq" 2 } } */ +/* { dg-final { scan-assembler-times "sbbq" 1 } } */ #include <x86intrin.h> @@ -12,4 +13,6 @@ void extern adx_test (void) { c = _addcarryx_u64 (c, x, y, sum); + c = _addcarry_u64 (c, x, y, sum); + c = _subborrow_u64 (c, x, y, sum); } -- 1.8.3.1