forked from OSchip/llvm-project
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
This commit is contained in:
parent
e7439392f1
commit
f3a0bce155
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -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<Builtin::Info> getTargetBuiltins() const override {
|
||||
return llvm::makeArrayRef(BuiltinInfo,
|
||||
clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin);
|
||||
}
|
||||
ArrayRef<const char *> getGCCRegNames() const override {
|
||||
return llvm::makeArrayRef(GCCRegNames);
|
||||
}
|
||||
|
@ -4127,6 +4127,10 @@ public:
|
|||
|
||||
return X86TargetInfo::validateOperandSize(Constraint, Size);
|
||||
}
|
||||
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
|
||||
return llvm::makeArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin -
|
||||
Builtin::FirstTSBuiltin + 1);
|
||||
}
|
||||
};
|
||||
|
||||
class NetBSDI386TargetInfo : public NetBSDTargetInfo<X86_32TargetInfo> {
|
||||
|
@ -4482,6 +4486,10 @@ public:
|
|||
return X86TargetInfo::validateGlobalRegisterVariable(RegName, RegSize,
|
||||
HasSizeMismatch);
|
||||
}
|
||||
ArrayRef<Builtin::Info> getTargetBuiltins() const override {
|
||||
return llvm::makeArrayRef(BuiltinInfoX86,
|
||||
X86::LastTSBuiltin - Builtin::FirstTSBuiltin);
|
||||
}
|
||||
};
|
||||
|
||||
// x86-64 Windows target
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 <stdlib.h> 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 <stdlib.h> 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 <intrin.h> or explicitly provide a declaration for '__mulh'}}
|
||||
(void)__umulh(21, 2); // expected-warning{{implicitly declaring library function '__umulh'}} \
|
||||
// expected-note{{include the header <intrin.h> 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
|
||||
|
|
Loading…
Reference in New Issue