r356848 - [X86] Add BSR/BSF/BSWAP intrinsics to ia32intrin.h to match gcc.

Craig Topper via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 23 17:56:52 PDT 2019


Author: ctopper
Date: Sat Mar 23 17:56:52 2019
New Revision: 356848

URL: http://llvm.org/viewvc/llvm-project?rev=356848&view=rev
Log:
[X86] Add BSR/BSF/BSWAP intrinsics to ia32intrin.h to match gcc.

Summary:
These are all implemented by icc as well.

I made bit_scan_forward/reverse forward to the __bsfd/__bsrq since we also have
__bsfq/__bsrq.

Note, when lzcnt is enabled the bsr intrinsics generates lzcnt+xor instead of bsr.

Reviewers: RKSimon, spatel

Subscribers: cfe-commits, llvm-commits

Tags: #clang

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

Added:
    cfe/trunk/test/CodeGen/x86-bswap.c
Modified:
    cfe/trunk/lib/Headers/ia32intrin.h
    cfe/trunk/lib/Headers/immintrin.h
    cfe/trunk/test/CodeGen/bitscan-builtins.c

Modified: cfe/trunk/lib/Headers/ia32intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/ia32intrin.h?rev=356848&r1=356847&r2=356848&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/ia32intrin.h (original)
+++ cfe/trunk/lib/Headers/ia32intrin.h Sat Mar 23 17:56:52 2019
@@ -28,6 +28,114 @@
 #ifndef __IA32INTRIN_H
 #define __IA32INTRIN_H
 
+/** Find the first set bit starting from the lsb. Result is undefined if
+ *  input is 0.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSF </c> instruction or the
+ *  <c> TZCNT </c> instruction.
+ *
+ *  \param __A
+ *     A 32-bit integer operand.
+ *  \returns A 32-bit integer containing the bit number.
+ */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__bsfd(int __A) {
+  return __builtin_ctz(__A);
+}
+
+/** Find the first set bit starting from the msb. Result is undefined if
+ *  input is 0.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSR </c> instruction or the
+ *  <c> LZCNT </c> instruction and an <c> XOR </c>.
+ *
+ *  \param __A
+ *     A 32-bit integer operand.
+ *  \returns A 32-bit integer containing the bit number.
+ */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__bsrd(int __A) {
+  return 31 - __builtin_clz(__A);
+}
+
+/** Swaps the bytes in the input. Converting little endian to big endian or
+ *  vice versa.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSWAP </c> instruction.
+ *
+ *  \param __A
+ *     A 32-bit integer operand.
+ *  \returns A 32-bit integer containing the swapped bytes.
+ */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__bswapd(int __A) {
+  return __builtin_bswap32(__A);
+}
+
+#define _bswap(A) __bswapd((A))
+#define _bit_scan_forward(A) __bsfd((A))
+#define _bit_scan_reverse(A) __bsrd((A))
+
+#ifdef __x86_64__
+/** Find the first set bit starting from the lsb. Result is undefined if
+ *  input is 0.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSF </c> instruction or the
+ *  <c> TZCNT </c> instruction.
+ *
+ *  \param __A
+ *     A 64-bit integer operand.
+ *  \returns A 32-bit integer containing the bit number.
+ */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__bsfq(long long __A) {
+  return __builtin_ctzll(__A);
+}
+
+/** Find the first set bit starting from the msb. Result is undefined if
+ *  input is 0.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSR </c> instruction or the
+ *  <c> LZCNT </c> instruction and an <c> XOR </c>.
+ *
+ *  \param __A
+ *     A 64-bit integer operand.
+ *  \returns A 32-bit integer containing the bit number.
+ */
+static __inline__ int __attribute__((__always_inline__, __nodebug__))
+__bsrq(long long __A) {
+  return 63 - __builtin_clzll(__A);
+}
+
+/** Swaps the bytes in the input. Converting little endian to big endian or
+ *  vice versa.
+ *
+ *  \headerfile <x86intrin.h>
+ *
+ *  This intrinsic corresponds to the <c> BSWAP </c> instruction.
+ *
+ *  \param __A
+ *     A 64-bit integer operand.
+ *  \returns A 64-bit integer containing the swapped bytes.
+ */
+static __inline__ long long __attribute__((__always_inline__, __nodebug__))
+__bswapq(long long __A) {
+  return __builtin_bswap64(__A);
+}
+
+#define _bswap64(A) __bswapq((A))
+#endif
+
 /** Counts the number of bits in the source operand having a value of 1.
  *
  *  \headerfile <x86intrin.h>

Modified: cfe/trunk/lib/Headers/immintrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/immintrin.h?rev=356848&r1=356847&r2=356848&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/immintrin.h (original)
+++ cfe/trunk/lib/Headers/immintrin.h Sat Mar 23 17:56:52 2019
@@ -241,18 +241,6 @@ _rdrand64_step(unsigned long long *__p)
 #endif
 #endif /* __RDRND__ */
 
