26#define DEBUG_TYPE "si-post-ra-16bit-mov-folding"
30class SIPostRA16BitMovFolding {
37 MCRegister &SrcReg32,
bool &SrcIsHi,
bool &SrcIsImm,
38 int64_t &ImmVal)
const;
41 bool IsHiFirst)
const;
55 return "SI post-RA 16bit Mov Folding";
64 return SIPostRA16BitMovFolding().run(MF);
71 "SI Post RA 16bit Mov Folding",
false,
false)
73char SIPostRA16BitMovFoldingLegacy::ID = 0;
80void SIPostRA16BitMovFolding::getMovB16Info(
82 bool &SrcIsVGPR,
MCRegister &SrcReg32,
bool &SrcIsHi,
bool &SrcIsImm,
83 int64_t &ImmVal)
const {
99 SrcIsVGPR = AMDGPU::VGPR_16RegClass.contains(SrcReg16);
102 SrcReg32 =
TRI->get32BitRegister(SrcReg16);
126bool SIPostRA16BitMovFolding::mergeSingleMovB16Pair(
MachineInstr &
Lo,
128 bool IsHiFirst)
const {
130 MCRegister LoDst =
Lo.getOperand(0).getReg().asMCReg();
131 MCRegister HiDst =
Hi.getOperand(0).getReg().asMCReg();
132 MCRegister Dst32 =
TRI->get32BitRegister(LoDst);
135 MCRegister LoSrc16, LoSrc32, HiSrc16, HiSrc32;
136 bool LoSrcIsHi, HiSrcIsHi, LoSrcIsImm, HiSrcIsImm, LoSrcIsVGPR, HiSrcIsVGPR;
137 int64_t LoImm = 0, HiImm = 0;
139 getMovB16Info(
Lo,
TRI, LoSrc16, LoSrcIsVGPR, LoSrc32, LoSrcIsHi, LoSrcIsImm,
141 getMovB16Info(
Hi,
TRI, HiSrc16, HiSrcIsVGPR, HiSrc32, HiSrcIsHi, HiSrcIsImm,
144 MachineInstr &FirstMI = IsHiFirst ?
Hi :
Lo;
145 MachineInstr &SecondMI = IsHiFirst ?
Lo :
Hi;
150 unsigned LoopCnt = 0, UpperBoundCnt = UINT_MAX, LowerBoundCnt = 0;
159 MCRegister FirstSrc16 = IsHiFirst ? HiSrc16 : LoSrc16;
160 MCRegister FirstDst16 = IsHiFirst ? HiDst : LoDst;
161 MCRegister SecondSrc16 = IsHiFirst ? LoSrc16 : HiSrc16;
162 MCRegister SecondDst16 = IsHiFirst ? LoDst : HiDst;
167 if (SecondSrc16 &&
TRI->regsOverlap(SecondSrc16, FirstDst16)) {
169 if (SecondSrc16 != FirstDst16)
172 getMovB16Info(FirstMI,
TRI, LoSrc16, LoSrcIsVGPR, LoSrc32, LoSrcIsHi,
175 getMovB16Info(FirstMI,
TRI, HiSrc16, HiSrcIsVGPR, HiSrc32, HiSrcIsHi,
180 for (MachineInstr &Scan :
182 if (Scan.isDebugInstr())
184 if (Scan.modifiesRegister(Dst32,
TRI))
187 if (LoopCnt < UpperBoundCnt &&
188 ((FirstSrc16 && Scan.modifiesRegister(FirstSrc16,
TRI)) ||
189 Scan.readsRegister(FirstDst16,
TRI))) {
190 UpperBound = Scan.getIterator();
191 UpperBoundCnt = LoopCnt;
193 if (LoopCnt > LowerBoundCnt &&
194 ((SecondSrc16 && Scan.modifiesRegister(SecondSrc16,
TRI)) ||
195 Scan.readsRegister(SecondDst16,
TRI))) {
197 LowerBoundCnt = LoopCnt;
202 if (LowerBoundCnt >= UpperBoundCnt)
207 MachineInstr &Selected = *UpperBound;
215 if (!HiSrcIsImm && !LoSrcIsImm) {
217 if (!LoSrcIsVGPR && !HiSrcIsVGPR && HiSrc32 != LoSrc32)
219 unsigned MaskHiSrc = HiSrcIsHi ? 0x0706 : 0x0504;
220 unsigned MaskLoSrc = LoSrcIsHi ? 0x0302 : 0x0100;
224 .
addImm((MaskHiSrc << 16) | MaskLoSrc);
225 Lo.eraseFromParent();
226 Hi.eraseFromParent();
231 AMDGPU::VGPR_32_Lo128RegClass.contains(Dst32) &&
233 (LoSrcIsVGPR && AMDGPU::VGPR_32_Lo128RegClass.contains(LoSrc32))) &&
235 (HiSrcIsVGPR && AMDGPU::VGPR_32_Lo128RegClass.contains(HiSrc32)));
239 if (LoSrcIsImm && HiSrcIsImm) {
241 TII->get(Usevop2 ? AMDGPU::V_MOV_B32_e32 : AMDGPU::V_MOV_B32_e64),
243 .
addImm(((HiImm & 0xffff) << 16) | (LoImm & 0xffff));
244 Lo.eraseFromParent();
245 Hi.eraseFromParent();
251 if (HiSrcIsImm && HiImm == 0 && !LoSrcIsImm && !LoSrcIsHi) {
253 TII->get(Usevop2 ? AMDGPU::V_AND_B32_e32 : AMDGPU::V_AND_B32_e64),
257 Lo.eraseFromParent();
258 Hi.eraseFromParent();
264 if (HiSrcIsImm && HiImm == 0 && !LoSrcIsImm && LoSrcIsHi) {
266 TII->get(Usevop2 ? AMDGPU::V_LSHRREV_B32_e32
267 : AMDGPU::V_LSHRREV_B32_e64),
271 Lo.eraseFromParent();
272 Hi.eraseFromParent();
278 if (LoSrcIsImm && LoImm == 0 && !HiSrcIsImm && !HiSrcIsHi) {
280 TII->get(Usevop2 ? AMDGPU::V_LSHLREV_B32_e32
281 : AMDGPU::V_LSHLREV_B32_e64),
285 Lo.eraseFromParent();
286 Hi.eraseFromParent();
292 if (LoSrcIsImm && LoImm == 0 && !HiSrcIsImm && HiSrcIsHi) {
294 TII->get(Usevop2 ? AMDGPU::V_AND_B32_e32 : AMDGPU::V_AND_B32_e64),
298 Lo.eraseFromParent();
299 Hi.eraseFromParent();
308bool SIPostRA16BitMovFolding::mergeMovB16Pairs(
MachineFunction &MF)
const {
310 for (MachineBasicBlock &
MBB : MF) {
320 const unsigned ScanLimit = 16;
321 std::array<Pending, ScanLimit> CirBuf = {};
322 SmallDenseMap<MCRegister, unsigned> PendingWrites;
326 if (
MI.isDebugInstr())
329 unsigned Opc =
MI.getOpcode();
330 bool IsMovB16 = (
Opc == AMDGPU::V_MOV_B16_t16_e32 ||
331 Opc == AMDGPU::V_MOV_B16_t16_e64);
333 if (++Head == ScanLimit)
337 PendingWrites.
erase(CirBuf[Head].Dst32);
340 CirBuf[Head] = {MCRegister(),
nullptr,
false};
345 MCRegister DstReg =
MI.getOperand(0).getReg().asMCReg();
347 MCRegister Dst32 =
TRI->get32BitRegister(DstReg);
350 CirBuf[Head] = {Dst32, &
MI, DstIsHi};
354 if (CirBuf[It->second].IsHi == DstIsHi) {
360 MachineInstr &LoMI = !DstIsHi ?
MI : *CirBuf[It->second].MI;
361 MachineInstr &HiMI = DstIsHi ?
MI : *CirBuf[It->second].MI;
362 bool IsHiFirst = CirBuf[It->second].IsHi;
363 if (mergeSingleMovB16Pair(LoMI, HiMI, IsHiFirst)) {
365 PendingWrites.
erase(It);
379 SIPostRA16BitMovFolding().run(MF);
386 TII = ST.getInstrInfo();
390 if (ST.useRealTrue16Insts())
391 Changed |= mergeMovB16Pairs(MF);
Provides AMDGPU specific target descriptions.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Wrapper class representing physical registers. Should be passed by value.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
MachineOperand class - Representation of each machine instruction operand.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represent a constant reference to a string, i.e.
self_iterator getIterator()
bool isHi16Reg(MCRegister Reg, const MCRegisterInfo &MRI)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
char & SIPostRA16BitMovFoldingLegacyID
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.