xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1480093f4SDimitry Andric //===- AMDGPUGlobalISelUtils.cpp ---------------------------------*- C++ -*-==//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric 
9480093f4SDimitry Andric #include "AMDGPUGlobalISelUtils.h"
1081ad6265SDimitry Andric #include "GCNSubtarget.h"
11bdd1243dSDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
12480093f4SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
13*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
14480093f4SDimitry Andric #include "llvm/IR/Constants.h"
15480093f4SDimitry Andric 
16480093f4SDimitry Andric using namespace llvm;
17480093f4SDimitry Andric using namespace MIPatternMatch;
18480093f4SDimitry Andric 
19e8d8bef9SDimitry Andric std::pair<Register, unsigned>
20bdd1243dSDimitry Andric AMDGPU::getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg,
215f757f3fSDimitry Andric                                   GISelKnownBits *KnownBits, bool CheckNUW) {
22480093f4SDimitry Andric   MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
23480093f4SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_CONSTANT) {
24480093f4SDimitry Andric     unsigned Offset;
25480093f4SDimitry Andric     const MachineOperand &Op = Def->getOperand(1);
26480093f4SDimitry Andric     if (Op.isImm())
27480093f4SDimitry Andric       Offset = Op.getImm();
28480093f4SDimitry Andric     else
29480093f4SDimitry Andric       Offset = Op.getCImm()->getZExtValue();
30480093f4SDimitry Andric 
31bdd1243dSDimitry Andric     return std::pair(Register(), Offset);
32480093f4SDimitry Andric   }
33480093f4SDimitry Andric 
34480093f4SDimitry Andric   int64_t Offset;
35480093f4SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_ADD) {
365f757f3fSDimitry Andric     // A 32-bit (address + offset) should not cause unsigned 32-bit integer
375f757f3fSDimitry Andric     // wraparound, because s_load instructions perform the addition in 64 bits.
385f757f3fSDimitry Andric     if (CheckNUW && !Def->getFlag(MachineInstr::NoUWrap)) {
395f757f3fSDimitry Andric       assert(MRI.getType(Reg).getScalarSizeInBits() == 32);
405f757f3fSDimitry Andric       return std::pair(Reg, 0);
415f757f3fSDimitry Andric     }
42480093f4SDimitry Andric     // TODO: Handle G_OR used for add case
43480093f4SDimitry Andric     if (mi_match(Def->getOperand(2).getReg(), MRI, m_ICst(Offset)))
44bdd1243dSDimitry Andric       return std::pair(Def->getOperand(1).getReg(), Offset);
45480093f4SDimitry Andric 
46480093f4SDimitry Andric     // FIXME: matcher should ignore copies
47480093f4SDimitry Andric     if (mi_match(Def->getOperand(2).getReg(), MRI, m_Copy(m_ICst(Offset))))
48bdd1243dSDimitry Andric       return std::pair(Def->getOperand(1).getReg(), Offset);
49480093f4SDimitry Andric   }
50480093f4SDimitry Andric 
51bdd1243dSDimitry Andric   Register Base;
52bdd1243dSDimitry Andric   if (KnownBits && mi_match(Reg, MRI, m_GOr(m_Reg(Base), m_ICst(Offset))) &&
53bdd1243dSDimitry Andric       KnownBits->maskedValueIsZero(Base, APInt(32, Offset)))
54bdd1243dSDimitry Andric     return std::pair(Base, Offset);
55bdd1243dSDimitry Andric 
56fe6060f1SDimitry Andric   // Handle G_PTRTOINT (G_PTR_ADD base, const) case
57fe6060f1SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_PTRTOINT) {
58fe6060f1SDimitry Andric     MachineInstr *Base;
59fe6060f1SDimitry Andric     if (mi_match(Def->getOperand(1).getReg(), MRI,
60fe6060f1SDimitry Andric                  m_GPtrAdd(m_MInstr(Base), m_ICst(Offset)))) {
61fe6060f1SDimitry Andric       // If Base was int converted to pointer, simply return int and offset.
62fe6060f1SDimitry Andric       if (Base->getOpcode() == TargetOpcode::G_INTTOPTR)
63bdd1243dSDimitry Andric         return std::pair(Base->getOperand(1).getReg(), Offset);
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric       // Register returned here will be of pointer type.
66bdd1243dSDimitry Andric       return std::pair(Base->getOperand(0).getReg(), Offset);
67fe6060f1SDimitry Andric     }
68fe6060f1SDimitry Andric   }
69fe6060f1SDimitry Andric 
70bdd1243dSDimitry Andric   return std::pair(Reg, 0);
715ffd83dbSDimitry Andric }
72