LLVM 24.0.0git
AMDGPUGlobalISelUtils.cpp
Go to the documentation of this file.
1//===- AMDGPUGlobalISelUtils.cpp ---------------------------------*- 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
12#include "llvm/ADT/DenseSet.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/IntrinsicsAMDGPU.h"
20
21using namespace llvm;
22using namespace AMDGPU;
23using namespace MIPatternMatch;
24
25std::pair<Register, unsigned>
27 GISelValueTracking *ValueTracking,
28 bool CheckNUW) {
29 MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
30 if (Def->getOpcode() == TargetOpcode::G_CONSTANT) {
31 unsigned Offset;
32 const MachineOperand &Op = Def->getOperand(1);
33 if (Op.isImm())
34 Offset = Op.getImm();
35 else
36 Offset = Op.getCImm()->getZExtValue();
37
38 return std::pair(Register(), Offset);
39 }
40
41 int64_t Offset;
42 if (Def->getOpcode() == TargetOpcode::G_ADD) {
43 // A 32-bit (address + offset) should not cause unsigned 32-bit integer
44 // wraparound, because s_load instructions perform the addition in 64 bits.
45 if (CheckNUW && !Def->getFlag(MachineInstr::NoUWrap)) {
46 assert(MRI.getType(Reg).getScalarSizeInBits() == 32);
47 return std::pair(Reg, 0);
48 }
49 // TODO: Handle G_OR used for add case
50 if (mi_match(Def->getOperand(2).getReg(), MRI, m_ICst(Offset)))
51 return std::pair(Def->getOperand(1).getReg(), Offset);
52
53 // FIXME: matcher should ignore copies
54 if (mi_match(Def->getOperand(2).getReg(), MRI, m_Copy(m_ICst(Offset))))
55 return std::pair(Def->getOperand(1).getReg(), Offset);
56 }
57
59 if (ValueTracking && mi_match(Reg, MRI, m_GOr(m_Reg(Base), m_ICst(Offset))) &&
60 ValueTracking->maskedValueIsZero(Base,
61 APInt(32, Offset, /*isSigned=*/true)))
62 return std::pair(Base, Offset);
63
64 // Handle G_PTRTOINT (G_PTR_ADD base, const) case
65 if (Def->getOpcode() == TargetOpcode::G_PTRTOINT) {
67 Register PtrAdd = Def->getOperand(1).getReg();
68 if (mi_match(PtrAdd, MRI, m_GPtrAdd(m_MInstr(Base), m_ICst(Offset)))) {
69 // Same check as for G_ADD; nuw comes from getelementptr inbounds.
70 if (CheckNUW && !MRI.getVRegDef(PtrAdd)->getFlag(MachineInstr::NoUWrap)) {
71 assert(MRI.getType(Reg).getScalarSizeInBits() == 32);
72 return std::pair(Reg, 0);
73 }
74 // If Base was int converted to pointer, simply return int and offset.
75 if (Base->getOpcode() == TargetOpcode::G_INTTOPTR)
76 return std::pair(Base->getOperand(1).getReg(), Offset);
77
78 // Register returned here will be of pointer type.
79 return std::pair(Base->getOperand(0).getReg(), Offset);
80 }
81 }
82
83 return std::pair(Reg, 0);
84}
85
87 : MRI(MF.getRegInfo()) {
88 initLaneMaskIntrinsics(MF);
89}
90
92 return S32S64LaneMask.contains(Reg);
93}
94
95void IntrinsicLaneMaskAnalyzer::initLaneMaskIntrinsics(MachineFunction &MF) {
96 for (auto &MBB : MF) {
97 for (auto &MI : MBB) {
99 if (GI && GI->is(Intrinsic::amdgcn_if_break)) {
100 S32S64LaneMask.insert(MI.getOperand(3).getReg());
101 S32S64LaneMask.insert(MI.getOperand(0).getReg());
102 }
103
104 if (MI.getOpcode() == AMDGPU::SI_IF ||
105 MI.getOpcode() == AMDGPU::SI_ELSE) {
106 S32S64LaneMask.insert(MI.getOperand(0).getReg());
107 }
108 }
109 }
110}
111
113 if (Ty.isVector()) {
114 LLT ElTy = Ty.getElementType();
115 if (ElTy.getSizeInBits() == 16)
116 return LLT::fixed_vector(2, ElTy);
117 // S32, S64 or pointer
118 return ElTy;
119 }
120
121 // Large scalars and 64-bit pointers
122 return LLT::integer(32);
123}
124
125template <typename ReadLaneFnTy>
126static Register buildReadLane(MachineIRBuilder &, Register,
127 const RegisterBankInfo &, ReadLaneFnTy);
128
129template <typename ReadLaneFnTy>
130static void
132 LLT UnmergeTy, Register VgprSrc, const RegisterBankInfo &RBI,
133 ReadLaneFnTy BuildRL) {
134 const RegisterBank *VgprRB = &RBI.getRegBank(AMDGPU::VGPRRegBankID);
135 auto Unmerge = B.buildUnmerge({VgprRB, UnmergeTy}, VgprSrc);
136 for (unsigned i = 0; i < Unmerge->getNumOperands() - 1; ++i) {
137 SgprDstParts.push_back(buildReadLane(B, Unmerge.getReg(i), RBI, BuildRL));
138 }
139}
140
141template <typename ReadLaneFnTy>
143 const RegisterBankInfo &RBI,
144 ReadLaneFnTy BuildRL) {
145 LLT Ty = B.getMRI()->getType(VgprSrc);
146 const RegisterBank *SgprRB = &RBI.getRegBank(AMDGPU::SGPRRegBankID);
147 if (Ty.getSizeInBits() == 32) {
148 Register SgprDst = B.getMRI()->createVirtualRegister({SgprRB, Ty});
149 return BuildRL(B, SgprDst, VgprSrc).getReg(0);
150 }
151
152 SmallVector<Register, 8> SgprDstParts;
153 unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI,
154 BuildRL);
155
156 return B.buildMergeLikeInstr({SgprRB, Ty}, SgprDstParts).getReg(0);
157}
158
159template <typename ReadLaneFnTy>
161 Register VgprSrc, const RegisterBankInfo &RBI,
162 ReadLaneFnTy BuildReadLane) {
163 LLT Ty = B.getMRI()->getType(VgprSrc);
164 if (Ty.getSizeInBits() == 32) {
165 BuildReadLane(B, SgprDst, VgprSrc);
166 return;
167 }
168
169 SmallVector<Register, 8> SgprDstParts;
170 unmergeReadAnyLane(B, SgprDstParts, getReadAnyLaneSplitTy(Ty), VgprSrc, RBI,
171 BuildReadLane);
172
173 B.buildMergeLikeInstr(SgprDst, SgprDstParts).getReg(0);
174}
175
177 Register VgprSrc, const RegisterBankInfo &RBI) {
178 return buildReadLane(
179 B, SgprDst, VgprSrc, RBI,
180 [](MachineIRBuilder &B, Register SgprDst, Register VgprSrc) {
181 return B.buildInstr(AMDGPU::G_AMDGPU_READANYLANE, {SgprDst}, {VgprSrc});
182 });
183}
184
186 Register VgprSrc, const RegisterBankInfo &RBI) {
187 return buildReadLane(
188 B, SgprDst, VgprSrc, RBI,
189 [](MachineIRBuilder &B, Register SgprDst, Register VgprSrc) {
190 return B.buildIntrinsic(Intrinsic::amdgcn_readfirstlane, SgprDst)
191 .addReg(VgprSrc);
192 });
193}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static LLT getReadAnyLaneSplitTy(LLT Ty)
static Register buildReadLane(MachineIRBuilder &, Register, const RegisterBankInfo &, ReadLaneFnTy)
static void unmergeReadAnyLane(MachineIRBuilder &B, SmallVectorImpl< Register > &SgprDstParts, LLT UnmergeTy, Register VgprSrc, const RegisterBankInfo &RBI, ReadLaneFnTy BuildRL)
Provides AMDGPU specific target descriptions.
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseSet and SmallDenseSet classes.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
Class for arbitrary precision integers.
Definition APInt.h:78
bool maskedValueIsZero(Register Val, const APInt &Mask)
Represents a call to an intrinsic.
bool is(Intrinsic::ID ID) const
constexpr unsigned getScalarSizeInBits() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
static LLT integer(unsigned SizeInBits)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
Helper class to build MachineInstr.
Representation of each machine instruction.
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Holds all the information related to register banks.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< Register, unsigned > getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg, GISelValueTracking *ValueTracking=nullptr, bool CheckNUW=false)
Returns base register and constant offset.
void buildReadAnyLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
void buildReadFirstLane(MachineIRBuilder &B, Register SgprDst, Register VgprSrc, const RegisterBankInfo &RBI)
operand_type_match m_Reg()
UnaryOp_match< SrcTy, TargetOpcode::COPY > m_Copy(SrcTy &&Src)
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
bind_ty< MachineInstr * > m_MInstr(MachineInstr *&MI)
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:497
DWARFExpression::Operation Op