1 | //===- llvm/CodeGen/GlobalISel/GISelKnownBits.h ---------------*- 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 | /// \file |
9 | /// Provides analysis for querying information about KnownBits during GISel |
10 | /// passes. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H |
15 | #define LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H |
16 | |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" |
19 | #include "llvm/CodeGen/MachineFunctionPass.h" |
20 | #include "llvm/CodeGen/Register.h" |
21 | #include "llvm/InitializePasses.h" |
22 | #include "llvm/Support/KnownBits.h" |
23 | |
24 | namespace llvm { |
25 | |
26 | class TargetLowering; |
27 | class DataLayout; |
28 | |
29 | class GISelKnownBits : public GISelChangeObserver { |
30 | MachineFunction &MF; |
31 | MachineRegisterInfo &MRI; |
32 | const TargetLowering &TL; |
33 | const DataLayout &DL; |
34 | unsigned MaxDepth; |
35 | /// Cache maintained during a computeKnownBits request. |
36 | SmallDenseMap<Register, KnownBits, 16> ComputeKnownBitsCache; |
37 | |
38 | void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known, |
39 | const APInt &DemandedElts, |
40 | unsigned Depth = 0); |
41 | |
42 | unsigned computeNumSignBitsMin(Register Src0, Register Src1, |
43 | const APInt &DemandedElts, unsigned Depth = 0); |
44 | |
45 | public: |
46 | GISelKnownBits(MachineFunction &MF, unsigned MaxDepth = 6); |
47 | virtual ~GISelKnownBits() = default; |
48 | |
49 | const MachineFunction &getMachineFunction() const { |
50 | return MF; |
51 | } |
52 | |
53 | const DataLayout &getDataLayout() const { |
54 | return DL; |
55 | } |
56 | |
57 | virtual void computeKnownBitsImpl(Register R, KnownBits &Known, |
58 | const APInt &DemandedElts, |
59 | unsigned Depth = 0); |
60 | |
61 | unsigned computeNumSignBits(Register R, const APInt &DemandedElts, |
62 | unsigned Depth = 0); |
63 | unsigned computeNumSignBits(Register R, unsigned Depth = 0); |
64 | |
65 | // KnownBitsAPI |
66 | KnownBits getKnownBits(Register R); |
67 | KnownBits getKnownBits(Register R, const APInt &DemandedElts, |
68 | unsigned Depth = 0); |
69 | |
70 | // Calls getKnownBits for first operand def of MI. |
71 | KnownBits getKnownBits(MachineInstr &MI); |
72 | APInt getKnownZeroes(Register R); |
73 | APInt getKnownOnes(Register R); |
74 | |
75 | /// \return true if 'V & Mask' is known to be zero in DemandedElts. We use |
76 | /// this predicate to simplify operations downstream. |
77 | /// Mask is known to be zero for bits that V cannot have. |
78 | bool maskedValueIsZero(Register Val, const APInt &Mask) { |
79 | return Mask.isSubsetOf(RHS: getKnownBits(R: Val).Zero); |
80 | } |
81 | |
82 | /// \return true if the sign bit of Op is known to be zero. We use this |
83 | /// predicate to simplify operations downstream. |
84 | bool signBitIsZero(Register Op); |
85 | |
86 | static void computeKnownBitsForAlignment(KnownBits &Known, |
87 | Align Alignment) { |
88 | // The low bits are known zero if the pointer is aligned. |
89 | Known.Zero.setLowBits(Log2(A: Alignment)); |
90 | } |
91 | |
92 | /// \return The known alignment for the pointer-like value \p R. |
93 | Align computeKnownAlignment(Register R, unsigned Depth = 0); |
94 | |
95 | // Observer API. No-op for non-caching implementation. |
96 | void erasingInstr(MachineInstr &MI) override {} |
97 | void createdInstr(MachineInstr &MI) override {} |
98 | void changingInstr(MachineInstr &MI) override {} |
99 | void changedInstr(MachineInstr &MI) override {} |
100 | |
101 | protected: |
102 | unsigned getMaxDepth() const { return MaxDepth; } |
103 | }; |
104 | |
105 | /// To use KnownBitsInfo analysis in a pass, |
106 | /// KnownBitsInfo &Info = getAnalysis<GISelKnownBitsInfoAnalysis>().get(MF); |
107 | /// Add to observer if the Info is caching. |
108 | /// WrapperObserver.addObserver(Info); |
109 | |
110 | /// Eventually add other features such as caching/ser/deserializing |
111 | /// to MIR etc. Those implementations can derive from GISelKnownBits |
112 | /// and override computeKnownBitsImpl. |
113 | class GISelKnownBitsAnalysis : public MachineFunctionPass { |
114 | std::unique_ptr<GISelKnownBits> Info; |
115 | |
116 | public: |
117 | static char ID; |
118 | GISelKnownBitsAnalysis() : MachineFunctionPass(ID) { |
119 | initializeGISelKnownBitsAnalysisPass(*PassRegistry::getPassRegistry()); |
120 | } |
121 | GISelKnownBits &get(MachineFunction &MF); |
122 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
123 | bool runOnMachineFunction(MachineFunction &MF) override; |
124 | void releaseMemory() override { Info.reset(); } |
125 | }; |
126 | } // namespace llvm |
127 | |
128 | #endif // LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H |
129 | |