r349098 - [Builltins][X86] Provide implementations of __lzcnt16, __lzcnt, __lzcnt64 for MS compatibility. Remove declarations from intrin.h and implementations from lzcntintrin.h

Craig Topper via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 13 16:21:02 PST 2018


Author: ctopper
Date: Thu Dec 13 16:21:02 2018
New Revision: 349098

URL: http://llvm.org/viewvc/llvm-project?rev=349098&view=rev
Log:
[Builltins][X86] Provide implementations of __lzcnt16, __lzcnt, __lzcnt64 for MS compatibility. Remove declarations from intrin.h and implementations from lzcntintrin.h

intrin.h had forward declarations for these and lzcntintrin.h had implementations that were only available with -mlzcnt or a -march that supported the lzcnt feature.

For MS compatibility we should always have these builtins available regardless of X86 being the target or the CPU support the lzcnt instruction. The backends should be able to gracefully fallback to something support even if its just shifts and bit ops.

Unfortunately, gcc also implements 2 of the 3 function names here on X86 when lzcnt feature is enabled.

This patch adds builtins for these for MSVC compatibility and drops the forward declarations from intrin.h. To keep the gcc compatibility the two intrinsics that collided have been turned into macros that use the X86 specific builtins with the lzcnt feature check. These macros are only defined when _MSC_VER is not defined. Without them being macros we can get a redefinition error because -ms-extensions doesn't seem to set _MSC_VER but does make the MS builtins available.

Should fix PR40014

Differential Revision: https://reviews.llvm.org/D55677

Modified:
    cfe/trunk/include/clang/Basic/Builtins.def
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/Headers/intrin.h
    cfe/trunk/lib/Headers/lzcntintrin.h
    cfe/trunk/test/CodeGen/ms-intrinsics-other.c

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=349098&r1=349097&r2=349098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Thu Dec 13 16:21:02 2018
@@ -818,20 +818,23 @@ LANGBUILTIN(_interlockedbittestandset_ac
 LANGBUILTIN(_interlockedbittestandset_nf,    "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_interlockedbittestandset_rel,   "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__noop,           "i.",  "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt16, "UsUs",     "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt,   "UiUi",     "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt16, "UsUs",    "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt,   "UiUi",    "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt64, "UWiUWi",  "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt16, "UsUs",   "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt,   "UiUi",   "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES)
 LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl8,  "UcUcUc",    "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl16, "UsUsUc",    "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl,   "UiUii",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_lrotl,  "UNiUNii",   "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_rotl64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotl64, "UWiUWii",   "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotr8,  "UcUcUc",    "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotr16, "UsUsUc",    "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotr,   "UiUii",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_lrotr,  "UNiUNii",   "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(_rotr64, "ULLiULLii", "n", ALL_MS_LANGUAGES)
+LANGBUILTIN(_rotr64, "UWiUWii",   "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__va_start,       "vc**.", "nt", ALL_MS_LANGUAGES)
 LANGBUILTIN(__fastfail, "vUi",    "nr", ALL_MS_LANGUAGES)
 

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=349098&r1=349097&r2=349098&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Dec 13 16:21:02 2018
@@ -1802,6 +1802,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(
                                      "cast");
     return RValue::get(Result);
   }
+  case Builtin::BI__lzcnt16:
+  case Builtin::BI__lzcnt:
+  case Builtin::BI__lzcnt64: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+    llvm::Type *ArgType = ArgValue->getType();
+    Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+                                     "cast");
+    return RValue::get(Result);
+  }
   case Builtin::BI__popcnt16:
   case Builtin::BI__popcnt:
   case Builtin::BI__popcnt64:

