xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
11*bdd1243dSDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
12480093f4SDimitry Andric #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
13480093f4SDimitry Andric #include "llvm/IR/Constants.h"
1481ad6265SDimitry Andric #include "llvm/Support/LowLevelTypeImpl.h"
15480093f4SDimitry Andric 
16480093f4SDimitry Andric using namespace llvm;
17480093f4SDimitry Andric using namespace MIPatternMatch;
18480093f4SDimitry Andric 
19e8d8bef9SDimitry Andric std::pair<Register, unsigned>
20*bdd1243dSDimitry Andric AMDGPU::getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg,
21*bdd1243dSDimitry Andric                                   GISelKnownBits *KnownBits) {
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 
31*bdd1243dSDimitry Andric     return std::pair(Register(), Offset);
32480093f4SDimitry Andric   }
33480093f4SDimitry Andric 
34480093f4SDimitry Andric   int64_t Offset;
35480093f4SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_ADD) {
36480093f4SDimitry Andric     // TODO: Handle G_OR used for add case
37480093f4SDimitry Andric     if (mi_match(Def->getOperand(2).getReg(), MRI, m_ICst(Offset)))
38*bdd1243dSDimitry Andric       return std::pair(Def->getOperand(1).getReg(), Offset);
39480093f4SDimitry Andric 
40480093f4SDimitry Andric     // FIXME: matcher should ignore copies
41480093f4SDimitry Andric     if (mi_match(Def->getOperand(2).getReg(), MRI, m_Copy(m_ICst(Offset))))
42*bdd1243dSDimitry Andric       return std::pair(Def->getOperand(1).getReg(), Offset);
43480093f4SDimitry Andric   }
44480093f4SDimitry Andric 
45*bdd1243dSDimitry Andric   Register Base;
46*bdd1243dSDimitry Andric   if (KnownBits && mi_match(Reg, MRI, m_GOr(m_Reg(Base), m_ICst(Offset))) &&
47*bdd1243dSDimitry Andric       KnownBits->maskedValueIsZero(Base, APInt(32, Offset)))
48*bdd1243dSDimitry Andric     return std::pair(Base, Offset);
49*bdd1243dSDimitry Andric 
50fe6060f1SDimitry Andric   // Handle G_PTRTOINT (G_PTR_ADD base, const) case
51fe6060f1SDimitry Andric   if (Def->getOpcode() == TargetOpcode::G_PTRTOINT) {
52fe6060f1SDimitry Andric     MachineInstr *Base;
53fe6060f1SDimitry Andric     if (mi_match(Def->getOperand(1).getReg(), MRI,
54fe6060f1SDimitry Andric                  m_GPtrAdd(m_MInstr(Base), m_ICst(Offset)))) {
55fe6060f1SDimitry Andric       // If Base was int converted to pointer, simply return int and offset.
56fe6060f1SDimitry Andric       if (Base->getOpcode() == TargetOpcode::G_INTTOPTR)
57*bdd1243dSDimitry Andric         return std::pair(Base->getOperand(1).getReg(), Offset);
58fe6060f1SDimitry Andric 
59fe6060f1SDimitry Andric       // Register returned here will be of pointer type.
60*bdd1243dSDimitry Andric       return std::pair(Base->getOperand(0).getReg(), Offset);
61fe6060f1SDimitry Andric     }
62fe6060f1SDimitry Andric   }
63fe6060f1SDimitry Andric 
64*bdd1243dSDimitry Andric   return std::pair(Reg, 0);
655ffd83dbSDimitry Andric }
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric bool AMDGPU::hasAtomicFaddRtnForTy(const GCNSubtarget &Subtarget,
6881ad6265SDimitry Andric                                    const LLT &Ty) {
6981ad6265SDimitry Andric   if (Ty == LLT::scalar(32))
7081ad6265SDimitry Andric     return Subtarget.hasAtomicFaddRtnInsts();
7181ad6265SDimitry Andric   if (Ty == LLT::fixed_vector(2, 16) || Ty == LLT::scalar(64))
7281ad6265SDimitry Andric     return Subtarget.hasGFX90AInsts();
7381ad6265SDimitry Andric   return false;
7481ad6265SDimitry Andric }
75