summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/BuiltinsX86_64.def25
-rw-r--r--clang/include/clang/Basic/TargetBuiltins.h12
-rw-r--r--clang/lib/Basic/Targets.cpp24
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp24
-rw-r--r--clang/lib/Headers/intrin.h9
-rw-r--r--clang/test/CodeGen/ms-intrinsics.c7
-rw-r--r--clang/test/Sema/implicit-ms-builtin-decl.c31
7 files changed, 110 insertions, 22 deletions
diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def
new file mode 100644
index 00000000000..d94bedc1984
--- /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 623c0b64dbf..5d45e162d9f 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 f4710fa5493..39ac8be445d 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<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
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e9248b35cd6..d05e910f244 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 cc635bf2134..3a45ad91221 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 8547c63142b..d3ca33b6ecc 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 e43d8f867d8..9a3e410c47d 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 <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
OpenPOWER on IntegriCloud