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 
getMachineFunction()49   const MachineFunction &getMachineFunction() const {
50     return MF;
51   }
52 
getDataLayout()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.
maskedValueIsZero(Register Val,const APInt & Mask)78   bool maskedValueIsZero(Register Val, const APInt &Mask) {
79     return Mask.isSubsetOf(getKnownBits(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 
computeKnownBitsForAlignment(KnownBits & Known,Align Alignment)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(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.
erasingInstr(MachineInstr & MI)96   void erasingInstr(MachineInstr &MI) override {}
createdInstr(MachineInstr & MI)97   void createdInstr(MachineInstr &MI) override {}
changingInstr(MachineInstr & MI)98   void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)99   void changedInstr(MachineInstr &MI) override {}
100 
101 protected:
getMaxDepth()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;
GISelKnownBitsAnalysis()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;
releaseMemory()124   void releaseMemory() override { Info.reset(); }
125 };
126 } // namespace llvm
127 
128 #endif // LLVM_CODEGEN_GLOBALISEL_GISELKNOWNBITS_H
129