LLVM  16.0.0git
bit.h
Go to the documentation of this file.
1 //===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements the C++20 <bit> header.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ADT_BIT_H
15 #define LLVM_ADT_BIT_H
16 
17 #include <cstdint>
18 #include <cstring>
19 #include <type_traits>
20 
21 namespace llvm {
22 
23 // This implementation of bit_cast is different from the C++20 one in two ways:
24 // - It isn't constexpr because that requires compiler support.
25 // - It requires trivially-constructible To, to avoid UB in the implementation.
26 template <
27  typename To, typename From,
28  typename = std::enable_if_t<sizeof(To) == sizeof(From)>,
29  typename = std::enable_if_t<std::is_trivially_constructible<To>::value>,
30  typename = std::enable_if_t<std::is_trivially_copyable<To>::value>,
31  typename = std::enable_if_t<std::is_trivially_copyable<From>::value>>
32 inline To bit_cast(const From &from) noexcept {
33  To to;
34  std::memcpy(&to, &from, sizeof(To));
35  return to;
36 }
37 
38 template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
39 constexpr inline bool has_single_bit(T Value) noexcept {
40  return (Value != 0) && ((Value & (Value - 1)) == 0);
41 }
42 
43 namespace detail {
44 template <typename T, std::size_t SizeOfT> struct PopulationCounter {
45  static int count(T Value) {
46  // Generic version, forward to 32 bits.
47  static_assert(SizeOfT <= 4, "Not implemented!");
48 #if defined(__GNUC__)
49  return (int)__builtin_popcount(Value);
50 #else
51  uint32_t v = Value;
52  v = v - ((v >> 1) & 0x55555555);
53  v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
54  return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
55 #endif
56  }
57 };
58 
59 template <typename T> struct PopulationCounter<T, 8> {
60  static int count(T Value) {
61 #if defined(__GNUC__)
62  return (int)__builtin_popcountll(Value);
63 #else
64  uint64_t v = Value;
65  v = v - ((v >> 1) & 0x5555555555555555ULL);
66  v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL);
67  v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
68  return int((uint64_t)(v * 0x0101010101010101ULL) >> 56);
69 #endif
70  }
71 };
72 } // namespace detail
73 
74 /// Count the number of set bits in a value.
75 /// Ex. popcount(0xF000F000) = 8
76 /// Returns 0 if the word is zero.
77 template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
78 inline int popcount(T Value) noexcept {
79  return detail::PopulationCounter<T, sizeof(T)>::count(Value);
80 }
81 
82 } // namespace llvm
83 
84 #endif
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::detail::PopulationCounter
Definition: bit.h:44
to
Should compile to
Definition: README.txt:449
llvm::has_single_bit
constexpr bool has_single_bit(T Value) noexcept
Definition: bit.h:39
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::detail::PopulationCounter::count
static int count(T Value)
Definition: bit.h:45
llvm::popcount
int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition: bit.h:78
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
llvm::detail::PopulationCounter< T, 8 >::count
static int count(T Value)
Definition: bit.h:60
llvm::count
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition: STLExtras.h:1895
uint64_t
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
uint32_t
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::bit_cast
To bit_cast(const From &from) noexcept
Definition: bit.h:32
From
BlockVerifier::State From
Definition: BlockVerifier.cpp:55
llvm::Value
LLVM Value Representation.
Definition: Value.h:74