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