1 | //===-- include/llvm/CodeGen/ByteProvider.h - Map bytes ---------*- 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 ByteProvider. The purpose of ByteProvider is to provide |
11 | // a map between a target node's byte (byte position is DestOffset) and the |
12 | // source (and byte position) that provides it (in Src and SrcOffset |
13 | // respectively) See CodeGen/SelectionDAG/DAGCombiner.cpp MatchLoadCombine |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_CODEGEN_BYTEPROVIDER_H |
18 | #define LLVM_CODEGEN_BYTEPROVIDER_H |
19 | |
20 | #include <optional> |
21 | #include <type_traits> |
22 | |
23 | namespace llvm { |
24 | |
25 | /// Represents known origin of an individual byte in combine pattern. The |
26 | /// value of the byte is either constant zero, or comes from memory / |
27 | /// some other productive instruction (e.g. arithmetic instructions). |
28 | /// Bit manipulation instructions like shifts are not ByteProviders, rather |
29 | /// are used to extract Bytes. |
30 | template <typename ISelOp> class ByteProvider { |
31 | private: |
32 | ByteProvider(std::optional<ISelOp> Src, int64_t DestOffset, int64_t SrcOffset) |
33 | : Src(Src), DestOffset(DestOffset), SrcOffset(SrcOffset) {} |
34 | |
35 | // TODO -- use constraint in c++20 |
36 | // Does this type correspond with an operation in selection DAG |
37 | template <typename T> class is_op { |
38 | private: |
39 | using yes = std::true_type; |
40 | using no = std::false_type; |
41 | |
42 | // Only allow classes with member function getOpcode |
43 | template <typename U> |
44 | static auto test(int) -> decltype(std::declval<U>().getOpcode(), yes()); |
45 | |
46 | template <typename> static no test(...); |
47 | |
48 | public: |
49 | using remove_pointer_t = typename std::remove_pointer<T>::type; |
50 | static constexpr bool value = |
51 | std::is_same<decltype(test<remove_pointer_t>(0)), yes>::value; |
52 | }; |
53 | |
54 | public: |
55 | // For constant zero providers Src is set to nullopt. For actual providers |
56 | // Src represents the node which originally produced the relevant bits. |
57 | std::optional<ISelOp> Src = std::nullopt; |
58 | // DestOffset is the offset of the byte in the dest we are trying to map for. |
59 | int64_t DestOffset = 0; |
60 | // SrcOffset is the offset in the ultimate source node that maps to the |
61 | // DestOffset |
62 | int64_t SrcOffset = 0; |
63 | |
64 | ByteProvider() = default; |
65 | |
66 | static ByteProvider getSrc(std::optional<ISelOp> Val, int64_t ByteOffset, |
67 | int64_t VectorOffset) { |
68 | static_assert(is_op<ISelOp>().value, |
69 | "ByteProviders must contain an operation in selection DAG." ); |
70 | return ByteProvider(Val, ByteOffset, VectorOffset); |
71 | } |
72 | |
73 | static ByteProvider getConstantZero() { |
74 | return ByteProvider<ISelOp>(std::nullopt, 0, 0); |
75 | } |
76 | bool isConstantZero() const { return !Src; } |
77 | |
78 | bool hasSrc() const { return Src.has_value(); } |
79 | |
80 | bool hasSameSrc(const ByteProvider &Other) const { return Other.Src == Src; } |
81 | |
82 | bool operator==(const ByteProvider &Other) const { |
83 | return Other.Src == Src && Other.DestOffset == DestOffset && |
84 | Other.SrcOffset == SrcOffset; |
85 | } |
86 | }; |
87 | } // end namespace llvm |
88 | |
89 | #endif // LLVM_CODEGEN_BYTEPROVIDER_H |
90 | |