From ee76e7215d27c25bb053b71ae0a59119c08ccef9 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Tue, 18 Jun 2013 20:40:40 +0000 Subject: [PATCH] [multiprecision-builtins] Added missing builtin __builtin_{add,sub}cb for {add,sub} with carry for bytes. I have had several people ask me about why this builtin was not available in clang (since it seems like a logical conclusion). This patch implements said builtins. Relevant tests are included as well. I also updated the Clang language extension reference. rdar://14192664. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184227 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LanguageExtensions.rst | 2 ++ include/clang/Basic/Builtins.def | 2 ++ lib/CodeGen/CGBuiltin.cpp | 4 +++ test/CodeGen/builtins-multiprecision.c | 38 ++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index d7e88dfda9..af9b61a704 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -1555,10 +1555,12 @@ The complete list of builtins are: .. code-block:: c + unsigned char __builtin_addcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout); unsigned short __builtin_addcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout); unsigned __builtin_addc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout); unsigned long __builtin_addcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout); unsigned long long __builtin_addcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout); + unsigned char __builtin_subcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout); unsigned short __builtin_subcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout); unsigned __builtin_subc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout); unsigned long __builtin_subcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout); diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3dd25b4ebf..0da551f1e8 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -928,10 +928,12 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) BUILTIN(__builtin_annotation, "v.", "tn") // Multiprecision Arithmetic Builtins. +BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n") BUILTIN(__builtin_addc, "UiUiCUiCUiCUi*", "n") BUILTIN(__builtin_addcl, "ULiULiCULiCULiCULi*", "n") BUILTIN(__builtin_addcll, "ULLiULLiCULLiCULLiCULLi*", "n") +BUILTIN(__builtin_subcb, "UcUcCUcCUcCUc*", "n") BUILTIN(__builtin_subcs, "UsUsCUsCUsCUs*", "n") BUILTIN(__builtin_subc, "UiUiCUiCUiCUi*", "n") BUILTIN(__builtin_subcl, "ULiULiCULiCULiCULi*", "n") diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index bd5afb6d17..90b8ebc48c 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -1345,10 +1345,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, StringRef Str = cast(AnnotationStrExpr)->getString(); return RValue::get(EmitAnnotationCall(F, AnnVal, Str, E->getExprLoc())); } + case Builtin::BI__builtin_addcb: case Builtin::BI__builtin_addcs: case Builtin::BI__builtin_addc: case Builtin::BI__builtin_addcl: case Builtin::BI__builtin_addcll: + case Builtin::BI__builtin_subcb: case Builtin::BI__builtin_subcs: case Builtin::BI__builtin_subc: case Builtin::BI__builtin_subcl: @@ -1382,12 +1384,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::Intrinsic::ID IntrinsicId; switch (BuiltinID) { default: llvm_unreachable("Unknown multiprecision builtin id."); + case Builtin::BI__builtin_addcb: case Builtin::BI__builtin_addcs: case Builtin::BI__builtin_addc: case Builtin::BI__builtin_addcl: case Builtin::BI__builtin_addcll: IntrinsicId = llvm::Intrinsic::uadd_with_overflow; break; + case Builtin::BI__builtin_subcb: case Builtin::BI__builtin_subcs: case Builtin::BI__builtin_subc: case Builtin::BI__builtin_subcl: diff --git a/test/CodeGen/builtins-multiprecision.c b/test/CodeGen/builtins-multiprecision.c index 172f683de3..4d196088d3 100644 --- a/test/CodeGen/builtins-multiprecision.c +++ b/test/CodeGen/builtins-multiprecision.c @@ -2,6 +2,25 @@ // RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - -O3 | FileCheck %s // RUN: %clang_cc1 -triple "x86_64-mingw32" -emit-llvm -x c %s -o - -O3 | FileCheck %s +unsigned char test_addcb(unsigned char x, unsigned char y, + unsigned char carryin, unsigned char *z) { + // CHECK: @test_addcb + // CHECK: %{{.+}} = {{.*}} call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %x, i8 %y) + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %{{.+}}, i8 %carryin) + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i8 + // CHECK: store i8 %{{.+}}, i8* %z, align 1 + + unsigned char carryout; + *z = __builtin_addcb(x, y, carryin, &carryout); + + return carryout; +} + unsigned short test_addcs(unsigned short x, unsigned short y, unsigned short carryin, unsigned short *z) { // CHECK: @test_addcs @@ -76,6 +95,25 @@ unsigned long long test_addcll(unsigned long long x, unsigned long long y, return carryout; } +unsigned char test_subcb(unsigned char x, unsigned char y, + unsigned char carryin, unsigned char *z) { + // CHECK: @test_subcb + // CHECK: %{{.+}} = {{.*}} call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y) + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = {{.*}} call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %{{.+}}, i8 %carryin) + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 1 + // CHECK: %{{.+}} = extractvalue { i8, i1 } %{{.+}}, 0 + // CHECK: %{{.+}} = or i1 %{{.+}}, %{{.+}} + // CHECK: %{{.+}} = zext i1 %{{.+}} to i8 + // CHECK: store i8 %{{.+}}, i8* %z, align 1 + + unsigned char carryout; + *z = __builtin_subcb(x, y, carryin, &carryout); + + return carryout; +} + unsigned short test_subcs(unsigned short x, unsigned short y, unsigned short carryin, unsigned short *z) { // CHECK: @test_subcs -- 2.40.0