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