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