From: Albert Gutowski Date: Tue, 4 Oct 2016 22:29:49 +0000 (+0000) Subject: Separate builtins for x84-64 and i386; implement __mulh and __umulh X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f3a0bce1557f2c070518875122a8eb648f971211;p=platform%2Fupstream%2Fllvm.git Separate builtins for x84-64 and i386; implement __mulh and __umulh Summary: We need x86-64-specific builtins if we want to implement some of the MS intrinsics - winnt.h contains definitions of some functions for i386, but not for x86-64 (for example _InterlockedOr64), which means that we cannot treat them as builtins for both i386 and x86-64, because then we have definitions of builtin functions in winnt.h on i386. Reviewers: thakis, majnemer, hans, rnk Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D24598 llvm-svn: 283264 --- diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def new file mode 100644 index 0000000..d94bedc1 --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -0,0 +1,25 @@ +//===--- BuiltinsX86_64.def - X86-64 Builtin function database --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the X86-64-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN) +# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + +TARGET_HEADER_BUILTIN(__mulh, "LLiLLiLLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "") + +#undef BUILTIN +#undef TARGET_HEADER_BUILTIN diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index 623c0b6..5d45e16 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -85,12 +85,16 @@ namespace clang { /// \brief X86 builtins namespace X86 { - enum { - LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, #define BUILTIN(ID, TYPE, ATTRS) BI##ID, #include "clang/Basic/BuiltinsX86.def" - LastTSBuiltin - }; + FirstX86_64Builtin, + LastX86CommonBuiltin = FirstX86_64Builtin - 1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsX86_64.def" + LastTSBuiltin + }; } /// \brief Flags to identify the types for overloaded Neon builtins. diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index f4710fa..39ac8be 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -2329,19 +2329,23 @@ bool AMDGPUTargetInfo::initFeatureMap( return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec); } -// Namespace for x86 abstract base class -const Builtin::Info BuiltinInfo[] = { +const Builtin::Info BuiltinInfoX86[] = { #define BUILTIN(ID, TYPE, ATTRS) \ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, -#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ - { #ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr }, #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE }, #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE }, #include "clang/Basic/BuiltinsX86.def" + +#define BUILTIN(ID, TYPE, ATTRS) \ + { #ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr }, +#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ + { #ID, TYPE, ATTRS, HEADER, LANGS, FEATURE }, +#include "clang/Basic/BuiltinsX86_64.def" }; + static const char* const GCCRegNames[] = { "ax", "dx", "cx", "bx", "si", "di", "bp", "sp", "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)", @@ -2705,10 +2709,6 @@ public: // X87 evaluates with 80 bits "long double" precision. return SSELevel == NoSSE ? 2 : 0; } - ArrayRef getTargetBuiltins() const override { - return llvm::makeArrayRef(BuiltinInfo, - clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin); - } ArrayRef getGCCRegNames() const override { return llvm::makeArrayRef(GCCRegNames); } @@ -4127,6 +4127,10 @@ public: return X86TargetInfo::validateOperandSize(Constraint, Size); } + ArrayRef getTargetBuiltins() const override { + return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin - + Builtin::FirstTSBuiltin + 1); + } }; class NetBSDI386TargetInfo : public NetBSDTargetInfo { @@ -4482,6 +4486,10 @@ public: return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize, HasSizeMismatch); } + ArrayRef getTargetBuiltins() const override { + return llvm::makeArrayRef(BuiltinInfoX86, + X86::LastTSBuiltin - Builtin::FirstTSBuiltin); + } }; // x86-64 Windows target diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e9248b3..d05e910 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -7575,6 +7575,30 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 6); case X86::BI__builtin_ia32_cmpordsd: return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 7); + + case X86::BI__mulh: + case X86::BI__umulh: { + Value *LHS = EmitScalarExpr(E->getArg(0)); + Value *RHS = EmitScalarExpr(E->getArg(1)); + llvm::Type *ResType = ConvertType(E->getType()); + llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128); + + bool IsSigned = (BuiltinID == X86::BI__mulh); + LHS = Builder.CreateIntCast(LHS, Int128Ty, IsSigned); + RHS = Builder.CreateIntCast(RHS, Int128Ty, IsSigned); + + Value *MulResult, *HigherBits; + if (IsSigned) { + MulResult = Builder.CreateNSWMul(LHS, RHS); + HigherBits = Builder.CreateAShr(MulResult, 64); + } else { + MulResult = Builder.CreateNUWMul(LHS, RHS); + HigherBits = Builder.CreateLShr(MulResult, 64); + } + + HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned); + return HigherBits; + } } } diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index cc635bf..3a45ad9 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -312,6 +312,7 @@ void __lwpval64(unsigned __int64, unsigned int, unsigned int); unsigned __int64 __lzcnt64(unsigned __int64); static __inline__ void __movsq(unsigned long long *, unsigned long long const *, size_t); +static __inline__ __int64 __mulh(__int64, __int64); static __inline__ unsigned __int64 __popcnt64(unsigned __int64); @@ -426,12 +427,8 @@ _umul128(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand, *_HighProduct = _FullProduct >> 64; return _FullProduct; } -static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS -__umulh(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand) { - unsigned __int128 _FullProduct = - (unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand; - return _FullProduct >> 64; -} +static __inline__ +unsigned __int64 __umulh(unsigned __int64, unsigned __int64); #endif /* __x86_64__ */ diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index 8547c63..d3ca33b 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -54,12 +54,17 @@ long test__readfsdword(unsigned long Offset) { #endif #if defined(__x86_64__) +__int64 test__mulh(__int64 a, __int64 b) { + return __mulh(a, b); +} +// CHECK-X64-LABEL: define i64 @test__mulh(i64 %a, i64 %b) +// CHECK-X64: = mul nsw i128 % + unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) { return __umulh(a, b); } // CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b) // CHECK-X64: = mul nuw i128 % - #endif char test_InterlockedExchange8(char volatile *value, char mask) { diff --git a/clang/test/Sema/implicit-ms-builtin-decl.c b/clang/test/Sema/implicit-ms-builtin-decl.c index e43d8f8..9a3e410 100644 --- a/clang/test/Sema/implicit-ms-builtin-decl.c +++ b/clang/test/Sema/implicit-ms-builtin-decl.c @@ -1,9 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -fms-extensions +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s -fms-extensions +// RUN: %clang_cc1 -triple i386-unknown-unknown -fsyntax-only -verify %s -fms-extensions void f() { - (void)_byteswap_ushort(42); // expected-warning{{implicitly declaring library function '_byteswap_ushort}} \ + (void)_byteswap_ushort(42); // expected-warning{{implicitly declaring library function '_byteswap_ushort'}} \ // expected-note{{include the header or explicitly provide a declaration for '_byteswap_ushort'}} - (void)_byteswap_uint64(42LL); // expected-warning{{implicitly declaring library function '_byteswap_uint64}} \ + (void)_byteswap_uint64(42LL); // expected-warning{{implicitly declaring library function '_byteswap_uint64'}} \ // expected-note{{include the header or explicitly provide a declaration for '_byteswap_uint64'}} } @@ -17,3 +18,27 @@ void g() { (void)_byteswap_ushort(42); (void)_byteswap_uint64(42LL); } + +#if defined(__x86_64__) +void h() { + (void)__mulh(21, 2); // expected-warning{{implicitly declaring library function '__mulh'}} \ + // expected-note{{include the header or explicitly provide a declaration for '__mulh'}} + (void)__umulh(21, 2); // expected-warning{{implicitly declaring library function '__umulh'}} \ + // expected-note{{include the header or explicitly provide a declaration for '__umulh'}} +} + +long long __mulh(long long, long long); +unsigned long long __umulh(unsigned long long, unsigned long long); + +void i() { + (void)__mulh(21, 2); + (void)__umulh(21, 2); +} +#endif + +#if defined(i386) +void h() { + (void)__mulh(21LL, 2LL); // expected-warning{{implicit declaration of function '__mulh' is invalid}} + (void)__umulh(21ULL, 2ULL); // expected-warning{{implicit declaration of function '__umulh' is invalid}} +} +#endif