craig.topper created this revision.
craig.topper added a reviewer: rnk.

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. But the 32-bit version was misnamed in lzcntrin.h

This patch provides an independent implementation for MS that doesn't rely on 
the X86 feature flag.

Fixes PR40014


https://reviews.llvm.org/D55677

Files:
  include/clang/Basic/Builtins.def
  lib/CodeGen/CGBuiltin.cpp
  lib/Headers/intrin.h
  lib/Headers/lzcntintrin.h
  test/CodeGen/lzcnt-builtins.c
  test/CodeGen/ms-intrinsics-other.c
  test/Headers/x86intrin-2.c

Index: test/Headers/x86intrin-2.c
===================================================================
--- test/Headers/x86intrin-2.c
+++ test/Headers/x86intrin-2.c
@@ -56,10 +56,6 @@
   return _bzhi_u32(x, y);
 }
 
-unsigned short __attribute__((__target__("lzcnt"))) lzcnt16_wrap(unsigned short x) {
-  return __lzcnt16(x);
-}
-
 __m256d __attribute__((__target__("fma"))) mm256_fmsubadd_pd_wrap(__m256d a, __m256d b, __m256d c) {
   return _mm256_fmsubadd_pd(a, b, c);
 }
Index: test/CodeGen/ms-intrinsics-other.c
===================================================================
--- test/CodeGen/ms-intrinsics-other.c
+++ test/CodeGen/ms-intrinsics-other.c
@@ -148,3 +148,51 @@
 // 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: }
Index: test/CodeGen/lzcnt-builtins.c
===================================================================
--- test/CodeGen/lzcnt-builtins.c
+++ test/CodeGen/lzcnt-builtins.c
@@ -3,24 +3,6 @@
 
 #include <immintrin.h>
 
-unsigned short test__lzcnt16(unsigned short __X)
-{
-  // CHECK: @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
-  return __lzcnt16(__X);
-}
-
-unsigned int test_lzcnt32(unsigned int __X)
-{
-  // CHECK: @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
-  return __lzcnt32(__X);
-}
-
-unsigned long long test__lzcnt64(unsigned long long __X)
-{
-  // CHECK: @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
-  return __lzcnt64(__X);
-}
-
 unsigned int test_lzcnt_u32(unsigned int __X)
 {
   // CHECK: @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
Index: lib/Headers/lzcntintrin.h
===================================================================
--- lib/Headers/lzcntintrin.h
+++ lib/Headers/lzcntintrin.h
@@ -38,39 +38,6 @@
 /// This intrinsic corresponds to the \c LZCNT instruction.
 ///
 /// \param __X
-///    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);
-}
-
-/// Counts the number of leading zero bits in the operand.
-///
-/// \headerfile <x86intrin.h>
-///
-/// This intrinsic corresponds to the \c LZCNT instruction.
-///
-/// \param __X
-///    An unsigned 32-bit integer whose leading zeros are to be counted.
-/// \returns An unsigned 32-bit integer containing the number of leading zero
-///    bits in the operand.
-/// \see _lzcnt_u32
-static __inline__ unsigned int __DEFAULT_FN_ATTRS
-__lzcnt32(unsigned int __X)
-{
-  return __builtin_ia32_lzcnt_u32(__X);
-}
-
-/// Counts the number of leading zero bits in the operand.
-///
-/// \headerfile <x86intrin.h>
-///
-/// This intrinsic corresponds to the \c LZCNT instruction.
-///
-/// \param __X
 ///    An unsigned 32-bit integer whose leading zeros are to be counted.
 /// \returns An unsigned 32-bit integer containing the number of leading zero
 ///    bits in the operand.
@@ -92,23 +59,6 @@
 ///    An unsigned 64-bit integer whose leading zeros are to be counted.
 /// \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);
-}
-
-/// Counts the number of leading zero bits in the operand.
-///
-/// \headerfile <x86intrin.h>
-///
-/// This intrinsic corresponds to the \c LZCNT instruction.
-///
-/// \param __X
-///    An unsigned 64-bit integer whose leading zeros are to be counted.
-/// \returns An unsigned 64-bit integer containing the number of leading zero
-///    bits in the operand.
 /// \see __lzcnt64
 static __inline__ unsigned long long __DEFAULT_FN_ATTRS
 _lzcnt_u64(unsigned long long __X)
Index: lib/Headers/intrin.h
===================================================================
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -90,8 +90,6 @@
 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 __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__
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -1802,6 +1802,21 @@
                                      "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:
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -818,20 +818,23 @@
 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)
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to