diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 789f01cc8229..a472bf59d717 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -10405,6 +10405,41 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Ops[0]); return Builder.CreateExtractValue(Call, 1); } + case X86::BI__builtin_ia32_addcarryx_u32: + case X86::BI__builtin_ia32_addcarryx_u64: + case X86::BI__builtin_ia32_addcarry_u32: + case X86::BI__builtin_ia32_addcarry_u64: + case X86::BI__builtin_ia32_subborrow_u32: + case X86::BI__builtin_ia32_subborrow_u64: { + Intrinsic::ID IID; + switch (BuiltinID) { + default: llvm_unreachable("Unsupported intrinsic!"); + case X86::BI__builtin_ia32_addcarryx_u32: + IID = Intrinsic::x86_addcarryx_u32; + break; + case X86::BI__builtin_ia32_addcarryx_u64: + IID = Intrinsic::x86_addcarryx_u64; + break; + case X86::BI__builtin_ia32_addcarry_u32: + IID = Intrinsic::x86_addcarry_u32; + break; + case X86::BI__builtin_ia32_addcarry_u64: + IID = Intrinsic::x86_addcarry_u64; + break; + case X86::BI__builtin_ia32_subborrow_u32: + IID = Intrinsic::x86_subborrow_u32; + break; + case X86::BI__builtin_ia32_subborrow_u64: + IID = Intrinsic::x86_subborrow_u64; + break; + } + + Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), + { Ops[0], Ops[1], Ops[2] }); + Builder.CreateDefaultAlignedStore(Builder.CreateExtractValue(Call, 1), + Ops[3]); + return Builder.CreateExtractValue(Call, 0); + } case X86::BI__builtin_ia32_fpclassps128_mask: case X86::BI__builtin_ia32_fpclassps256_mask: diff --git a/clang/test/CodeGen/adc-builtins.c b/clang/test/CodeGen/adc-builtins.c index d41fa8f446e6..feb6671742dd 100644 --- a/clang/test/CodeGen/adc-builtins.c +++ b/clang/test/CodeGen/adc-builtins.c @@ -5,7 +5,10 @@ unsigned char test_addcarry_u32(unsigned char __cf, unsigned int __x, unsigned int __y, unsigned int *__p) { // CHECK-LABEL: test_addcarry_u32 -// CHECK: call i8 @llvm.x86.addcarry.u32 +// CHECK: [[ADC:%.*]] = call { i8, i32 } @llvm.x86.addcarry.u32 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[ADC]], 1 +// CHECK: store i32 [[DATA]], i32* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[ADC]], 0 return _addcarry_u32(__cf, __x, __y, __p); } @@ -13,14 +16,20 @@ unsigned char test_addcarry_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y, unsigned long long *__p) { // CHECK-LABEL: test_addcarry_u64 -// CHECK: call i8 @llvm.x86.addcarry.u64 +// CHECK: [[ADC:%.*]] = call { i8, i64 } @llvm.x86.addcarry.u64 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[ADC]], 1 +// CHECK: store i64 [[DATA]], i64* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[ADC]], 0 return _addcarry_u64(__cf, __x, __y, __p); } unsigned char test_subborrow_u32(unsigned char __cf, unsigned int __x, unsigned int __y, unsigned int *__p) { // CHECK-LABEL: test_subborrow_u32 -// CHECK: call i8 @llvm.x86.subborrow.u32 +// CHECK: [[SBB:%.*]] = call { i8, i32 } @llvm.x86.subborrow.u32 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[SBB]], 1 +// CHECK: store i32 [[DATA]], i32* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[SBB]], 0 return _subborrow_u32(__cf, __x, __y, __p); } @@ -28,6 +37,9 @@ unsigned char test_subborrow_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y, unsigned long long *__p) { // CHECK-LABEL: test_subborrow_u64 -// CHECK: call i8 @llvm.x86.subborrow.u64 +// CHECK: [[SBB:%.*]] = call { i8, i64 } @llvm.x86.subborrow.u64 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[SBB]], 1 +// CHECK: store i64 [[DATA]], i64* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[SBB]], 0 return _subborrow_u64(__cf, __x, __y, __p); } diff --git a/clang/test/CodeGen/adx-builtins.c b/clang/test/CodeGen/adx-builtins.c index ac33367d0ebd..8fd95c005b9a 100644 --- a/clang/test/CodeGen/adx-builtins.c +++ b/clang/test/CodeGen/adx-builtins.c @@ -5,7 +5,10 @@ unsigned char test_addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y, unsigned int *__p) { // CHECK-LABEL: test_addcarryx_u32 -// CHECK: call i8 @llvm.x86.addcarryx.u32 +// CHECK: [[ADC:%.*]] = call { i8, i32 } @llvm.x86.addcarryx.u32 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i32 } [[ADC]], 1 +// CHECK: store i32 [[DATA]], i32* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i32 } [[ADC]], 0 return _addcarryx_u32(__cf, __x, __y, __p); } @@ -13,6 +16,9 @@ unsigned char test_addcarryx_u64(unsigned char __cf, unsigned long long __x, unsigned long long __y, unsigned long long *__p) { // CHECK-LABEL: test_addcarryx_u64 -// CHECK: call i8 @llvm.x86.addcarryx.u64 +// CHECK: [[ADC:%.*]] = call { i8, i64 } @llvm.x86.addcarryx.u64 +// CHECK: [[DATA:%.*]] = extractvalue { i8, i64 } [[ADC]], 1 +// CHECK: store i64 [[DATA]], i64* %{{.*}} +// CHECK: [[CF:%.*]] = extractvalue { i8, i64 } [[ADC]], 0 return _addcarryx_u64(__cf, __x, __y, __p); }