Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //==-- llvm/CodeGen/GlobalISel/Utils.h ---------------------------*- C++ -*-==// |
| 2 | // |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 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 |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | /// \file This file declares the API of helper functions used throughout the |
| 10 | /// GlobalISel pipeline. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_CODEGEN_GLOBALISEL_UTILS_H |
| 15 | #define LLVM_CODEGEN_GLOBALISEL_UTILS_H |
| 16 | |
| 17 | #include "llvm/ADT/StringRef.h" |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 18 | #include "llvm/CodeGen/Register.h" |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 19 | #include "llvm/Support/Alignment.h" |
| 20 | #include "llvm/Support/LowLevelTypeImpl.h" |
| 21 | #include <cstdint> |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 22 | |
| 23 | namespace llvm { |
| 24 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 25 | class AnalysisUsage; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 26 | class GISelKnownBits; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 27 | class MachineFunction; |
| 28 | class MachineInstr; |
| 29 | class MachineOperand; |
| 30 | class MachineOptimizationRemarkEmitter; |
| 31 | class MachineOptimizationRemarkMissed; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 32 | struct MachinePointerInfo; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 33 | class MachineRegisterInfo; |
| 34 | class MCInstrDesc; |
| 35 | class RegisterBankInfo; |
| 36 | class TargetInstrInfo; |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 37 | class TargetLowering; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 38 | class TargetPassConfig; |
| 39 | class TargetRegisterInfo; |
| 40 | class TargetRegisterClass; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 41 | class ConstantFP; |
| 42 | class APFloat; |
| 43 | |
| 44 | /// Try to constrain Reg to the specified register class. If this fails, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 45 | /// create a new virtual register in the correct class. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 46 | /// |
| 47 | /// \return The virtual register constrained to the right register class. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 48 | Register constrainRegToClass(MachineRegisterInfo &MRI, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 49 | const TargetInstrInfo &TII, |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 50 | const RegisterBankInfo &RBI, Register Reg, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 51 | const TargetRegisterClass &RegClass); |
| 52 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 53 | /// Constrain the Register operand OpIdx, so that it is now constrained to the |
| 54 | /// TargetRegisterClass passed as an argument (RegClass). |
| 55 | /// If this fails, create a new virtual register in the correct class and |
| 56 | /// insert a COPY before \p InsertPt if it is a use or after if it is a |
| 57 | /// definition. The debug location of \p InsertPt is used for the new copy. |
| 58 | /// |
| 59 | /// \return The virtual register constrained to the right register class. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 60 | Register constrainOperandRegClass(const MachineFunction &MF, |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 61 | const TargetRegisterInfo &TRI, |
| 62 | MachineRegisterInfo &MRI, |
| 63 | const TargetInstrInfo &TII, |
| 64 | const RegisterBankInfo &RBI, |
| 65 | MachineInstr &InsertPt, |
| 66 | const TargetRegisterClass &RegClass, |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 67 | const MachineOperand &RegMO); |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 68 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 69 | /// Try to constrain Reg so that it is usable by argument OpIdx of the |
| 70 | /// provided MCInstrDesc \p II. If this fails, create a new virtual |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 71 | /// register in the correct class and insert a COPY before \p InsertPt |
| 72 | /// if it is a use or after if it is a definition. |
| 73 | /// This is equivalent to constrainOperandRegClass(..., RegClass, ...) |
| 74 | /// with RegClass obtained from the MCInstrDesc. The debug location of \p |
| 75 | /// InsertPt is used for the new copy. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 76 | /// |
| 77 | /// \return The virtual register constrained to the right register class. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 78 | Register constrainOperandRegClass(const MachineFunction &MF, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 79 | const TargetRegisterInfo &TRI, |
| 80 | MachineRegisterInfo &MRI, |
| 81 | const TargetInstrInfo &TII, |
| 82 | const RegisterBankInfo &RBI, |
| 83 | MachineInstr &InsertPt, const MCInstrDesc &II, |
| 84 | const MachineOperand &RegMO, unsigned OpIdx); |
| 85 | |
| 86 | /// Mutate the newly-selected instruction \p I to constrain its (possibly |
| 87 | /// generic) virtual register operands to the instruction's register class. |
| 88 | /// This could involve inserting COPYs before (for uses) or after (for defs). |
| 89 | /// This requires the number of operands to match the instruction description. |
| 90 | /// \returns whether operand regclass constraining succeeded. |
| 91 | /// |
| 92 | // FIXME: Not all instructions have the same number of operands. We should |
| 93 | // probably expose a constrain helper per operand and let the target selector |
| 94 | // constrain individual registers, like fast-isel. |
| 95 | bool constrainSelectedInstRegOperands(MachineInstr &I, |
| 96 | const TargetInstrInfo &TII, |
| 97 | const TargetRegisterInfo &TRI, |
| 98 | const RegisterBankInfo &RBI); |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 99 | |
| 100 | /// Check if DstReg can be replaced with SrcReg depending on the register |
| 101 | /// constraints. |
| 102 | bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI); |
| 103 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 104 | /// Check whether an instruction \p MI is dead: it only defines dead virtual |
| 105 | /// registers, and doesn't have other side effects. |
| 106 | bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI); |
| 107 | |
| 108 | /// Report an ISel error as a missed optimization remark to the LLVMContext's |
| 109 | /// diagnostic stream. Set the FailedISel MachineFunction property. |
| 110 | void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, |
| 111 | MachineOptimizationRemarkEmitter &MORE, |
| 112 | MachineOptimizationRemarkMissed &R); |
| 113 | |
| 114 | void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, |
| 115 | MachineOptimizationRemarkEmitter &MORE, |
| 116 | const char *PassName, StringRef Msg, |
| 117 | const MachineInstr &MI); |
| 118 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 119 | /// Report an ISel warning as a missed optimization remark to the LLVMContext's |
| 120 | /// diagnostic stream. |
| 121 | void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC, |
| 122 | MachineOptimizationRemarkEmitter &MORE, |
| 123 | MachineOptimizationRemarkMissed &R); |
| 124 | |
| 125 | /// If \p VReg is defined by a G_CONSTANT, return the corresponding value. |
| 126 | Optional<APInt> getConstantVRegVal(Register VReg, |
| 127 | const MachineRegisterInfo &MRI); |
| 128 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 129 | /// If \p VReg is defined by a G_CONSTANT fits in int64_t |
| 130 | /// returns it. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 131 | Optional<int64_t> getConstantVRegSExtVal(Register VReg, |
| 132 | const MachineRegisterInfo &MRI); |
| 133 | |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 134 | /// Simple struct used to hold a constant integer value and a virtual |
| 135 | /// register. |
| 136 | struct ValueAndVReg { |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 137 | APInt Value; |
| 138 | Register VReg; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 139 | }; |
| 140 | /// If \p VReg is defined by a statically evaluable chain of |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 141 | /// instructions rooted on a G_F/CONSTANT (\p LookThroughInstrs == true) |
| 142 | /// and that constant fits in int64_t, returns its value as well as the |
| 143 | /// virtual register defined by this G_F/CONSTANT. |
| 144 | /// When \p LookThroughInstrs == false this function behaves like |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 145 | /// getConstantVRegVal. |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 146 | /// When \p HandleFConstants == false the function bails on G_FCONSTANTs. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 147 | Optional<ValueAndVReg> |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 148 | getConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, |
| 149 | bool LookThroughInstrs = true, |
| 150 | bool HandleFConstants = true); |
| 151 | const ConstantFP* getConstantFPVRegVal(Register VReg, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 152 | const MachineRegisterInfo &MRI); |
| 153 | |
| 154 | /// See if Reg is defined by an single def instruction that is |
| 155 | /// Opcode. Also try to do trivial folding if it's a COPY with |
| 156 | /// same types. Returns null otherwise. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 157 | MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg, |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 158 | const MachineRegisterInfo &MRI); |
| 159 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 160 | /// Simple struct used to hold a Register value and the instruction which |
| 161 | /// defines it. |
| 162 | struct DefinitionAndSourceRegister { |
| 163 | MachineInstr *MI; |
| 164 | Register Reg; |
| 165 | }; |
| 166 | |
| 167 | /// Find the def instruction for \p Reg, and underlying value Register folding |
| 168 | /// away any copies. |
| 169 | Optional<DefinitionAndSourceRegister> |
| 170 | getDefSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI); |
| 171 | |
| 172 | /// Find the def instruction for \p Reg, folding away any trivial copies. May |
| 173 | /// return nullptr if \p Reg is not a generic virtual register. |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 174 | MachineInstr *getDefIgnoringCopies(Register Reg, |
| 175 | const MachineRegisterInfo &MRI); |
| 176 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 177 | /// Find the source register for \p Reg, folding away any trivial copies. It |
| 178 | /// will be an output register of the instruction that getDefIgnoringCopies |
| 179 | /// returns. May return an invalid register if \p Reg is not a generic virtual |
| 180 | /// register. |
| 181 | Register getSrcRegIgnoringCopies(Register Reg, |
| 182 | const MachineRegisterInfo &MRI); |
| 183 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 184 | /// Returns an APFloat from Val converted to the appropriate size. |
| 185 | APFloat getAPFloatFromSize(double Val, unsigned Size); |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 186 | |
| 187 | /// Modify analysis usage so it preserves passes required for the SelectionDAG |
| 188 | /// fallback. |
| 189 | void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); |
| 190 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 191 | Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const Register Op1, |
| 192 | const Register Op2, |
Andrew Walbran | 16937d0 | 2019-10-22 13:54:20 +0100 | [diff] [blame] | 193 | const MachineRegisterInfo &MRI); |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 194 | |
| 195 | Optional<APInt> ConstantFoldExtOp(unsigned Opcode, const Register Op1, |
| 196 | uint64_t Imm, const MachineRegisterInfo &MRI); |
| 197 | |
| 198 | /// Test if the given value is known to have exactly one bit set. This differs |
| 199 | /// from computeKnownBits in that it doesn't necessarily determine which bit is |
| 200 | /// set. |
| 201 | bool isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI, |
| 202 | GISelKnownBits *KnownBits = nullptr); |
| 203 | |
| 204 | /// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true, |
| 205 | /// this returns if \p Val can be assumed to never be a signaling NaN. |
| 206 | bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, |
| 207 | bool SNaN = false); |
| 208 | |
| 209 | /// Returns true if \p Val can be assumed to never be a signaling NaN. |
| 210 | inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) { |
| 211 | return isKnownNeverNaN(Val, MRI, true); |
| 212 | } |
| 213 | |
| 214 | Align inferAlignFromPtrInfo(MachineFunction &MF, const MachinePointerInfo &MPO); |
| 215 | |
| 216 | /// Return a virtual register corresponding to the incoming argument register \p |
| 217 | /// PhysReg. This register is expected to have class \p RC, and optional type \p |
| 218 | /// RegTy. This assumes all references to the register will use the same type. |
| 219 | /// |
| 220 | /// If there is an existing live-in argument register, it will be returned. |
| 221 | /// This will also ensure there is a valid copy |
| 222 | Register getFunctionLiveInPhysReg(MachineFunction &MF, const TargetInstrInfo &TII, |
| 223 | MCRegister PhysReg, |
| 224 | const TargetRegisterClass &RC, |
| 225 | LLT RegTy = LLT()); |
| 226 | |
| 227 | /// Return the least common multiple type of \p OrigTy and \p TargetTy, by changing the |
| 228 | /// number of vector elements or scalar bitwidth. The intent is a |
| 229 | /// G_MERGE_VALUES, G_BUILD_VECTOR, or G_CONCAT_VECTORS can be constructed from |
| 230 | /// \p OrigTy elements, and unmerged into \p TargetTy |
| 231 | LLVM_READNONE |
| 232 | LLT getLCMType(LLT OrigTy, LLT TargetTy); |
| 233 | |
| 234 | /// Return a type where the total size is the greatest common divisor of \p |
| 235 | /// OrigTy and \p TargetTy. This will try to either change the number of vector |
| 236 | /// elements, or bitwidth of scalars. The intent is the result type can be used |
| 237 | /// as the result of a G_UNMERGE_VALUES from \p OrigTy, and then some |
| 238 | /// combination of G_MERGE_VALUES, G_BUILD_VECTOR and G_CONCAT_VECTORS (possibly |
| 239 | /// with intermediate casts) can re-form \p TargetTy. |
| 240 | /// |
| 241 | /// If these are vectors with different element types, this will try to produce |
| 242 | /// a vector with a compatible total size, but the element type of \p OrigTy. If |
| 243 | /// this can't be satisfied, this will produce a scalar smaller than the |
| 244 | /// original vector elements. |
| 245 | /// |
| 246 | /// In the worst case, this returns LLT::scalar(1) |
| 247 | LLVM_READNONE |
| 248 | LLT getGCDType(LLT OrigTy, LLT TargetTy); |
| 249 | |
| 250 | /// \returns The splat index of a G_SHUFFLE_VECTOR \p MI when \p MI is a splat. |
| 251 | /// If \p MI is not a splat, returns None. |
| 252 | Optional<int> getSplatIndex(MachineInstr &MI); |
| 253 | |
| 254 | /// Returns a scalar constant of a G_BUILD_VECTOR splat if it exists. |
| 255 | Optional<int64_t> getBuildVectorConstantSplat(const MachineInstr &MI, |
| 256 | const MachineRegisterInfo &MRI); |
| 257 | |
| 258 | /// Return true if the specified instruction is a G_BUILD_VECTOR or |
| 259 | /// G_BUILD_VECTOR_TRUNC where all of the elements are 0 or undef. |
| 260 | bool isBuildVectorAllZeros(const MachineInstr &MI, |
| 261 | const MachineRegisterInfo &MRI); |
| 262 | |
| 263 | /// Return true if the specified instruction is a G_BUILD_VECTOR or |
| 264 | /// G_BUILD_VECTOR_TRUNC where all of the elements are ~0 or undef. |
| 265 | bool isBuildVectorAllOnes(const MachineInstr &MI, |
| 266 | const MachineRegisterInfo &MRI); |
| 267 | |
| 268 | /// Returns true if given the TargetLowering's boolean contents information, |
| 269 | /// the value \p Val contains a true value. |
| 270 | bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, |
| 271 | bool IsFP); |
| 272 | |
| 273 | /// Returns an integer representing true, as defined by the |
| 274 | /// TargetBooleanContents. |
| 275 | int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP); |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 276 | } // End namespace llvm. |
| 277 | #endif |