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