xref: /llvm-project/clang/test/CodeGen/X86/adc-builtins.c (revision c7fb0eed05e768093fc202e94df1c0d88fd7c2f0)
1 // RUN: %clang_cc1 -x c -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
2 // RUN: %clang_cc1 -x c++ -ffreestanding -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
3 
4 #include <x86intrin.h>
5 
6 unsigned char test_addcarry_u32(unsigned char __cf, unsigned int __x,
7                                 unsigned int __y, unsigned int *__p) {
8 // CHECK-LABEL: test_addcarry_u32
9 // CHECK: [[ADC:%.*]] = call { i8, i32 } @llvm.x86.addcarry.32
10 // CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[ADC]], 1
11 // CHECK: store i32 [[DATA]], ptr %{{.*}}
12 // CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[ADC]], 0
13   return _addcarry_u32(__cf, __x, __y, __p);
14 }
15 
16 unsigned char test_addcarry_u64(unsigned char __cf, unsigned long long __x,
17                                 unsigned long long __y,
18                                 unsigned long long *__p) {
19 // CHECK-LABEL: test_addcarry_u64
20 // CHECK: [[ADC:%.*]] = call { i8, i64 } @llvm.x86.addcarry.64
21 // CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[ADC]], 1
22 // CHECK: store i64 [[DATA]], ptr %{{.*}}
23 // CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[ADC]], 0
24   return _addcarry_u64(__cf, __x, __y, __p);
25 }
26 
27 unsigned char test_subborrow_u32(unsigned char __cf, unsigned int __x,
28                                  unsigned int __y, unsigned int *__p) {
29 // CHECK-LABEL: test_subborrow_u32
30 // CHECK: [[SBB:%.*]] = call { i8, i32 } @llvm.x86.subborrow.32
31 // CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[SBB]], 1
32 // CHECK: store i32 [[DATA]], ptr %{{.*}}
33 // CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[SBB]], 0
34   return _subborrow_u32(__cf, __x, __y, __p);
35 }
36 
37 unsigned char test_subborrow_u64(unsigned char __cf, unsigned long long __x,
38                                  unsigned long long __y,
39                                  unsigned long long *__p) {
40 // CHECK-LABEL: test_subborrow_u64
41 // CHECK: [[SBB:%.*]] = call { i8, i64 } @llvm.x86.subborrow.64
42 // CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[SBB]], 1
43 // CHECK: store i64 [[DATA]], ptr %{{.*}}
44 // CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[SBB]], 0
45   return _subborrow_u64(__cf, __x, __y, __p);
46 }
47 
48 // Test constexpr handling.
49 #if defined(__cplusplus) && (__cplusplus >= 201103L)
50 
51 template<typename X>
52 struct Result {
53   unsigned char A;
54   X B;
55   constexpr bool operator==(const Result<X> &Other) {
56     return A == Other.A && B == Other.B;
57   }
58 };
59 
60 constexpr Result<unsigned int>
61 const_test_addcarry_u32(unsigned char __cf, unsigned int __x, unsigned int __y)
62 {
63   unsigned int __r{};
64   return { _addcarry_u32(__cf, __x, __y, &__r), __r };
65 }
66 
67 void constexpr adcu32() {
68   static_assert(const_test_addcarry_u32(0, 0x00000000, 0x00000000) == Result<unsigned int>{0, 0x00000000});
69   static_assert(const_test_addcarry_u32(1, 0xFFFFFFFE, 0x00000000) == Result<unsigned int>{0, 0xFFFFFFFF});
70   static_assert(const_test_addcarry_u32(1, 0xFFFFFFFE, 0x00000001) == Result<unsigned int>{1, 0x00000000});
71   static_assert(const_test_addcarry_u32(0, 0xFFFFFFFF, 0xFFFFFFFF) == Result<unsigned int>{1, 0xFFFFFFFE});
72   static_assert(const_test_addcarry_u32(1, 0xFFFFFFFF, 0xFFFFFFFF) == Result<unsigned int>{1, 0xFFFFFFFF});
73 }
74 
75 constexpr Result<unsigned int>
76 const_test_subborrow_u32(unsigned char __cf, unsigned int __x, unsigned int __y)
77 {
78   unsigned int __r{};
79   return { _subborrow_u32(__cf, __x, __y, &__r), __r };
80 }
81 
82 void constexpr sbbu32() {
83   static_assert(const_test_subborrow_u32(0, 0x00000000, 0x00000000) == Result<unsigned int>{0, 0x00000000});
84   static_assert(const_test_subborrow_u32(0, 0x00000000, 0x00000001) == Result<unsigned int>{1, 0xFFFFFFFF});
85   static_assert(const_test_subborrow_u32(1, 0x00000000, 0x00000001) == Result<unsigned int>{1, 0xFFFFFFFE});
86   static_assert(const_test_subborrow_u32(1, 0xFFFFFFFE, 0x00000000) == Result<unsigned int>{0, 0xFFFFFFFD});
87   static_assert(const_test_subborrow_u32(1, 0xFFFFFFFE, 0x00000001) == Result<unsigned int>{0, 0xFFFFFFFC});
88   static_assert(const_test_subborrow_u32(0, 0xFFFFFFFF, 0xFFFFFFFF) == Result<unsigned int>{0, 0x00000000});
89   static_assert(const_test_subborrow_u32(1, 0xFFFFFFFF, 0xFFFFFFFF) == Result<unsigned int>{1, 0xFFFFFFFF});
90 }
91 
92 constexpr Result<unsigned long long>
93 const_test_addcarry_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y)
94 {
95   unsigned long long __r{};
96   return { _addcarry_u64(__cf, __x, __y, &__r), __r };
97 }
98 
99 void constexpr adcu64() {
100   static_assert(const_test_addcarry_u64(0, 0x0000000000000000ULL, 0x0000000000000000ULL) == Result<unsigned long long>{0, 0x0000000000000000ULL});
101   static_assert(const_test_addcarry_u64(1, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000000ULL) == Result<unsigned long long>{0, 0xFFFFFFFFFFFFFFFFULL});
102   static_assert(const_test_addcarry_u64(1, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000001ULL) == Result<unsigned long long>{1, 0x0000000000000000ULL});
103   static_assert(const_test_addcarry_u64(0, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == Result<unsigned long long>{1, 0xFFFFFFFFFFFFFFFEULL});
104   static_assert(const_test_addcarry_u64(1, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == Result<unsigned long long>{1, 0xFFFFFFFFFFFFFFFFULL});
105 }
106 
107 constexpr Result<unsigned long long>
108 const_test_subborrow_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y)
109 {
110   unsigned long long __r{};
111   return { _subborrow_u64(__cf, __x, __y, &__r), __r };
112 }
113 
114 void constexpr sbbu64() {
115   static_assert(const_test_subborrow_u64(0, 0x0000000000000000ULL, 0x0000000000000000ULL) == Result<unsigned long long>{0, 0x0000000000000000ULL});
116   static_assert(const_test_subborrow_u64(0, 0x0000000000000000ULL, 0x0000000000000001ULL) == Result<unsigned long long>{1, 0xFFFFFFFFFFFFFFFFULL});
117   static_assert(const_test_subborrow_u64(1, 0x0000000000000000ULL, 0x0000000000000001ULL) == Result<unsigned long long>{1, 0xFFFFFFFFFFFFFFFEULL});
118   static_assert(const_test_subborrow_u64(1, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000000ULL) == Result<unsigned long long>{0, 0xFFFFFFFFFFFFFFFDULL});
119   static_assert(const_test_subborrow_u64(1, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000001ULL) == Result<unsigned long long>{0, 0xFFFFFFFFFFFFFFFCULL});
120   static_assert(const_test_subborrow_u64(0, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == Result<unsigned long long>{0, 0x0000000000000000ULL});
121   static_assert(const_test_subborrow_u64(1, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL) == Result<unsigned long long>{1, 0xFFFFFFFFFFFFFFFFULL});
122 }
123 
124 #endif