Modified: cfe/trunk/lib/Headers/intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/intrin.h?rev=349098&r1=349097&r2=349098&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/intrin.h (original)
+++ cfe/trunk/lib/Headers/intrin.h Thu Dec 13 16:21:02 2018
@@ -90,8 +90,6 @@ void __inwordstring(unsigned short, unsi
 void __lidt(void *);
 unsigned __int64 __ll_lshift(unsigned __int64, int);
 __int64 __ll_rshift(__int64, int);
-unsigned int __lzcnt(unsigned int);
-unsigned short __lzcnt16(unsigned short);
 static __inline__
 void __movsb(unsigned char *, unsigned char const *, size_t);
 static __inline__
@@ -219,7 +217,6 @@ void __incgsbyte(unsigned long);
 void __incgsdword(unsigned long);
 void __incgsqword(unsigned long);
 void __incgsword(unsigned long);
-unsigned __int64 __lzcnt64(unsigned __int64);
 static __inline__
 void __movsq(unsigned long long *, unsigned long long const *, size_t);
 static __inline__

Modified: cfe/trunk/lib/Headers/lzcntintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/lzcntintrin.h?rev=349098&r1=349097&r2=349098&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/lzcntintrin.h (original)
+++ cfe/trunk/lib/Headers/lzcntintrin.h Thu Dec 13 16:21:02 2018
@@ -31,6 +31,7 @@
 /* Define the default attributes for the functions in this file. */
 #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("lzcnt")))
 
+#ifndef _MSC_VER
 /// Counts the number of leading zero bits in the operand.
 ///
 /// \headerfile <x86intrin.h>
@@ -41,11 +42,8 @@
 ///    An unsigned 16-bit integer whose leading zeros are to be counted.
 /// \returns An unsigned 16-bit integer containing the number of leading zero
 ///    bits in the operand.
-static __inline__ unsigned short __DEFAULT_FN_ATTRS
-__lzcnt16(unsigned short __X)
-{
-  return __builtin_ia32_lzcnt_u16(__X);
-}
+#define __lzcnt16(X) __builtin_ia32_lzcnt_u16((unsigned short)(X))
+#endif // _MSC_VER
 
 /// Counts the number of leading zero bits in the operand.
 ///
@@ -82,6 +80,7 @@ _lzcnt_u32(unsigned int __X)
 }
 
 #ifdef __x86_64__
+#ifndef _MSC_VER
 /// Counts the number of leading zero bits in the operand.
 ///
 /// \headerfile <x86intrin.h>
@@ -93,11 +92,8 @@ _lzcnt_u32(unsigned int __X)
 /// \returns An unsigned 64-bit integer containing the number of leading zero
 ///    bits in the operand.
 /// \see _lzcnt_u64
-static __inline__ unsigned long long __DEFAULT_FN_ATTRS
-__lzcnt64(unsigned long long __X)
-{
-  return __builtin_ia32_lzcnt_u64(__X);
-}
+#define __lzcnt64(X) __builtin_ia32_lzcnt_u64((unsigned long long)(X))
+#endif // _MSC_VER
 
 /// Counts the number of leading zero bits in the operand.
 ///

Modified: cfe/trunk/test/CodeGen/ms-intrinsics-other.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-intrinsics-other.c?rev=349098&r1=349097&r2=349098&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-intrinsics-other.c (original)
+++ cfe/trunk/test/CodeGen/ms-intrinsics-other.c Thu Dec 13 16:21:02 2018
@@ -148,3 +148,51 @@ LONG test_InterlockedDecrement(LONG vola
 // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1
 // CHECK: ret i32 [[RESULT]]
 // CHECK: }
+
+unsigned short test__lzcnt16(unsigned short x) {
+  return __lzcnt16(x);
+}
+// CHECK: i16 @test__lzcnt16
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+unsigned int test__lzcnt(unsigned int x) {
+  return __lzcnt(x);
+}
+// CHECK: i32 @test__lzcnt
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+unsigned __int64 test__lzcnt64(unsigned __int64 x) {
+  return __lzcnt64(x);
+}
+// CHECK: i64 @test__lzcnt64
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
+// CHECK: ret i64 [[RESULT]]
+// CHECK: }
+
+unsigned short test__popcnt16(unsigned short x) {
+  return __popcnt16(x);
+}
+// CHECK: i16 @test__popcnt16
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctpop.i16(i16 %x)
+// CHECK: ret i16 [[RESULT]]
+// CHECK: }
+
+unsigned int test__popcnt(unsigned int x) {
+  return __popcnt(x);
+}
+// CHECK: i32 @test__popcnt
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctpop.i32(i32 %x)
+// CHECK: ret i32 [[RESULT]]
+// CHECK: }
+
+unsigned __int64 test__popcnt64(unsigned __int64 x) {
+  return __popcnt64(x);
+}
+// CHECK: i64 @test__popcnt64
+// CHECK:  [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctpop.i64(i64 %x)
+// CHECK: ret i64 [[RESULT]]
+// CHECK: }




More information about the cfe-commits mailing list