xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUGlobalISelUtils.cpp (revision e32fecd0c2c3ee37c47ee100f169e7eb0282a873)
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 
9 #include "AMDGPUGlobalISelUtils.h"
10 #include "GCNSubtarget.h"
11 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/Support/LowLevelTypeImpl.h"
14 
15 using namespace llvm;
16 using namespace MIPatternMatch;
17 
18 std::pair<Register, unsigned>
19 AMDGPU::getBaseWithConstantOffset(MachineRegisterInfo &MRI, Register Reg) {
20   MachineInstr *Def = getDefIgnoringCopies(Reg, MRI);
21   if (!Def)
22     return std::make_pair(Reg, 0);
23 
24   if (Def->getOpcode() == TargetOpcode::G_CONSTANT) {
25     unsigned Offset;
26     const MachineOperand &Op = Def->getOperand(1);
27     if (Op.isImm())
28       Offset = Op.getImm();
29     else
30       Offset = Op.getCImm()->getZExtValue();
31 
32     return std::make_pair(Register(), Offset);
33   }
34 
35   int64_t Offset;
36   if (Def->getOpcode() == TargetOpcode::G_ADD) {
37     // TODO: Handle G_OR used for add case
38     if (mi_match(Def->getOperand(2).getReg(), MRI, m_ICst(Offset)))
39       return std::make_pair(Def->getOperand(1).getReg(), Offset);
40 
41     // FIXME: matcher should ignore copies
42     if (mi_match(Def->getOperand(2).getReg(), MRI, m_Copy(m_ICst(Offset))))
43       return std::make_pair(Def->getOperand(1).getReg(), Offset);
44   }
45 
46   // Handle G_PTRTOINT (G_PTR_ADD base, const) case
47   if (Def->getOpcode() == TargetOpcode::G_PTRTOINT) {
48     MachineInstr *Base;
49     if (mi_match(Def->getOperand(1).getReg(), MRI,
50                  m_GPtrAdd(m_MInstr(Base), m_ICst(Offset)))) {
51       // If Base was int converted to pointer, simply return int and offset.
52       if (Base->getOpcode() == TargetOpcode::G_INTTOPTR)
53         return std::make_pair(Base->getOperand(1).getReg(), Offset);
54 
55       // Register returned here will be of pointer type.
56       return std::make_pair(Base->getOperand(0).getReg(), Offset);
57     }
58   }
59 
60   return std::make_pair(Reg, 0);
61 }
62 
63 bool AMDGPU::isLegalVOP3PShuffleMask(ArrayRef<int> Mask) {
64   assert(Mask.size() == 2);
65 
66   // If one half is undef, the other is trivially in the same reg.
67   if (Mask[0] == -1 || Mask[1] == -1)
68     return true;
69   return (Mask[0] & 2) == (Mask[1] & 2);
70 }
71 
72 bool AMDGPU::hasAtomicFaddRtnForTy(const GCNSubtarget &Subtarget,
73                                    const LLT &Ty) {
74   if (Ty == LLT::scalar(32))
75     return Subtarget.hasAtomicFaddRtnInsts();
76   if (Ty == LLT::fixed_vector(2, 16) || Ty == LLT::scalar(64))
77     return Subtarget.hasGFX90AInsts();
78   return false;
79 }
80