-/* __bit_scan_forward */
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
-_bit_scan_forward(int __A) {
-  return __builtin_ctz(__A);
-}
-
-/* __bit_scan_reverse */
-static __inline__ int __attribute__((__always_inline__, __nodebug__))
-_bit_scan_reverse(int __A) {
-  return 31 - __builtin_clz(__A);
-}
-
 #if !defined(_MSC_VER) || __has_feature(modules) || defined(__FSGSBASE__)
 #ifdef __x86_64__
 static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__, __target__("fsgsbase")))

Modified: cfe/trunk/test/CodeGen/bitscan-builtins.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/bitscan-builtins.c?rev=356848&r1=356847&r2=356848&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/bitscan-builtins.c (original)
+++ cfe/trunk/test/CodeGen/bitscan-builtins.c Sat Mar 23 17:56:52 2019
@@ -3,18 +3,45 @@
 // PR33722
 // RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-unknown -fms-extensions -fms-compatibility-version=19.00 -emit-llvm -o - %s | FileCheck %s
 
-#include <immintrin.h>
+#include <x86intrin.h>
 
 int test_bit_scan_forward(int a) {
   return _bit_scan_forward(a);
 // CHECK: @test_bit_scan_forward
-// CHECK: %[[call:.*]] = call i32 @llvm.cttz.i32(
+// CHECK: %[[call:.*]] = call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true)
 // CHECK: ret i32 %[[call]]
 }
 
 int test_bit_scan_reverse(int a) {
   return _bit_scan_reverse(a);
-// CHECK:  %[[call:.*]] = call i32 @llvm.ctlz.i32(
+// CHECK:  %[[call:.*]] = call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true)
 // CHECK:  %[[sub:.*]] = sub nsw i32 31, %[[call]]
 // CHECK: ret i32 %[[sub]]
 }
+
+int test__bsfd(int X) {
+// CHECK: @test__bsfd
+// CHECK: %[[call:.*]] = call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 true)
+  return __bsfd(X);
+}
+
+int test__bsfq(long long X) {
+// CHECK: @test__bsfq
+// CHECK: %[[call:.*]] = call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 true)
+  return __bsfq(X);
+}
+
+int test__bsrd(int X) {
+// CHECK: @test__bsrd
+// CHECK:  %[[call:.*]] = call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true)
+// CHECK:  %[[sub:.*]] = sub nsw i32 31, %[[call]]
+  return __bsrd(X);
+}
+
+int test__bsrq(long long X) {
+// CHECK: @test__bsrq
+// CHECK:  %[[call:.*]] = call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 true)
+// CHECK:  %[[cast:.*]] = trunc i64 %[[call]] to i32
+// CHECK:  %[[sub:.*]] = sub nsw i32 63, %[[cast]]
+  return __bsrq(X);
+}

Added: cfe/trunk/test/CodeGen/x86-bswap.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/x86-bswap.c?rev=356848&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/x86-bswap.c (added)
+++ cfe/trunk/test/CodeGen/x86-bswap.c Sat Mar 23 17:56:52 2019
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -ffreestanding %s -triple=x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
+
+#include <x86intrin.h>
+
+int test__bswapd(int X) {
+// CHECK-LABEL: @test__bswapd
+// CHECK: call i32 @llvm.bswap.i32
+  return __bswapd(X);
+}
+
+int test_bswap(int X) {
+// CHECK-LABEL: @test_bswap
+// CHECK: call i32 @llvm.bswap.i32
+  return _bswap(X);
+}
+
+long test__bswapq(long long X) {
+// CHECK-LABEL: @test__bswapq
+// CHECK: call i64 @llvm.bswap.i64
+  return __bswapq(X);
+}
+
+long test_bswap64(long long X) {
+// CHECK-LABEL: @test_bswap64
+// CHECK: call i64 @llvm.bswap.i64
+  return _bswap64(X);
+}
+
+




More information about the cfe-commits mailing list