xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/GISelValueTracking.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- llvm/CodeGen/GlobalISel/GISelValueTracking.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_GISELVALUETRACKING_H
15 #define LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
16 
17 #include "llvm/ADT/APFloat.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/Register.h"
22 #include "llvm/IR/InstrTypes.h"
23 #include "llvm/IR/PassManager.h"
24 #include "llvm/InitializePasses.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/KnownBits.h"
27 #include "llvm/Support/KnownFPClass.h"
28 
29 namespace llvm {
30 
31 class TargetLowering;
32 class DataLayout;
33 
34 class LLVM_ABI GISelValueTracking : public GISelChangeObserver {
35   MachineFunction &MF;
36   MachineRegisterInfo &MRI;
37   const TargetLowering &TL;
38   const DataLayout &DL;
39   unsigned MaxDepth;
40   /// Cache maintained during a computeKnownBits request.
41   SmallDenseMap<Register, KnownBits, 16> ComputeKnownBitsCache;
42 
43   void computeKnownBitsMin(Register Src0, Register Src1, KnownBits &Known,
44                            const APInt &DemandedElts, unsigned Depth = 0);
45 
46   unsigned computeNumSignBitsMin(Register Src0, Register Src1,
47                                  const APInt &DemandedElts, unsigned Depth = 0);
48 
49   void computeKnownFPClass(Register R, KnownFPClass &Known,
50                            FPClassTest InterestedClasses, unsigned Depth);
51 
52   void computeKnownFPClassForFPTrunc(const MachineInstr &MI,
53                                      const APInt &DemandedElts,
54                                      FPClassTest InterestedClasses,
55                                      KnownFPClass &Known, unsigned Depth);
56 
57   void computeKnownFPClass(Register R, const APInt &DemandedElts,
58                            FPClassTest InterestedClasses, KnownFPClass &Known,
59                            unsigned Depth);
60 
61 public:
62   GISelValueTracking(MachineFunction &MF, unsigned MaxDepth = 6);
63   virtual ~GISelValueTracking() = default;
64 
getMachineFunction()65   const MachineFunction &getMachineFunction() const { return MF; }
66 
getDataLayout()67   const DataLayout &getDataLayout() const { return DL; }
68 
69   virtual void computeKnownBitsImpl(Register R, KnownBits &Known,
70                                     const APInt &DemandedElts,
71                                     unsigned Depth = 0);
72 
73   unsigned computeNumSignBits(Register R, const APInt &DemandedElts,
74                               unsigned Depth = 0);
75   unsigned computeNumSignBits(Register R, unsigned Depth = 0);
76 
77   // KnownBitsAPI
78   KnownBits getKnownBits(Register R);
79   KnownBits getKnownBits(Register R, const APInt &DemandedElts,
80                          unsigned Depth = 0);
81 
82   // Calls getKnownBits for first operand def of MI.
83   KnownBits getKnownBits(MachineInstr &MI);
84   APInt getKnownZeroes(Register R);
85   APInt getKnownOnes(Register R);
86 
87   /// \return true if 'V & Mask' is known to be zero in DemandedElts. We use
88   /// this predicate to simplify operations downstream.
89   /// Mask is known to be zero for bits that V cannot have.
maskedValueIsZero(Register Val,const APInt & Mask)90   bool maskedValueIsZero(Register Val, const APInt &Mask) {
91     return Mask.isSubsetOf(getKnownBits(Val).Zero);
92   }
93 
94   /// \return true if the sign bit of Op is known to be zero.  We use this
95   /// predicate to simplify operations downstream.
96   bool signBitIsZero(Register Op);
97 
computeKnownBitsForAlignment(KnownBits & Known,Align Alignment)98   static void computeKnownBitsForAlignment(KnownBits &Known, Align Alignment) {
99     // The low bits are known zero if the pointer is aligned.
100     Known.Zero.setLowBits(Log2(Alignment));
101   }
102 
103   /// \return The known alignment for the pointer-like value \p R.
104   Align computeKnownAlignment(Register R, unsigned Depth = 0);
105 
106   /// Determine which floating-point classes are valid for \p V, and return them
107   /// in KnownFPClass bit sets.
108   ///
109   /// This function is defined on values with floating-point type, values
110   /// vectors of floating-point type, and arrays of floating-point type.
111 
112   /// \p InterestedClasses is a compile time optimization hint for which
113   /// floating point classes should be queried. Queries not specified in \p
114   /// InterestedClasses should be reliable if they are determined during the
115   /// query.
116   KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
117                                    FPClassTest InterestedClasses,
118                                    unsigned Depth);
119 
120   KnownFPClass computeKnownFPClass(Register R,
121                                    FPClassTest InterestedClasses = fcAllFlags,
122                                    unsigned Depth = 0);
123 
124   /// Wrapper to account for known fast math flags at the use instruction.
125   KnownFPClass computeKnownFPClass(Register R, const APInt &DemandedElts,
126                                    uint32_t Flags,
127                                    FPClassTest InterestedClasses,
128                                    unsigned Depth);
129 
130   KnownFPClass computeKnownFPClass(Register R, uint32_t Flags,
131                                    FPClassTest InterestedClasses,
132                                    unsigned Depth);
133 
134   // Observer API. No-op for non-caching implementation.
erasingInstr(MachineInstr & MI)135   void erasingInstr(MachineInstr &MI) override {}
createdInstr(MachineInstr & MI)136   void createdInstr(MachineInstr &MI) override {}
changingInstr(MachineInstr & MI)137   void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)138   void changedInstr(MachineInstr &MI) override {}
139 
140 protected:
getMaxDepth()141   unsigned getMaxDepth() const { return MaxDepth; }
142 };
143 
144 /// To use KnownBitsInfo analysis in a pass,
145 /// KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnalysis>().get(MF);
146 /// Add to observer if the Info is caching.
147 /// WrapperObserver.addObserver(Info);
148 
149 /// Eventually add other features such as caching/ser/deserializing
150 /// to MIR etc. Those implementations can derive from GISelValueTracking
151 /// and override computeKnownBitsImpl.
152 class LLVM_ABI GISelValueTrackingAnalysisLegacy : public MachineFunctionPass {
153   std::unique_ptr<GISelValueTracking> Info;
154 
155 public:
156   static char ID;
GISelValueTrackingAnalysisLegacy()157   GISelValueTrackingAnalysisLegacy() : MachineFunctionPass(ID) {
158     initializeGISelValueTrackingAnalysisLegacyPass(
159         *PassRegistry::getPassRegistry());
160   }
161   GISelValueTracking &get(MachineFunction &MF);
162   void getAnalysisUsage(AnalysisUsage &AU) const override;
163   bool runOnMachineFunction(MachineFunction &MF) override;
releaseMemory()164   void releaseMemory() override { Info.reset(); }
165 };
166 
167 class GISelValueTrackingAnalysis
168     : public AnalysisInfoMixin<GISelValueTrackingAnalysis> {
169   friend AnalysisInfoMixin<GISelValueTrackingAnalysis>;
170   LLVM_ABI static AnalysisKey Key;
171 
172 public:
173   using Result = GISelValueTracking;
174 
175   LLVM_ABI Result run(MachineFunction &MF,
176                       MachineFunctionAnalysisManager &MFAM);
177 };
178 
179 class GISelValueTrackingPrinterPass
180     : public PassInfoMixin<GISelValueTrackingPrinterPass> {
181   raw_ostream &OS;
182 
183 public:
GISelValueTrackingPrinterPass(raw_ostream & OS)184   GISelValueTrackingPrinterPass(raw_ostream &OS) : OS(OS) {}
185 
186   LLVM_ABI PreservedAnalyses run(MachineFunction &MF,
187                                  MachineFunctionAnalysisManager &MFAM);
188 };
189 } // namespace llvm
190 
191 #endif // LLVM_CODEGEN_GLOBALISEL_GISELVALUETRACKING_H
192