1*0b57cec5SDimitry Andric //===- SIInstrInfo.cpp - SI Instruction Information ----------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric /// \file 10*0b57cec5SDimitry Andric /// SI Implementation of TargetInstrInfo. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "SIInstrInfo.h" 15*0b57cec5SDimitry Andric #include "AMDGPU.h" 16*0b57cec5SDimitry Andric #include "AMDGPUSubtarget.h" 17*0b57cec5SDimitry Andric #include "GCNHazardRecognizer.h" 18*0b57cec5SDimitry Andric #include "SIDefines.h" 19*0b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h" 20*0b57cec5SDimitry Andric #include "SIRegisterInfo.h" 21*0b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 22*0b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h" 23*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 24*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 25*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 26*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 27*0b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 28*0b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 29*0b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h" 30*0b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 31*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 32*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 33*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 34*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 35*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 36*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 37*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h" 38*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 39*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 40*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 41*0b57cec5SDimitry Andric #include "llvm/CodeGen/RegisterScavenging.h" 42*0b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 43*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h" 44*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 45*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 46*0b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 47*0b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 48*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 49*0b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h" 50*0b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 51*0b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 52*0b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 53*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 54*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 55*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 56*0b57cec5SDimitry Andric #include "llvm/Support/MachineValueType.h" 57*0b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 58*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 59*0b57cec5SDimitry Andric #include <cassert> 60*0b57cec5SDimitry Andric #include <cstdint> 61*0b57cec5SDimitry Andric #include <iterator> 62*0b57cec5SDimitry Andric #include <utility> 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric using namespace llvm; 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 67*0b57cec5SDimitry Andric #include "AMDGPUGenInstrInfo.inc" 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric namespace llvm { 70*0b57cec5SDimitry Andric namespace AMDGPU { 71*0b57cec5SDimitry Andric #define GET_D16ImageDimIntrinsics_IMPL 72*0b57cec5SDimitry Andric #define GET_ImageDimIntrinsicTable_IMPL 73*0b57cec5SDimitry Andric #define GET_RsrcIntrinsics_IMPL 74*0b57cec5SDimitry Andric #include "AMDGPUGenSearchableTables.inc" 75*0b57cec5SDimitry Andric } 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric 79*0b57cec5SDimitry Andric // Must be at least 4 to be able to branch over minimum unconditional branch 80*0b57cec5SDimitry Andric // code. This is only for making it possible to write reasonably small tests for 81*0b57cec5SDimitry Andric // long branches. 82*0b57cec5SDimitry Andric static cl::opt<unsigned> 83*0b57cec5SDimitry Andric BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16), 84*0b57cec5SDimitry Andric cl::desc("Restrict range of branch instructions (DEBUG)")); 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric SIInstrInfo::SIInstrInfo(const GCNSubtarget &ST) 87*0b57cec5SDimitry Andric : AMDGPUGenInstrInfo(AMDGPU::ADJCALLSTACKUP, AMDGPU::ADJCALLSTACKDOWN), 88*0b57cec5SDimitry Andric RI(ST), ST(ST) {} 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 91*0b57cec5SDimitry Andric // TargetInstrInfo callbacks 92*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric static unsigned getNumOperandsNoGlue(SDNode *Node) { 95*0b57cec5SDimitry Andric unsigned N = Node->getNumOperands(); 96*0b57cec5SDimitry Andric while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue) 97*0b57cec5SDimitry Andric --N; 98*0b57cec5SDimitry Andric return N; 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric /// Returns true if both nodes have the same value for the given 102*0b57cec5SDimitry Andric /// operand \p Op, or if both nodes do not have this operand. 103*0b57cec5SDimitry Andric static bool nodesHaveSameOperandValue(SDNode *N0, SDNode* N1, unsigned OpName) { 104*0b57cec5SDimitry Andric unsigned Opc0 = N0->getMachineOpcode(); 105*0b57cec5SDimitry Andric unsigned Opc1 = N1->getMachineOpcode(); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName); 108*0b57cec5SDimitry Andric int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName); 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric if (Op0Idx == -1 && Op1Idx == -1) 111*0b57cec5SDimitry Andric return true; 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric if ((Op0Idx == -1 && Op1Idx != -1) || 115*0b57cec5SDimitry Andric (Op1Idx == -1 && Op0Idx != -1)) 116*0b57cec5SDimitry Andric return false; 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric // getNamedOperandIdx returns the index for the MachineInstr's operands, 119*0b57cec5SDimitry Andric // which includes the result as the first operand. We are indexing into the 120*0b57cec5SDimitry Andric // MachineSDNode's operands, so we need to skip the result operand to get 121*0b57cec5SDimitry Andric // the real index. 122*0b57cec5SDimitry Andric --Op0Idx; 123*0b57cec5SDimitry Andric --Op1Idx; 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx); 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric bool SIInstrInfo::isReallyTriviallyReMaterializable(const MachineInstr &MI, 129*0b57cec5SDimitry Andric AliasAnalysis *AA) const { 130*0b57cec5SDimitry Andric // TODO: The generic check fails for VALU instructions that should be 131*0b57cec5SDimitry Andric // rematerializable due to implicit reads of exec. We really want all of the 132*0b57cec5SDimitry Andric // generic logic for this except for this. 133*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 134*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e32: 135*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e64: 136*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B64_PSEUDO: 137*0b57cec5SDimitry Andric // No implicit operands. 138*0b57cec5SDimitry Andric return MI.getNumOperands() == MI.getDesc().getNumOperands(); 139*0b57cec5SDimitry Andric default: 140*0b57cec5SDimitry Andric return false; 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric bool SIInstrInfo::areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1, 145*0b57cec5SDimitry Andric int64_t &Offset0, 146*0b57cec5SDimitry Andric int64_t &Offset1) const { 147*0b57cec5SDimitry Andric if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode()) 148*0b57cec5SDimitry Andric return false; 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric unsigned Opc0 = Load0->getMachineOpcode(); 151*0b57cec5SDimitry Andric unsigned Opc1 = Load1->getMachineOpcode(); 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric // Make sure both are actually loads. 154*0b57cec5SDimitry Andric if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad()) 155*0b57cec5SDimitry Andric return false; 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric if (isDS(Opc0) && isDS(Opc1)) { 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric // FIXME: Handle this case: 160*0b57cec5SDimitry Andric if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1)) 161*0b57cec5SDimitry Andric return false; 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric // Check base reg. 164*0b57cec5SDimitry Andric if (Load0->getOperand(0) != Load1->getOperand(0)) 165*0b57cec5SDimitry Andric return false; 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric // Skip read2 / write2 variants for simplicity. 168*0b57cec5SDimitry Andric // TODO: We should report true if the used offsets are adjacent (excluded 169*0b57cec5SDimitry Andric // st64 versions). 170*0b57cec5SDimitry Andric int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset); 171*0b57cec5SDimitry Andric int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset); 172*0b57cec5SDimitry Andric if (Offset0Idx == -1 || Offset1Idx == -1) 173*0b57cec5SDimitry Andric return false; 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // XXX - be careful of datalesss loads 176*0b57cec5SDimitry Andric // getNamedOperandIdx returns the index for MachineInstrs. Since they 177*0b57cec5SDimitry Andric // include the output in the operand list, but SDNodes don't, we need to 178*0b57cec5SDimitry Andric // subtract the index by one. 179*0b57cec5SDimitry Andric Offset0Idx -= get(Opc0).NumDefs; 180*0b57cec5SDimitry Andric Offset1Idx -= get(Opc1).NumDefs; 181*0b57cec5SDimitry Andric Offset0 = cast<ConstantSDNode>(Load0->getOperand(Offset0Idx))->getZExtValue(); 182*0b57cec5SDimitry Andric Offset1 = cast<ConstantSDNode>(Load1->getOperand(Offset1Idx))->getZExtValue(); 183*0b57cec5SDimitry Andric return true; 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric if (isSMRD(Opc0) && isSMRD(Opc1)) { 187*0b57cec5SDimitry Andric // Skip time and cache invalidation instructions. 188*0b57cec5SDimitry Andric if (AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::sbase) == -1 || 189*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::sbase) == -1) 190*0b57cec5SDimitry Andric return false; 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric assert(getNumOperandsNoGlue(Load0) == getNumOperandsNoGlue(Load1)); 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andric // Check base reg. 195*0b57cec5SDimitry Andric if (Load0->getOperand(0) != Load1->getOperand(0)) 196*0b57cec5SDimitry Andric return false; 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric const ConstantSDNode *Load0Offset = 199*0b57cec5SDimitry Andric dyn_cast<ConstantSDNode>(Load0->getOperand(1)); 200*0b57cec5SDimitry Andric const ConstantSDNode *Load1Offset = 201*0b57cec5SDimitry Andric dyn_cast<ConstantSDNode>(Load1->getOperand(1)); 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric if (!Load0Offset || !Load1Offset) 204*0b57cec5SDimitry Andric return false; 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric Offset0 = Load0Offset->getZExtValue(); 207*0b57cec5SDimitry Andric Offset1 = Load1Offset->getZExtValue(); 208*0b57cec5SDimitry Andric return true; 209*0b57cec5SDimitry Andric } 210*0b57cec5SDimitry Andric 211*0b57cec5SDimitry Andric // MUBUF and MTBUF can access the same addresses. 212*0b57cec5SDimitry Andric if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) { 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric // MUBUF and MTBUF have vaddr at different indices. 215*0b57cec5SDimitry Andric if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) || 216*0b57cec5SDimitry Andric !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) || 217*0b57cec5SDimitry Andric !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc)) 218*0b57cec5SDimitry Andric return false; 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset); 221*0b57cec5SDimitry Andric int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset); 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric if (OffIdx0 == -1 || OffIdx1 == -1) 224*0b57cec5SDimitry Andric return false; 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric // getNamedOperandIdx returns the index for MachineInstrs. Since they 227*0b57cec5SDimitry Andric // include the output in the operand list, but SDNodes don't, we need to 228*0b57cec5SDimitry Andric // subtract the index by one. 229*0b57cec5SDimitry Andric OffIdx0 -= get(Opc0).NumDefs; 230*0b57cec5SDimitry Andric OffIdx1 -= get(Opc1).NumDefs; 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric SDValue Off0 = Load0->getOperand(OffIdx0); 233*0b57cec5SDimitry Andric SDValue Off1 = Load1->getOperand(OffIdx1); 234*0b57cec5SDimitry Andric 235*0b57cec5SDimitry Andric // The offset might be a FrameIndexSDNode. 236*0b57cec5SDimitry Andric if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1)) 237*0b57cec5SDimitry Andric return false; 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric Offset0 = cast<ConstantSDNode>(Off0)->getZExtValue(); 240*0b57cec5SDimitry Andric Offset1 = cast<ConstantSDNode>(Off1)->getZExtValue(); 241*0b57cec5SDimitry Andric return true; 242*0b57cec5SDimitry Andric } 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric return false; 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric static bool isStride64(unsigned Opc) { 248*0b57cec5SDimitry Andric switch (Opc) { 249*0b57cec5SDimitry Andric case AMDGPU::DS_READ2ST64_B32: 250*0b57cec5SDimitry Andric case AMDGPU::DS_READ2ST64_B64: 251*0b57cec5SDimitry Andric case AMDGPU::DS_WRITE2ST64_B32: 252*0b57cec5SDimitry Andric case AMDGPU::DS_WRITE2ST64_B64: 253*0b57cec5SDimitry Andric return true; 254*0b57cec5SDimitry Andric default: 255*0b57cec5SDimitry Andric return false; 256*0b57cec5SDimitry Andric } 257*0b57cec5SDimitry Andric } 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric bool SIInstrInfo::getMemOperandWithOffset(const MachineInstr &LdSt, 260*0b57cec5SDimitry Andric const MachineOperand *&BaseOp, 261*0b57cec5SDimitry Andric int64_t &Offset, 262*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 263*0b57cec5SDimitry Andric unsigned Opc = LdSt.getOpcode(); 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric if (isDS(LdSt)) { 266*0b57cec5SDimitry Andric const MachineOperand *OffsetImm = 267*0b57cec5SDimitry Andric getNamedOperand(LdSt, AMDGPU::OpName::offset); 268*0b57cec5SDimitry Andric if (OffsetImm) { 269*0b57cec5SDimitry Andric // Normal, single offset LDS instruction. 270*0b57cec5SDimitry Andric BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr); 271*0b57cec5SDimitry Andric // TODO: ds_consume/ds_append use M0 for the base address. Is it safe to 272*0b57cec5SDimitry Andric // report that here? 273*0b57cec5SDimitry Andric if (!BaseOp) 274*0b57cec5SDimitry Andric return false; 275*0b57cec5SDimitry Andric 276*0b57cec5SDimitry Andric Offset = OffsetImm->getImm(); 277*0b57cec5SDimitry Andric assert(BaseOp->isReg() && "getMemOperandWithOffset only supports base " 278*0b57cec5SDimitry Andric "operands of type register."); 279*0b57cec5SDimitry Andric return true; 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric // The 2 offset instructions use offset0 and offset1 instead. We can treat 283*0b57cec5SDimitry Andric // these as a load with a single offset if the 2 offsets are consecutive. We 284*0b57cec5SDimitry Andric // will use this for some partially aligned loads. 285*0b57cec5SDimitry Andric const MachineOperand *Offset0Imm = 286*0b57cec5SDimitry Andric getNamedOperand(LdSt, AMDGPU::OpName::offset0); 287*0b57cec5SDimitry Andric const MachineOperand *Offset1Imm = 288*0b57cec5SDimitry Andric getNamedOperand(LdSt, AMDGPU::OpName::offset1); 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric uint8_t Offset0 = Offset0Imm->getImm(); 291*0b57cec5SDimitry Andric uint8_t Offset1 = Offset1Imm->getImm(); 292*0b57cec5SDimitry Andric 293*0b57cec5SDimitry Andric if (Offset1 > Offset0 && Offset1 - Offset0 == 1) { 294*0b57cec5SDimitry Andric // Each of these offsets is in element sized units, so we need to convert 295*0b57cec5SDimitry Andric // to bytes of the individual reads. 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric unsigned EltSize; 298*0b57cec5SDimitry Andric if (LdSt.mayLoad()) 299*0b57cec5SDimitry Andric EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16; 300*0b57cec5SDimitry Andric else { 301*0b57cec5SDimitry Andric assert(LdSt.mayStore()); 302*0b57cec5SDimitry Andric int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0); 303*0b57cec5SDimitry Andric EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8; 304*0b57cec5SDimitry Andric } 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric if (isStride64(Opc)) 307*0b57cec5SDimitry Andric EltSize *= 64; 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr); 310*0b57cec5SDimitry Andric Offset = EltSize * Offset0; 311*0b57cec5SDimitry Andric assert(BaseOp->isReg() && "getMemOperandWithOffset only supports base " 312*0b57cec5SDimitry Andric "operands of type register."); 313*0b57cec5SDimitry Andric return true; 314*0b57cec5SDimitry Andric } 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric return false; 317*0b57cec5SDimitry Andric } 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric if (isMUBUF(LdSt) || isMTBUF(LdSt)) { 320*0b57cec5SDimitry Andric const MachineOperand *SOffset = getNamedOperand(LdSt, AMDGPU::OpName::soffset); 321*0b57cec5SDimitry Andric if (SOffset && SOffset->isReg()) 322*0b57cec5SDimitry Andric return false; 323*0b57cec5SDimitry Andric 324*0b57cec5SDimitry Andric const MachineOperand *AddrReg = getNamedOperand(LdSt, AMDGPU::OpName::vaddr); 325*0b57cec5SDimitry Andric if (!AddrReg) 326*0b57cec5SDimitry Andric return false; 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric const MachineOperand *OffsetImm = 329*0b57cec5SDimitry Andric getNamedOperand(LdSt, AMDGPU::OpName::offset); 330*0b57cec5SDimitry Andric BaseOp = AddrReg; 331*0b57cec5SDimitry Andric Offset = OffsetImm->getImm(); 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric if (SOffset) // soffset can be an inline immediate. 334*0b57cec5SDimitry Andric Offset += SOffset->getImm(); 335*0b57cec5SDimitry Andric 336*0b57cec5SDimitry Andric assert(BaseOp->isReg() && "getMemOperandWithOffset only supports base " 337*0b57cec5SDimitry Andric "operands of type register."); 338*0b57cec5SDimitry Andric return true; 339*0b57cec5SDimitry Andric } 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric if (isSMRD(LdSt)) { 342*0b57cec5SDimitry Andric const MachineOperand *OffsetImm = 343*0b57cec5SDimitry Andric getNamedOperand(LdSt, AMDGPU::OpName::offset); 344*0b57cec5SDimitry Andric if (!OffsetImm) 345*0b57cec5SDimitry Andric return false; 346*0b57cec5SDimitry Andric 347*0b57cec5SDimitry Andric const MachineOperand *SBaseReg = getNamedOperand(LdSt, AMDGPU::OpName::sbase); 348*0b57cec5SDimitry Andric BaseOp = SBaseReg; 349*0b57cec5SDimitry Andric Offset = OffsetImm->getImm(); 350*0b57cec5SDimitry Andric assert(BaseOp->isReg() && "getMemOperandWithOffset only supports base " 351*0b57cec5SDimitry Andric "operands of type register."); 352*0b57cec5SDimitry Andric return true; 353*0b57cec5SDimitry Andric } 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric if (isFLAT(LdSt)) { 356*0b57cec5SDimitry Andric const MachineOperand *VAddr = getNamedOperand(LdSt, AMDGPU::OpName::vaddr); 357*0b57cec5SDimitry Andric if (VAddr) { 358*0b57cec5SDimitry Andric // Can't analyze 2 offsets. 359*0b57cec5SDimitry Andric if (getNamedOperand(LdSt, AMDGPU::OpName::saddr)) 360*0b57cec5SDimitry Andric return false; 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric BaseOp = VAddr; 363*0b57cec5SDimitry Andric } else { 364*0b57cec5SDimitry Andric // scratch instructions have either vaddr or saddr. 365*0b57cec5SDimitry Andric BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr); 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm(); 369*0b57cec5SDimitry Andric assert(BaseOp->isReg() && "getMemOperandWithOffset only supports base " 370*0b57cec5SDimitry Andric "operands of type register."); 371*0b57cec5SDimitry Andric return true; 372*0b57cec5SDimitry Andric } 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric return false; 375*0b57cec5SDimitry Andric } 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric static bool memOpsHaveSameBasePtr(const MachineInstr &MI1, 378*0b57cec5SDimitry Andric const MachineOperand &BaseOp1, 379*0b57cec5SDimitry Andric const MachineInstr &MI2, 380*0b57cec5SDimitry Andric const MachineOperand &BaseOp2) { 381*0b57cec5SDimitry Andric // Support only base operands with base registers. 382*0b57cec5SDimitry Andric // Note: this could be extended to support FI operands. 383*0b57cec5SDimitry Andric if (!BaseOp1.isReg() || !BaseOp2.isReg()) 384*0b57cec5SDimitry Andric return false; 385*0b57cec5SDimitry Andric 386*0b57cec5SDimitry Andric if (BaseOp1.isIdenticalTo(BaseOp2)) 387*0b57cec5SDimitry Andric return true; 388*0b57cec5SDimitry Andric 389*0b57cec5SDimitry Andric if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand()) 390*0b57cec5SDimitry Andric return false; 391*0b57cec5SDimitry Andric 392*0b57cec5SDimitry Andric auto MO1 = *MI1.memoperands_begin(); 393*0b57cec5SDimitry Andric auto MO2 = *MI2.memoperands_begin(); 394*0b57cec5SDimitry Andric if (MO1->getAddrSpace() != MO2->getAddrSpace()) 395*0b57cec5SDimitry Andric return false; 396*0b57cec5SDimitry Andric 397*0b57cec5SDimitry Andric auto Base1 = MO1->getValue(); 398*0b57cec5SDimitry Andric auto Base2 = MO2->getValue(); 399*0b57cec5SDimitry Andric if (!Base1 || !Base2) 400*0b57cec5SDimitry Andric return false; 401*0b57cec5SDimitry Andric const MachineFunction &MF = *MI1.getParent()->getParent(); 402*0b57cec5SDimitry Andric const DataLayout &DL = MF.getFunction().getParent()->getDataLayout(); 403*0b57cec5SDimitry Andric Base1 = GetUnderlyingObject(Base1, DL); 404*0b57cec5SDimitry Andric Base2 = GetUnderlyingObject(Base1, DL); 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2)) 407*0b57cec5SDimitry Andric return false; 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric return Base1 == Base2; 410*0b57cec5SDimitry Andric } 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric bool SIInstrInfo::shouldClusterMemOps(const MachineOperand &BaseOp1, 413*0b57cec5SDimitry Andric const MachineOperand &BaseOp2, 414*0b57cec5SDimitry Andric unsigned NumLoads) const { 415*0b57cec5SDimitry Andric const MachineInstr &FirstLdSt = *BaseOp1.getParent(); 416*0b57cec5SDimitry Andric const MachineInstr &SecondLdSt = *BaseOp2.getParent(); 417*0b57cec5SDimitry Andric 418*0b57cec5SDimitry Andric if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOp1, SecondLdSt, BaseOp2)) 419*0b57cec5SDimitry Andric return false; 420*0b57cec5SDimitry Andric 421*0b57cec5SDimitry Andric const MachineOperand *FirstDst = nullptr; 422*0b57cec5SDimitry Andric const MachineOperand *SecondDst = nullptr; 423*0b57cec5SDimitry Andric 424*0b57cec5SDimitry Andric if ((isMUBUF(FirstLdSt) && isMUBUF(SecondLdSt)) || 425*0b57cec5SDimitry Andric (isMTBUF(FirstLdSt) && isMTBUF(SecondLdSt)) || 426*0b57cec5SDimitry Andric (isFLAT(FirstLdSt) && isFLAT(SecondLdSt))) { 427*0b57cec5SDimitry Andric const unsigned MaxGlobalLoadCluster = 6; 428*0b57cec5SDimitry Andric if (NumLoads > MaxGlobalLoadCluster) 429*0b57cec5SDimitry Andric return false; 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric FirstDst = getNamedOperand(FirstLdSt, AMDGPU::OpName::vdata); 432*0b57cec5SDimitry Andric if (!FirstDst) 433*0b57cec5SDimitry Andric FirstDst = getNamedOperand(FirstLdSt, AMDGPU::OpName::vdst); 434*0b57cec5SDimitry Andric SecondDst = getNamedOperand(SecondLdSt, AMDGPU::OpName::vdata); 435*0b57cec5SDimitry Andric if (!SecondDst) 436*0b57cec5SDimitry Andric SecondDst = getNamedOperand(SecondLdSt, AMDGPU::OpName::vdst); 437*0b57cec5SDimitry Andric } else if (isSMRD(FirstLdSt) && isSMRD(SecondLdSt)) { 438*0b57cec5SDimitry Andric FirstDst = getNamedOperand(FirstLdSt, AMDGPU::OpName::sdst); 439*0b57cec5SDimitry Andric SecondDst = getNamedOperand(SecondLdSt, AMDGPU::OpName::sdst); 440*0b57cec5SDimitry Andric } else if (isDS(FirstLdSt) && isDS(SecondLdSt)) { 441*0b57cec5SDimitry Andric FirstDst = getNamedOperand(FirstLdSt, AMDGPU::OpName::vdst); 442*0b57cec5SDimitry Andric SecondDst = getNamedOperand(SecondLdSt, AMDGPU::OpName::vdst); 443*0b57cec5SDimitry Andric } 444*0b57cec5SDimitry Andric 445*0b57cec5SDimitry Andric if (!FirstDst || !SecondDst) 446*0b57cec5SDimitry Andric return false; 447*0b57cec5SDimitry Andric 448*0b57cec5SDimitry Andric // Try to limit clustering based on the total number of bytes loaded 449*0b57cec5SDimitry Andric // rather than the number of instructions. This is done to help reduce 450*0b57cec5SDimitry Andric // register pressure. The method used is somewhat inexact, though, 451*0b57cec5SDimitry Andric // because it assumes that all loads in the cluster will load the 452*0b57cec5SDimitry Andric // same number of bytes as FirstLdSt. 453*0b57cec5SDimitry Andric 454*0b57cec5SDimitry Andric // The unit of this value is bytes. 455*0b57cec5SDimitry Andric // FIXME: This needs finer tuning. 456*0b57cec5SDimitry Andric unsigned LoadClusterThreshold = 16; 457*0b57cec5SDimitry Andric 458*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = 459*0b57cec5SDimitry Andric FirstLdSt.getParent()->getParent()->getRegInfo(); 460*0b57cec5SDimitry Andric 461*0b57cec5SDimitry Andric const unsigned Reg = FirstDst->getReg(); 462*0b57cec5SDimitry Andric 463*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC = TargetRegisterInfo::isVirtualRegister(Reg) 464*0b57cec5SDimitry Andric ? MRI.getRegClass(Reg) 465*0b57cec5SDimitry Andric : RI.getPhysRegClass(Reg); 466*0b57cec5SDimitry Andric 467*0b57cec5SDimitry Andric return (NumLoads * (RI.getRegSizeInBits(*DstRC) / 8)) <= LoadClusterThreshold; 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric // FIXME: This behaves strangely. If, for example, you have 32 load + stores, 471*0b57cec5SDimitry Andric // the first 16 loads will be interleaved with the stores, and the next 16 will 472*0b57cec5SDimitry Andric // be clustered as expected. It should really split into 2 16 store batches. 473*0b57cec5SDimitry Andric // 474*0b57cec5SDimitry Andric // Loads are clustered until this returns false, rather than trying to schedule 475*0b57cec5SDimitry Andric // groups of stores. This also means we have to deal with saying different 476*0b57cec5SDimitry Andric // address space loads should be clustered, and ones which might cause bank 477*0b57cec5SDimitry Andric // conflicts. 478*0b57cec5SDimitry Andric // 479*0b57cec5SDimitry Andric // This might be deprecated so it might not be worth that much effort to fix. 480*0b57cec5SDimitry Andric bool SIInstrInfo::shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, 481*0b57cec5SDimitry Andric int64_t Offset0, int64_t Offset1, 482*0b57cec5SDimitry Andric unsigned NumLoads) const { 483*0b57cec5SDimitry Andric assert(Offset1 > Offset0 && 484*0b57cec5SDimitry Andric "Second offset should be larger than first offset!"); 485*0b57cec5SDimitry Andric // If we have less than 16 loads in a row, and the offsets are within 64 486*0b57cec5SDimitry Andric // bytes, then schedule together. 487*0b57cec5SDimitry Andric 488*0b57cec5SDimitry Andric // A cacheline is 64 bytes (for global memory). 489*0b57cec5SDimitry Andric return (NumLoads <= 16 && (Offset1 - Offset0) < 64); 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB, 493*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 494*0b57cec5SDimitry Andric const DebugLoc &DL, unsigned DestReg, 495*0b57cec5SDimitry Andric unsigned SrcReg, bool KillSrc) { 496*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 497*0b57cec5SDimitry Andric DiagnosticInfoUnsupported IllegalCopy(MF->getFunction(), 498*0b57cec5SDimitry Andric "illegal SGPR to VGPR copy", 499*0b57cec5SDimitry Andric DL, DS_Error); 500*0b57cec5SDimitry Andric LLVMContext &C = MF->getFunction().getContext(); 501*0b57cec5SDimitry Andric C.diagnose(IllegalCopy); 502*0b57cec5SDimitry Andric 503*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg) 504*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 505*0b57cec5SDimitry Andric } 506*0b57cec5SDimitry Andric 507*0b57cec5SDimitry Andric void SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 508*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 509*0b57cec5SDimitry Andric const DebugLoc &DL, unsigned DestReg, 510*0b57cec5SDimitry Andric unsigned SrcReg, bool KillSrc) const { 511*0b57cec5SDimitry Andric const TargetRegisterClass *RC = RI.getPhysRegClass(DestReg); 512*0b57cec5SDimitry Andric 513*0b57cec5SDimitry Andric if (RC == &AMDGPU::VGPR_32RegClass) { 514*0b57cec5SDimitry Andric assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) || 515*0b57cec5SDimitry Andric AMDGPU::SReg_32RegClass.contains(SrcReg) || 516*0b57cec5SDimitry Andric AMDGPU::AGPR_32RegClass.contains(SrcReg)); 517*0b57cec5SDimitry Andric unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ? 518*0b57cec5SDimitry Andric AMDGPU::V_ACCVGPR_READ_B32 : AMDGPU::V_MOV_B32_e32; 519*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Opc), DestReg) 520*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 521*0b57cec5SDimitry Andric return; 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric if (RC == &AMDGPU::SReg_32_XM0RegClass || 525*0b57cec5SDimitry Andric RC == &AMDGPU::SReg_32RegClass) { 526*0b57cec5SDimitry Andric if (SrcReg == AMDGPU::SCC) { 527*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg) 528*0b57cec5SDimitry Andric .addImm(-1) 529*0b57cec5SDimitry Andric .addImm(0); 530*0b57cec5SDimitry Andric return; 531*0b57cec5SDimitry Andric } 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric if (DestReg == AMDGPU::VCC_LO) { 534*0b57cec5SDimitry Andric if (AMDGPU::SReg_32RegClass.contains(SrcReg)) { 535*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), AMDGPU::VCC_LO) 536*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 537*0b57cec5SDimitry Andric } else { 538*0b57cec5SDimitry Andric // FIXME: Hack until VReg_1 removed. 539*0b57cec5SDimitry Andric assert(AMDGPU::VGPR_32RegClass.contains(SrcReg)); 540*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32)) 541*0b57cec5SDimitry Andric .addImm(0) 542*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 543*0b57cec5SDimitry Andric } 544*0b57cec5SDimitry Andric 545*0b57cec5SDimitry Andric return; 546*0b57cec5SDimitry Andric } 547*0b57cec5SDimitry Andric 548*0b57cec5SDimitry Andric if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) { 549*0b57cec5SDimitry Andric reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc); 550*0b57cec5SDimitry Andric return; 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg) 554*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 555*0b57cec5SDimitry Andric return; 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric if (RC == &AMDGPU::SReg_64RegClass) { 559*0b57cec5SDimitry Andric if (DestReg == AMDGPU::VCC) { 560*0b57cec5SDimitry Andric if (AMDGPU::SReg_64RegClass.contains(SrcReg)) { 561*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), AMDGPU::VCC) 562*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 563*0b57cec5SDimitry Andric } else { 564*0b57cec5SDimitry Andric // FIXME: Hack until VReg_1 removed. 565*0b57cec5SDimitry Andric assert(AMDGPU::VGPR_32RegClass.contains(SrcReg)); 566*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32)) 567*0b57cec5SDimitry Andric .addImm(0) 568*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 569*0b57cec5SDimitry Andric } 570*0b57cec5SDimitry Andric 571*0b57cec5SDimitry Andric return; 572*0b57cec5SDimitry Andric } 573*0b57cec5SDimitry Andric 574*0b57cec5SDimitry Andric if (!AMDGPU::SReg_64RegClass.contains(SrcReg)) { 575*0b57cec5SDimitry Andric reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc); 576*0b57cec5SDimitry Andric return; 577*0b57cec5SDimitry Andric } 578*0b57cec5SDimitry Andric 579*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg) 580*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 581*0b57cec5SDimitry Andric return; 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric 584*0b57cec5SDimitry Andric if (DestReg == AMDGPU::SCC) { 585*0b57cec5SDimitry Andric assert(AMDGPU::SReg_32RegClass.contains(SrcReg)); 586*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)) 587*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)) 588*0b57cec5SDimitry Andric .addImm(0); 589*0b57cec5SDimitry Andric return; 590*0b57cec5SDimitry Andric } 591*0b57cec5SDimitry Andric 592*0b57cec5SDimitry Andric if (RC == &AMDGPU::AGPR_32RegClass) { 593*0b57cec5SDimitry Andric assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) || 594*0b57cec5SDimitry Andric AMDGPU::SReg_32RegClass.contains(SrcReg) || 595*0b57cec5SDimitry Andric AMDGPU::AGPR_32RegClass.contains(SrcReg)); 596*0b57cec5SDimitry Andric if (!AMDGPU::VGPR_32RegClass.contains(SrcReg)) { 597*0b57cec5SDimitry Andric // First try to find defining accvgpr_write to avoid temporary registers. 598*0b57cec5SDimitry Andric for (auto Def = MI, E = MBB.begin(); Def != E; ) { 599*0b57cec5SDimitry Andric --Def; 600*0b57cec5SDimitry Andric if (!Def->definesRegister(SrcReg, &RI)) 601*0b57cec5SDimitry Andric continue; 602*0b57cec5SDimitry Andric if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32) 603*0b57cec5SDimitry Andric break; 604*0b57cec5SDimitry Andric 605*0b57cec5SDimitry Andric MachineOperand &DefOp = Def->getOperand(1); 606*0b57cec5SDimitry Andric assert(DefOp.isReg() || DefOp.isImm()); 607*0b57cec5SDimitry Andric 608*0b57cec5SDimitry Andric if (DefOp.isReg()) { 609*0b57cec5SDimitry Andric // Check that register source operand if not clobbered before MI. 610*0b57cec5SDimitry Andric // Immediate operands are always safe to propagate. 611*0b57cec5SDimitry Andric bool SafeToPropagate = true; 612*0b57cec5SDimitry Andric for (auto I = Def; I != MI && SafeToPropagate; ++I) 613*0b57cec5SDimitry Andric if (I->modifiesRegister(DefOp.getReg(), &RI)) 614*0b57cec5SDimitry Andric SafeToPropagate = false; 615*0b57cec5SDimitry Andric 616*0b57cec5SDimitry Andric if (!SafeToPropagate) 617*0b57cec5SDimitry Andric break; 618*0b57cec5SDimitry Andric 619*0b57cec5SDimitry Andric DefOp.setIsKill(false); 620*0b57cec5SDimitry Andric } 621*0b57cec5SDimitry Andric 622*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32), DestReg) 623*0b57cec5SDimitry Andric .add(DefOp); 624*0b57cec5SDimitry Andric return; 625*0b57cec5SDimitry Andric } 626*0b57cec5SDimitry Andric 627*0b57cec5SDimitry Andric RegScavenger RS; 628*0b57cec5SDimitry Andric RS.enterBasicBlock(MBB); 629*0b57cec5SDimitry Andric RS.forward(MI); 630*0b57cec5SDimitry Andric 631*0b57cec5SDimitry Andric // Ideally we want to have three registers for a long reg_sequence copy 632*0b57cec5SDimitry Andric // to hide 2 waitstates between v_mov_b32 and accvgpr_write. 633*0b57cec5SDimitry Andric unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass, 634*0b57cec5SDimitry Andric *MBB.getParent()); 635*0b57cec5SDimitry Andric 636*0b57cec5SDimitry Andric // Registers in the sequence are allocated contiguously so we can just 637*0b57cec5SDimitry Andric // use register number to pick one of three round-robin temps. 638*0b57cec5SDimitry Andric unsigned RegNo = DestReg % 3; 639*0b57cec5SDimitry Andric unsigned Tmp = RS.scavengeRegister(&AMDGPU::VGPR_32RegClass, 0); 640*0b57cec5SDimitry Andric if (!Tmp) 641*0b57cec5SDimitry Andric report_fatal_error("Cannot scavenge VGPR to copy to AGPR"); 642*0b57cec5SDimitry Andric RS.setRegUsed(Tmp); 643*0b57cec5SDimitry Andric // Only loop through if there are any free registers left, otherwise 644*0b57cec5SDimitry Andric // scavenger may report a fatal error without emergency spill slot 645*0b57cec5SDimitry Andric // or spill with the slot. 646*0b57cec5SDimitry Andric while (RegNo-- && RS.FindUnusedReg(&AMDGPU::VGPR_32RegClass)) { 647*0b57cec5SDimitry Andric unsigned Tmp2 = RS.scavengeRegister(&AMDGPU::VGPR_32RegClass, 0); 648*0b57cec5SDimitry Andric if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs) 649*0b57cec5SDimitry Andric break; 650*0b57cec5SDimitry Andric Tmp = Tmp2; 651*0b57cec5SDimitry Andric RS.setRegUsed(Tmp); 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric copyPhysReg(MBB, MI, DL, Tmp, SrcReg, KillSrc); 654*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32), DestReg) 655*0b57cec5SDimitry Andric .addReg(Tmp, RegState::Kill); 656*0b57cec5SDimitry Andric return; 657*0b57cec5SDimitry Andric } 658*0b57cec5SDimitry Andric 659*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32), DestReg) 660*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(KillSrc)); 661*0b57cec5SDimitry Andric return; 662*0b57cec5SDimitry Andric } 663*0b57cec5SDimitry Andric 664*0b57cec5SDimitry Andric unsigned EltSize = 4; 665*0b57cec5SDimitry Andric unsigned Opcode = AMDGPU::V_MOV_B32_e32; 666*0b57cec5SDimitry Andric if (RI.isSGPRClass(RC)) { 667*0b57cec5SDimitry Andric // TODO: Copy vec3/vec5 with s_mov_b64s then final s_mov_b32. 668*0b57cec5SDimitry Andric if (!(RI.getRegSizeInBits(*RC) % 64)) { 669*0b57cec5SDimitry Andric Opcode = AMDGPU::S_MOV_B64; 670*0b57cec5SDimitry Andric EltSize = 8; 671*0b57cec5SDimitry Andric } else { 672*0b57cec5SDimitry Andric Opcode = AMDGPU::S_MOV_B32; 673*0b57cec5SDimitry Andric EltSize = 4; 674*0b57cec5SDimitry Andric } 675*0b57cec5SDimitry Andric 676*0b57cec5SDimitry Andric if (!RI.isSGPRClass(RI.getPhysRegClass(SrcReg))) { 677*0b57cec5SDimitry Andric reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc); 678*0b57cec5SDimitry Andric return; 679*0b57cec5SDimitry Andric } 680*0b57cec5SDimitry Andric } else if (RI.hasAGPRs(RC)) { 681*0b57cec5SDimitry Andric Opcode = RI.hasVGPRs(RI.getPhysRegClass(SrcReg)) ? 682*0b57cec5SDimitry Andric AMDGPU::V_ACCVGPR_WRITE_B32 : AMDGPU::COPY; 683*0b57cec5SDimitry Andric } else if (RI.hasVGPRs(RC) && RI.hasAGPRs(RI.getPhysRegClass(SrcReg))) { 684*0b57cec5SDimitry Andric Opcode = AMDGPU::V_ACCVGPR_READ_B32; 685*0b57cec5SDimitry Andric } 686*0b57cec5SDimitry Andric 687*0b57cec5SDimitry Andric ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize); 688*0b57cec5SDimitry Andric bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg); 689*0b57cec5SDimitry Andric 690*0b57cec5SDimitry Andric for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) { 691*0b57cec5SDimitry Andric unsigned SubIdx; 692*0b57cec5SDimitry Andric if (Forward) 693*0b57cec5SDimitry Andric SubIdx = SubIndices[Idx]; 694*0b57cec5SDimitry Andric else 695*0b57cec5SDimitry Andric SubIdx = SubIndices[SubIndices.size() - Idx - 1]; 696*0b57cec5SDimitry Andric 697*0b57cec5SDimitry Andric if (Opcode == TargetOpcode::COPY) { 698*0b57cec5SDimitry Andric copyPhysReg(MBB, MI, DL, RI.getSubReg(DestReg, SubIdx), 699*0b57cec5SDimitry Andric RI.getSubReg(SrcReg, SubIdx), KillSrc); 700*0b57cec5SDimitry Andric continue; 701*0b57cec5SDimitry Andric } 702*0b57cec5SDimitry Andric 703*0b57cec5SDimitry Andric MachineInstrBuilder Builder = BuildMI(MBB, MI, DL, 704*0b57cec5SDimitry Andric get(Opcode), RI.getSubReg(DestReg, SubIdx)); 705*0b57cec5SDimitry Andric 706*0b57cec5SDimitry Andric Builder.addReg(RI.getSubReg(SrcReg, SubIdx)); 707*0b57cec5SDimitry Andric 708*0b57cec5SDimitry Andric if (Idx == 0) 709*0b57cec5SDimitry Andric Builder.addReg(DestReg, RegState::Define | RegState::Implicit); 710*0b57cec5SDimitry Andric 711*0b57cec5SDimitry Andric bool UseKill = KillSrc && Idx == SubIndices.size() - 1; 712*0b57cec5SDimitry Andric Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit); 713*0b57cec5SDimitry Andric } 714*0b57cec5SDimitry Andric } 715*0b57cec5SDimitry Andric 716*0b57cec5SDimitry Andric int SIInstrInfo::commuteOpcode(unsigned Opcode) const { 717*0b57cec5SDimitry Andric int NewOpc; 718*0b57cec5SDimitry Andric 719*0b57cec5SDimitry Andric // Try to map original to commuted opcode 720*0b57cec5SDimitry Andric NewOpc = AMDGPU::getCommuteRev(Opcode); 721*0b57cec5SDimitry Andric if (NewOpc != -1) 722*0b57cec5SDimitry Andric // Check if the commuted (REV) opcode exists on the target. 723*0b57cec5SDimitry Andric return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1; 724*0b57cec5SDimitry Andric 725*0b57cec5SDimitry Andric // Try to map commuted to original opcode 726*0b57cec5SDimitry Andric NewOpc = AMDGPU::getCommuteOrig(Opcode); 727*0b57cec5SDimitry Andric if (NewOpc != -1) 728*0b57cec5SDimitry Andric // Check if the original (non-REV) opcode exists on the target. 729*0b57cec5SDimitry Andric return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1; 730*0b57cec5SDimitry Andric 731*0b57cec5SDimitry Andric return Opcode; 732*0b57cec5SDimitry Andric } 733*0b57cec5SDimitry Andric 734*0b57cec5SDimitry Andric void SIInstrInfo::materializeImmediate(MachineBasicBlock &MBB, 735*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 736*0b57cec5SDimitry Andric const DebugLoc &DL, unsigned DestReg, 737*0b57cec5SDimitry Andric int64_t Value) const { 738*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 739*0b57cec5SDimitry Andric const TargetRegisterClass *RegClass = MRI.getRegClass(DestReg); 740*0b57cec5SDimitry Andric if (RegClass == &AMDGPU::SReg_32RegClass || 741*0b57cec5SDimitry Andric RegClass == &AMDGPU::SGPR_32RegClass || 742*0b57cec5SDimitry Andric RegClass == &AMDGPU::SReg_32_XM0RegClass || 743*0b57cec5SDimitry Andric RegClass == &AMDGPU::SReg_32_XM0_XEXECRegClass) { 744*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg) 745*0b57cec5SDimitry Andric .addImm(Value); 746*0b57cec5SDimitry Andric return; 747*0b57cec5SDimitry Andric } 748*0b57cec5SDimitry Andric 749*0b57cec5SDimitry Andric if (RegClass == &AMDGPU::SReg_64RegClass || 750*0b57cec5SDimitry Andric RegClass == &AMDGPU::SGPR_64RegClass || 751*0b57cec5SDimitry Andric RegClass == &AMDGPU::SReg_64_XEXECRegClass) { 752*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg) 753*0b57cec5SDimitry Andric .addImm(Value); 754*0b57cec5SDimitry Andric return; 755*0b57cec5SDimitry Andric } 756*0b57cec5SDimitry Andric 757*0b57cec5SDimitry Andric if (RegClass == &AMDGPU::VGPR_32RegClass) { 758*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DestReg) 759*0b57cec5SDimitry Andric .addImm(Value); 760*0b57cec5SDimitry Andric return; 761*0b57cec5SDimitry Andric } 762*0b57cec5SDimitry Andric if (RegClass == &AMDGPU::VReg_64RegClass) { 763*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_PSEUDO), DestReg) 764*0b57cec5SDimitry Andric .addImm(Value); 765*0b57cec5SDimitry Andric return; 766*0b57cec5SDimitry Andric } 767*0b57cec5SDimitry Andric 768*0b57cec5SDimitry Andric unsigned EltSize = 4; 769*0b57cec5SDimitry Andric unsigned Opcode = AMDGPU::V_MOV_B32_e32; 770*0b57cec5SDimitry Andric if (RI.isSGPRClass(RegClass)) { 771*0b57cec5SDimitry Andric if (RI.getRegSizeInBits(*RegClass) > 32) { 772*0b57cec5SDimitry Andric Opcode = AMDGPU::S_MOV_B64; 773*0b57cec5SDimitry Andric EltSize = 8; 774*0b57cec5SDimitry Andric } else { 775*0b57cec5SDimitry Andric Opcode = AMDGPU::S_MOV_B32; 776*0b57cec5SDimitry Andric EltSize = 4; 777*0b57cec5SDimitry Andric } 778*0b57cec5SDimitry Andric } 779*0b57cec5SDimitry Andric 780*0b57cec5SDimitry Andric ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RegClass, EltSize); 781*0b57cec5SDimitry Andric for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) { 782*0b57cec5SDimitry Andric int64_t IdxValue = Idx == 0 ? Value : 0; 783*0b57cec5SDimitry Andric 784*0b57cec5SDimitry Andric MachineInstrBuilder Builder = BuildMI(MBB, MI, DL, 785*0b57cec5SDimitry Andric get(Opcode), RI.getSubReg(DestReg, Idx)); 786*0b57cec5SDimitry Andric Builder.addImm(IdxValue); 787*0b57cec5SDimitry Andric } 788*0b57cec5SDimitry Andric } 789*0b57cec5SDimitry Andric 790*0b57cec5SDimitry Andric const TargetRegisterClass * 791*0b57cec5SDimitry Andric SIInstrInfo::getPreferredSelectRegClass(unsigned Size) const { 792*0b57cec5SDimitry Andric return &AMDGPU::VGPR_32RegClass; 793*0b57cec5SDimitry Andric } 794*0b57cec5SDimitry Andric 795*0b57cec5SDimitry Andric void SIInstrInfo::insertVectorSelect(MachineBasicBlock &MBB, 796*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 797*0b57cec5SDimitry Andric const DebugLoc &DL, unsigned DstReg, 798*0b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 799*0b57cec5SDimitry Andric unsigned TrueReg, 800*0b57cec5SDimitry Andric unsigned FalseReg) const { 801*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 802*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 803*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>(); 804*0b57cec5SDimitry Andric const TargetRegisterClass *BoolXExecRC = 805*0b57cec5SDimitry Andric RI.getRegClass(AMDGPU::SReg_1_XEXECRegClassID); 806*0b57cec5SDimitry Andric assert(MRI.getRegClass(DstReg) == &AMDGPU::VGPR_32RegClass && 807*0b57cec5SDimitry Andric "Not a VGPR32 reg"); 808*0b57cec5SDimitry Andric 809*0b57cec5SDimitry Andric if (Cond.size() == 1) { 810*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 811*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::COPY), SReg) 812*0b57cec5SDimitry Andric .add(Cond[0]); 813*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 814*0b57cec5SDimitry Andric .addImm(0) 815*0b57cec5SDimitry Andric .addReg(FalseReg) 816*0b57cec5SDimitry Andric .addImm(0) 817*0b57cec5SDimitry Andric .addReg(TrueReg) 818*0b57cec5SDimitry Andric .addReg(SReg); 819*0b57cec5SDimitry Andric } else if (Cond.size() == 2) { 820*0b57cec5SDimitry Andric assert(Cond[0].isImm() && "Cond[0] is not an immediate"); 821*0b57cec5SDimitry Andric switch (Cond[0].getImm()) { 822*0b57cec5SDimitry Andric case SIInstrInfo::SCC_TRUE: { 823*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 824*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_CSELECT_B32 825*0b57cec5SDimitry Andric : AMDGPU::S_CSELECT_B64), SReg) 826*0b57cec5SDimitry Andric .addImm(-1) 827*0b57cec5SDimitry Andric .addImm(0); 828*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 829*0b57cec5SDimitry Andric .addImm(0) 830*0b57cec5SDimitry Andric .addReg(FalseReg) 831*0b57cec5SDimitry Andric .addImm(0) 832*0b57cec5SDimitry Andric .addReg(TrueReg) 833*0b57cec5SDimitry Andric .addReg(SReg); 834*0b57cec5SDimitry Andric break; 835*0b57cec5SDimitry Andric } 836*0b57cec5SDimitry Andric case SIInstrInfo::SCC_FALSE: { 837*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 838*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_CSELECT_B32 839*0b57cec5SDimitry Andric : AMDGPU::S_CSELECT_B64), SReg) 840*0b57cec5SDimitry Andric .addImm(0) 841*0b57cec5SDimitry Andric .addImm(-1); 842*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 843*0b57cec5SDimitry Andric .addImm(0) 844*0b57cec5SDimitry Andric .addReg(FalseReg) 845*0b57cec5SDimitry Andric .addImm(0) 846*0b57cec5SDimitry Andric .addReg(TrueReg) 847*0b57cec5SDimitry Andric .addReg(SReg); 848*0b57cec5SDimitry Andric break; 849*0b57cec5SDimitry Andric } 850*0b57cec5SDimitry Andric case SIInstrInfo::VCCNZ: { 851*0b57cec5SDimitry Andric MachineOperand RegOp = Cond[1]; 852*0b57cec5SDimitry Andric RegOp.setImplicit(false); 853*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 854*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::COPY), SReg) 855*0b57cec5SDimitry Andric .add(RegOp); 856*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 857*0b57cec5SDimitry Andric .addImm(0) 858*0b57cec5SDimitry Andric .addReg(FalseReg) 859*0b57cec5SDimitry Andric .addImm(0) 860*0b57cec5SDimitry Andric .addReg(TrueReg) 861*0b57cec5SDimitry Andric .addReg(SReg); 862*0b57cec5SDimitry Andric break; 863*0b57cec5SDimitry Andric } 864*0b57cec5SDimitry Andric case SIInstrInfo::VCCZ: { 865*0b57cec5SDimitry Andric MachineOperand RegOp = Cond[1]; 866*0b57cec5SDimitry Andric RegOp.setImplicit(false); 867*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 868*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::COPY), SReg) 869*0b57cec5SDimitry Andric .add(RegOp); 870*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 871*0b57cec5SDimitry Andric .addImm(0) 872*0b57cec5SDimitry Andric .addReg(TrueReg) 873*0b57cec5SDimitry Andric .addImm(0) 874*0b57cec5SDimitry Andric .addReg(FalseReg) 875*0b57cec5SDimitry Andric .addReg(SReg); 876*0b57cec5SDimitry Andric break; 877*0b57cec5SDimitry Andric } 878*0b57cec5SDimitry Andric case SIInstrInfo::EXECNZ: { 879*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 880*0b57cec5SDimitry Andric unsigned SReg2 = MRI.createVirtualRegister(RI.getBoolRC()); 881*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_OR_SAVEEXEC_B32 882*0b57cec5SDimitry Andric : AMDGPU::S_OR_SAVEEXEC_B64), SReg2) 883*0b57cec5SDimitry Andric .addImm(0); 884*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_CSELECT_B32 885*0b57cec5SDimitry Andric : AMDGPU::S_CSELECT_B64), SReg) 886*0b57cec5SDimitry Andric .addImm(-1) 887*0b57cec5SDimitry Andric .addImm(0); 888*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 889*0b57cec5SDimitry Andric .addImm(0) 890*0b57cec5SDimitry Andric .addReg(FalseReg) 891*0b57cec5SDimitry Andric .addImm(0) 892*0b57cec5SDimitry Andric .addReg(TrueReg) 893*0b57cec5SDimitry Andric .addReg(SReg); 894*0b57cec5SDimitry Andric break; 895*0b57cec5SDimitry Andric } 896*0b57cec5SDimitry Andric case SIInstrInfo::EXECZ: { 897*0b57cec5SDimitry Andric unsigned SReg = MRI.createVirtualRegister(BoolXExecRC); 898*0b57cec5SDimitry Andric unsigned SReg2 = MRI.createVirtualRegister(RI.getBoolRC()); 899*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_OR_SAVEEXEC_B32 900*0b57cec5SDimitry Andric : AMDGPU::S_OR_SAVEEXEC_B64), SReg2) 901*0b57cec5SDimitry Andric .addImm(0); 902*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(ST.isWave32() ? AMDGPU::S_CSELECT_B32 903*0b57cec5SDimitry Andric : AMDGPU::S_CSELECT_B64), SReg) 904*0b57cec5SDimitry Andric .addImm(0) 905*0b57cec5SDimitry Andric .addImm(-1); 906*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg) 907*0b57cec5SDimitry Andric .addImm(0) 908*0b57cec5SDimitry Andric .addReg(FalseReg) 909*0b57cec5SDimitry Andric .addImm(0) 910*0b57cec5SDimitry Andric .addReg(TrueReg) 911*0b57cec5SDimitry Andric .addReg(SReg); 912*0b57cec5SDimitry Andric llvm_unreachable("Unhandled branch predicate EXECZ"); 913*0b57cec5SDimitry Andric break; 914*0b57cec5SDimitry Andric } 915*0b57cec5SDimitry Andric default: 916*0b57cec5SDimitry Andric llvm_unreachable("invalid branch predicate"); 917*0b57cec5SDimitry Andric } 918*0b57cec5SDimitry Andric } else { 919*0b57cec5SDimitry Andric llvm_unreachable("Can only handle Cond size 1 or 2"); 920*0b57cec5SDimitry Andric } 921*0b57cec5SDimitry Andric } 922*0b57cec5SDimitry Andric 923*0b57cec5SDimitry Andric unsigned SIInstrInfo::insertEQ(MachineBasicBlock *MBB, 924*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 925*0b57cec5SDimitry Andric const DebugLoc &DL, 926*0b57cec5SDimitry Andric unsigned SrcReg, int Value) const { 927*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); 928*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(RI.getBoolRC()); 929*0b57cec5SDimitry Andric BuildMI(*MBB, I, DL, get(AMDGPU::V_CMP_EQ_I32_e64), Reg) 930*0b57cec5SDimitry Andric .addImm(Value) 931*0b57cec5SDimitry Andric .addReg(SrcReg); 932*0b57cec5SDimitry Andric 933*0b57cec5SDimitry Andric return Reg; 934*0b57cec5SDimitry Andric } 935*0b57cec5SDimitry Andric 936*0b57cec5SDimitry Andric unsigned SIInstrInfo::insertNE(MachineBasicBlock *MBB, 937*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 938*0b57cec5SDimitry Andric const DebugLoc &DL, 939*0b57cec5SDimitry Andric unsigned SrcReg, int Value) const { 940*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); 941*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(RI.getBoolRC()); 942*0b57cec5SDimitry Andric BuildMI(*MBB, I, DL, get(AMDGPU::V_CMP_NE_I32_e64), Reg) 943*0b57cec5SDimitry Andric .addImm(Value) 944*0b57cec5SDimitry Andric .addReg(SrcReg); 945*0b57cec5SDimitry Andric 946*0b57cec5SDimitry Andric return Reg; 947*0b57cec5SDimitry Andric } 948*0b57cec5SDimitry Andric 949*0b57cec5SDimitry Andric unsigned SIInstrInfo::getMovOpcode(const TargetRegisterClass *DstRC) const { 950*0b57cec5SDimitry Andric 951*0b57cec5SDimitry Andric if (RI.hasAGPRs(DstRC)) 952*0b57cec5SDimitry Andric return AMDGPU::COPY; 953*0b57cec5SDimitry Andric if (RI.getRegSizeInBits(*DstRC) == 32) { 954*0b57cec5SDimitry Andric return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32; 955*0b57cec5SDimitry Andric } else if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC)) { 956*0b57cec5SDimitry Andric return AMDGPU::S_MOV_B64; 957*0b57cec5SDimitry Andric } else if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC)) { 958*0b57cec5SDimitry Andric return AMDGPU::V_MOV_B64_PSEUDO; 959*0b57cec5SDimitry Andric } 960*0b57cec5SDimitry Andric return AMDGPU::COPY; 961*0b57cec5SDimitry Andric } 962*0b57cec5SDimitry Andric 963*0b57cec5SDimitry Andric static unsigned getSGPRSpillSaveOpcode(unsigned Size) { 964*0b57cec5SDimitry Andric switch (Size) { 965*0b57cec5SDimitry Andric case 4: 966*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S32_SAVE; 967*0b57cec5SDimitry Andric case 8: 968*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S64_SAVE; 969*0b57cec5SDimitry Andric case 12: 970*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S96_SAVE; 971*0b57cec5SDimitry Andric case 16: 972*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S128_SAVE; 973*0b57cec5SDimitry Andric case 20: 974*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S160_SAVE; 975*0b57cec5SDimitry Andric case 32: 976*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S256_SAVE; 977*0b57cec5SDimitry Andric case 64: 978*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S512_SAVE; 979*0b57cec5SDimitry Andric case 128: 980*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S1024_SAVE; 981*0b57cec5SDimitry Andric default: 982*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 983*0b57cec5SDimitry Andric } 984*0b57cec5SDimitry Andric } 985*0b57cec5SDimitry Andric 986*0b57cec5SDimitry Andric static unsigned getVGPRSpillSaveOpcode(unsigned Size) { 987*0b57cec5SDimitry Andric switch (Size) { 988*0b57cec5SDimitry Andric case 4: 989*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V32_SAVE; 990*0b57cec5SDimitry Andric case 8: 991*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V64_SAVE; 992*0b57cec5SDimitry Andric case 12: 993*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V96_SAVE; 994*0b57cec5SDimitry Andric case 16: 995*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V128_SAVE; 996*0b57cec5SDimitry Andric case 20: 997*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V160_SAVE; 998*0b57cec5SDimitry Andric case 32: 999*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V256_SAVE; 1000*0b57cec5SDimitry Andric case 64: 1001*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V512_SAVE; 1002*0b57cec5SDimitry Andric case 128: 1003*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V1024_SAVE; 1004*0b57cec5SDimitry Andric default: 1005*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 1006*0b57cec5SDimitry Andric } 1007*0b57cec5SDimitry Andric } 1008*0b57cec5SDimitry Andric 1009*0b57cec5SDimitry Andric static unsigned getAGPRSpillSaveOpcode(unsigned Size) { 1010*0b57cec5SDimitry Andric switch (Size) { 1011*0b57cec5SDimitry Andric case 4: 1012*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A32_SAVE; 1013*0b57cec5SDimitry Andric case 8: 1014*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A64_SAVE; 1015*0b57cec5SDimitry Andric case 16: 1016*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A128_SAVE; 1017*0b57cec5SDimitry Andric case 64: 1018*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A512_SAVE; 1019*0b57cec5SDimitry Andric case 128: 1020*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A1024_SAVE; 1021*0b57cec5SDimitry Andric default: 1022*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 1023*0b57cec5SDimitry Andric } 1024*0b57cec5SDimitry Andric } 1025*0b57cec5SDimitry Andric 1026*0b57cec5SDimitry Andric void SIInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 1027*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1028*0b57cec5SDimitry Andric unsigned SrcReg, bool isKill, 1029*0b57cec5SDimitry Andric int FrameIndex, 1030*0b57cec5SDimitry Andric const TargetRegisterClass *RC, 1031*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 1032*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1033*0b57cec5SDimitry Andric SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 1034*0b57cec5SDimitry Andric MachineFrameInfo &FrameInfo = MF->getFrameInfo(); 1035*0b57cec5SDimitry Andric const DebugLoc &DL = MBB.findDebugLoc(MI); 1036*0b57cec5SDimitry Andric 1037*0b57cec5SDimitry Andric unsigned Size = FrameInfo.getObjectSize(FrameIndex); 1038*0b57cec5SDimitry Andric unsigned Align = FrameInfo.getObjectAlignment(FrameIndex); 1039*0b57cec5SDimitry Andric MachinePointerInfo PtrInfo 1040*0b57cec5SDimitry Andric = MachinePointerInfo::getFixedStack(*MF, FrameIndex); 1041*0b57cec5SDimitry Andric MachineMemOperand *MMO 1042*0b57cec5SDimitry Andric = MF->getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore, 1043*0b57cec5SDimitry Andric Size, Align); 1044*0b57cec5SDimitry Andric unsigned SpillSize = TRI->getSpillSize(*RC); 1045*0b57cec5SDimitry Andric 1046*0b57cec5SDimitry Andric if (RI.isSGPRClass(RC)) { 1047*0b57cec5SDimitry Andric MFI->setHasSpilledSGPRs(); 1048*0b57cec5SDimitry Andric 1049*0b57cec5SDimitry Andric // We are only allowed to create one new instruction when spilling 1050*0b57cec5SDimitry Andric // registers, so we need to use pseudo instruction for spilling SGPRs. 1051*0b57cec5SDimitry Andric const MCInstrDesc &OpDesc = get(getSGPRSpillSaveOpcode(SpillSize)); 1052*0b57cec5SDimitry Andric 1053*0b57cec5SDimitry Andric // The SGPR spill/restore instructions only work on number sgprs, so we need 1054*0b57cec5SDimitry Andric // to make sure we are using the correct register class. 1055*0b57cec5SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(SrcReg) && SpillSize == 4) { 1056*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1057*0b57cec5SDimitry Andric MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0RegClass); 1058*0b57cec5SDimitry Andric } 1059*0b57cec5SDimitry Andric 1060*0b57cec5SDimitry Andric MachineInstrBuilder Spill = BuildMI(MBB, MI, DL, OpDesc) 1061*0b57cec5SDimitry Andric .addReg(SrcReg, getKillRegState(isKill)) // data 1062*0b57cec5SDimitry Andric .addFrameIndex(FrameIndex) // addr 1063*0b57cec5SDimitry Andric .addMemOperand(MMO) 1064*0b57cec5SDimitry Andric .addReg(MFI->getScratchRSrcReg(), RegState::Implicit) 1065*0b57cec5SDimitry Andric .addReg(MFI->getStackPtrOffsetReg(), RegState::Implicit); 1066*0b57cec5SDimitry Andric // Add the scratch resource registers as implicit uses because we may end up 1067*0b57cec5SDimitry Andric // needing them, and need to ensure that the reserved registers are 1068*0b57cec5SDimitry Andric // correctly handled. 1069*0b57cec5SDimitry Andric if (RI.spillSGPRToVGPR()) 1070*0b57cec5SDimitry Andric FrameInfo.setStackID(FrameIndex, TargetStackID::SGPRSpill); 1071*0b57cec5SDimitry Andric if (ST.hasScalarStores()) { 1072*0b57cec5SDimitry Andric // m0 is used for offset to scalar stores if used to spill. 1073*0b57cec5SDimitry Andric Spill.addReg(AMDGPU::M0, RegState::ImplicitDefine | RegState::Dead); 1074*0b57cec5SDimitry Andric } 1075*0b57cec5SDimitry Andric 1076*0b57cec5SDimitry Andric return; 1077*0b57cec5SDimitry Andric } 1078*0b57cec5SDimitry Andric 1079*0b57cec5SDimitry Andric unsigned Opcode = RI.hasAGPRs(RC) ? getAGPRSpillSaveOpcode(SpillSize) 1080*0b57cec5SDimitry Andric : getVGPRSpillSaveOpcode(SpillSize); 1081*0b57cec5SDimitry Andric MFI->setHasSpilledVGPRs(); 1082*0b57cec5SDimitry Andric 1083*0b57cec5SDimitry Andric auto MIB = BuildMI(MBB, MI, DL, get(Opcode)); 1084*0b57cec5SDimitry Andric if (RI.hasAGPRs(RC)) { 1085*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1086*0b57cec5SDimitry Andric unsigned Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 1087*0b57cec5SDimitry Andric MIB.addReg(Tmp, RegState::Define); 1088*0b57cec5SDimitry Andric } 1089*0b57cec5SDimitry Andric MIB.addReg(SrcReg, getKillRegState(isKill)) // data 1090*0b57cec5SDimitry Andric .addFrameIndex(FrameIndex) // addr 1091*0b57cec5SDimitry Andric .addReg(MFI->getScratchRSrcReg()) // scratch_rsrc 1092*0b57cec5SDimitry Andric .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset 1093*0b57cec5SDimitry Andric .addImm(0) // offset 1094*0b57cec5SDimitry Andric .addMemOperand(MMO); 1095*0b57cec5SDimitry Andric } 1096*0b57cec5SDimitry Andric 1097*0b57cec5SDimitry Andric static unsigned getSGPRSpillRestoreOpcode(unsigned Size) { 1098*0b57cec5SDimitry Andric switch (Size) { 1099*0b57cec5SDimitry Andric case 4: 1100*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S32_RESTORE; 1101*0b57cec5SDimitry Andric case 8: 1102*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S64_RESTORE; 1103*0b57cec5SDimitry Andric case 12: 1104*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S96_RESTORE; 1105*0b57cec5SDimitry Andric case 16: 1106*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S128_RESTORE; 1107*0b57cec5SDimitry Andric case 20: 1108*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S160_RESTORE; 1109*0b57cec5SDimitry Andric case 32: 1110*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S256_RESTORE; 1111*0b57cec5SDimitry Andric case 64: 1112*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S512_RESTORE; 1113*0b57cec5SDimitry Andric case 128: 1114*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_S1024_RESTORE; 1115*0b57cec5SDimitry Andric default: 1116*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 1117*0b57cec5SDimitry Andric } 1118*0b57cec5SDimitry Andric } 1119*0b57cec5SDimitry Andric 1120*0b57cec5SDimitry Andric static unsigned getVGPRSpillRestoreOpcode(unsigned Size) { 1121*0b57cec5SDimitry Andric switch (Size) { 1122*0b57cec5SDimitry Andric case 4: 1123*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V32_RESTORE; 1124*0b57cec5SDimitry Andric case 8: 1125*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V64_RESTORE; 1126*0b57cec5SDimitry Andric case 12: 1127*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V96_RESTORE; 1128*0b57cec5SDimitry Andric case 16: 1129*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V128_RESTORE; 1130*0b57cec5SDimitry Andric case 20: 1131*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V160_RESTORE; 1132*0b57cec5SDimitry Andric case 32: 1133*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V256_RESTORE; 1134*0b57cec5SDimitry Andric case 64: 1135*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V512_RESTORE; 1136*0b57cec5SDimitry Andric case 128: 1137*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_V1024_RESTORE; 1138*0b57cec5SDimitry Andric default: 1139*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 1140*0b57cec5SDimitry Andric } 1141*0b57cec5SDimitry Andric } 1142*0b57cec5SDimitry Andric 1143*0b57cec5SDimitry Andric static unsigned getAGPRSpillRestoreOpcode(unsigned Size) { 1144*0b57cec5SDimitry Andric switch (Size) { 1145*0b57cec5SDimitry Andric case 4: 1146*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A32_RESTORE; 1147*0b57cec5SDimitry Andric case 8: 1148*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A64_RESTORE; 1149*0b57cec5SDimitry Andric case 16: 1150*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A128_RESTORE; 1151*0b57cec5SDimitry Andric case 64: 1152*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A512_RESTORE; 1153*0b57cec5SDimitry Andric case 128: 1154*0b57cec5SDimitry Andric return AMDGPU::SI_SPILL_A1024_RESTORE; 1155*0b57cec5SDimitry Andric default: 1156*0b57cec5SDimitry Andric llvm_unreachable("unknown register size"); 1157*0b57cec5SDimitry Andric } 1158*0b57cec5SDimitry Andric } 1159*0b57cec5SDimitry Andric 1160*0b57cec5SDimitry Andric void SIInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 1161*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1162*0b57cec5SDimitry Andric unsigned DestReg, int FrameIndex, 1163*0b57cec5SDimitry Andric const TargetRegisterClass *RC, 1164*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 1165*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1166*0b57cec5SDimitry Andric SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 1167*0b57cec5SDimitry Andric MachineFrameInfo &FrameInfo = MF->getFrameInfo(); 1168*0b57cec5SDimitry Andric const DebugLoc &DL = MBB.findDebugLoc(MI); 1169*0b57cec5SDimitry Andric unsigned Align = FrameInfo.getObjectAlignment(FrameIndex); 1170*0b57cec5SDimitry Andric unsigned Size = FrameInfo.getObjectSize(FrameIndex); 1171*0b57cec5SDimitry Andric unsigned SpillSize = TRI->getSpillSize(*RC); 1172*0b57cec5SDimitry Andric 1173*0b57cec5SDimitry Andric MachinePointerInfo PtrInfo 1174*0b57cec5SDimitry Andric = MachinePointerInfo::getFixedStack(*MF, FrameIndex); 1175*0b57cec5SDimitry Andric 1176*0b57cec5SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 1177*0b57cec5SDimitry Andric PtrInfo, MachineMemOperand::MOLoad, Size, Align); 1178*0b57cec5SDimitry Andric 1179*0b57cec5SDimitry Andric if (RI.isSGPRClass(RC)) { 1180*0b57cec5SDimitry Andric MFI->setHasSpilledSGPRs(); 1181*0b57cec5SDimitry Andric 1182*0b57cec5SDimitry Andric // FIXME: Maybe this should not include a memoperand because it will be 1183*0b57cec5SDimitry Andric // lowered to non-memory instructions. 1184*0b57cec5SDimitry Andric const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize)); 1185*0b57cec5SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(DestReg) && SpillSize == 4) { 1186*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1187*0b57cec5SDimitry Andric MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0RegClass); 1188*0b57cec5SDimitry Andric } 1189*0b57cec5SDimitry Andric 1190*0b57cec5SDimitry Andric if (RI.spillSGPRToVGPR()) 1191*0b57cec5SDimitry Andric FrameInfo.setStackID(FrameIndex, TargetStackID::SGPRSpill); 1192*0b57cec5SDimitry Andric MachineInstrBuilder Spill = BuildMI(MBB, MI, DL, OpDesc, DestReg) 1193*0b57cec5SDimitry Andric .addFrameIndex(FrameIndex) // addr 1194*0b57cec5SDimitry Andric .addMemOperand(MMO) 1195*0b57cec5SDimitry Andric .addReg(MFI->getScratchRSrcReg(), RegState::Implicit) 1196*0b57cec5SDimitry Andric .addReg(MFI->getStackPtrOffsetReg(), RegState::Implicit); 1197*0b57cec5SDimitry Andric 1198*0b57cec5SDimitry Andric if (ST.hasScalarStores()) { 1199*0b57cec5SDimitry Andric // m0 is used for offset to scalar stores if used to spill. 1200*0b57cec5SDimitry Andric Spill.addReg(AMDGPU::M0, RegState::ImplicitDefine | RegState::Dead); 1201*0b57cec5SDimitry Andric } 1202*0b57cec5SDimitry Andric 1203*0b57cec5SDimitry Andric return; 1204*0b57cec5SDimitry Andric } 1205*0b57cec5SDimitry Andric 1206*0b57cec5SDimitry Andric unsigned Opcode = RI.hasAGPRs(RC) ? getAGPRSpillRestoreOpcode(SpillSize) 1207*0b57cec5SDimitry Andric : getVGPRSpillRestoreOpcode(SpillSize); 1208*0b57cec5SDimitry Andric auto MIB = BuildMI(MBB, MI, DL, get(Opcode), DestReg); 1209*0b57cec5SDimitry Andric if (RI.hasAGPRs(RC)) { 1210*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1211*0b57cec5SDimitry Andric unsigned Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 1212*0b57cec5SDimitry Andric MIB.addReg(Tmp, RegState::Define); 1213*0b57cec5SDimitry Andric } 1214*0b57cec5SDimitry Andric MIB.addFrameIndex(FrameIndex) // vaddr 1215*0b57cec5SDimitry Andric .addReg(MFI->getScratchRSrcReg()) // scratch_rsrc 1216*0b57cec5SDimitry Andric .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset 1217*0b57cec5SDimitry Andric .addImm(0) // offset 1218*0b57cec5SDimitry Andric .addMemOperand(MMO); 1219*0b57cec5SDimitry Andric } 1220*0b57cec5SDimitry Andric 1221*0b57cec5SDimitry Andric /// \param @Offset Offset in bytes of the FrameIndex being spilled 1222*0b57cec5SDimitry Andric unsigned SIInstrInfo::calculateLDSSpillAddress( 1223*0b57cec5SDimitry Andric MachineBasicBlock &MBB, MachineInstr &MI, RegScavenger *RS, unsigned TmpReg, 1224*0b57cec5SDimitry Andric unsigned FrameOffset, unsigned Size) const { 1225*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1226*0b57cec5SDimitry Andric SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 1227*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>(); 1228*0b57cec5SDimitry Andric const DebugLoc &DL = MBB.findDebugLoc(MI); 1229*0b57cec5SDimitry Andric unsigned WorkGroupSize = MFI->getMaxFlatWorkGroupSize(); 1230*0b57cec5SDimitry Andric unsigned WavefrontSize = ST.getWavefrontSize(); 1231*0b57cec5SDimitry Andric 1232*0b57cec5SDimitry Andric unsigned TIDReg = MFI->getTIDReg(); 1233*0b57cec5SDimitry Andric if (!MFI->hasCalculatedTID()) { 1234*0b57cec5SDimitry Andric MachineBasicBlock &Entry = MBB.getParent()->front(); 1235*0b57cec5SDimitry Andric MachineBasicBlock::iterator Insert = Entry.front(); 1236*0b57cec5SDimitry Andric const DebugLoc &DL = Insert->getDebugLoc(); 1237*0b57cec5SDimitry Andric 1238*0b57cec5SDimitry Andric TIDReg = RI.findUnusedRegister(MF->getRegInfo(), &AMDGPU::VGPR_32RegClass, 1239*0b57cec5SDimitry Andric *MF); 1240*0b57cec5SDimitry Andric if (TIDReg == AMDGPU::NoRegister) 1241*0b57cec5SDimitry Andric return TIDReg; 1242*0b57cec5SDimitry Andric 1243*0b57cec5SDimitry Andric if (!AMDGPU::isShader(MF->getFunction().getCallingConv()) && 1244*0b57cec5SDimitry Andric WorkGroupSize > WavefrontSize) { 1245*0b57cec5SDimitry Andric unsigned TIDIGXReg 1246*0b57cec5SDimitry Andric = MFI->getPreloadedReg(AMDGPUFunctionArgInfo::WORKGROUP_ID_X); 1247*0b57cec5SDimitry Andric unsigned TIDIGYReg 1248*0b57cec5SDimitry Andric = MFI->getPreloadedReg(AMDGPUFunctionArgInfo::WORKGROUP_ID_Y); 1249*0b57cec5SDimitry Andric unsigned TIDIGZReg 1250*0b57cec5SDimitry Andric = MFI->getPreloadedReg(AMDGPUFunctionArgInfo::WORKGROUP_ID_Z); 1251*0b57cec5SDimitry Andric unsigned InputPtrReg = 1252*0b57cec5SDimitry Andric MFI->getPreloadedReg(AMDGPUFunctionArgInfo::KERNARG_SEGMENT_PTR); 1253*0b57cec5SDimitry Andric for (unsigned Reg : {TIDIGXReg, TIDIGYReg, TIDIGZReg}) { 1254*0b57cec5SDimitry Andric if (!Entry.isLiveIn(Reg)) 1255*0b57cec5SDimitry Andric Entry.addLiveIn(Reg); 1256*0b57cec5SDimitry Andric } 1257*0b57cec5SDimitry Andric 1258*0b57cec5SDimitry Andric RS->enterBasicBlock(Entry); 1259*0b57cec5SDimitry Andric // FIXME: Can we scavenge an SReg_64 and access the subregs? 1260*0b57cec5SDimitry Andric unsigned STmp0 = RS->scavengeRegister(&AMDGPU::SGPR_32RegClass, 0); 1261*0b57cec5SDimitry Andric unsigned STmp1 = RS->scavengeRegister(&AMDGPU::SGPR_32RegClass, 0); 1262*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::S_LOAD_DWORD_IMM), STmp0) 1263*0b57cec5SDimitry Andric .addReg(InputPtrReg) 1264*0b57cec5SDimitry Andric .addImm(SI::KernelInputOffsets::NGROUPS_Z); 1265*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::S_LOAD_DWORD_IMM), STmp1) 1266*0b57cec5SDimitry Andric .addReg(InputPtrReg) 1267*0b57cec5SDimitry Andric .addImm(SI::KernelInputOffsets::NGROUPS_Y); 1268*0b57cec5SDimitry Andric 1269*0b57cec5SDimitry Andric // NGROUPS.X * NGROUPS.Y 1270*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::S_MUL_I32), STmp1) 1271*0b57cec5SDimitry Andric .addReg(STmp1) 1272*0b57cec5SDimitry Andric .addReg(STmp0); 1273*0b57cec5SDimitry Andric // (NGROUPS.X * NGROUPS.Y) * TIDIG.X 1274*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::V_MUL_U32_U24_e32), TIDReg) 1275*0b57cec5SDimitry Andric .addReg(STmp1) 1276*0b57cec5SDimitry Andric .addReg(TIDIGXReg); 1277*0b57cec5SDimitry Andric // NGROUPS.Z * TIDIG.Y + (NGROUPS.X * NGROPUS.Y * TIDIG.X) 1278*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::V_MAD_U32_U24), TIDReg) 1279*0b57cec5SDimitry Andric .addReg(STmp0) 1280*0b57cec5SDimitry Andric .addReg(TIDIGYReg) 1281*0b57cec5SDimitry Andric .addReg(TIDReg); 1282*0b57cec5SDimitry Andric // (NGROUPS.Z * TIDIG.Y + (NGROUPS.X * NGROPUS.Y * TIDIG.X)) + TIDIG.Z 1283*0b57cec5SDimitry Andric getAddNoCarry(Entry, Insert, DL, TIDReg) 1284*0b57cec5SDimitry Andric .addReg(TIDReg) 1285*0b57cec5SDimitry Andric .addReg(TIDIGZReg) 1286*0b57cec5SDimitry Andric .addImm(0); // clamp bit 1287*0b57cec5SDimitry Andric } else { 1288*0b57cec5SDimitry Andric // Get the wave id 1289*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::V_MBCNT_LO_U32_B32_e64), 1290*0b57cec5SDimitry Andric TIDReg) 1291*0b57cec5SDimitry Andric .addImm(-1) 1292*0b57cec5SDimitry Andric .addImm(0); 1293*0b57cec5SDimitry Andric 1294*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::V_MBCNT_HI_U32_B32_e64), 1295*0b57cec5SDimitry Andric TIDReg) 1296*0b57cec5SDimitry Andric .addImm(-1) 1297*0b57cec5SDimitry Andric .addReg(TIDReg); 1298*0b57cec5SDimitry Andric } 1299*0b57cec5SDimitry Andric 1300*0b57cec5SDimitry Andric BuildMI(Entry, Insert, DL, get(AMDGPU::V_LSHLREV_B32_e32), 1301*0b57cec5SDimitry Andric TIDReg) 1302*0b57cec5SDimitry Andric .addImm(2) 1303*0b57cec5SDimitry Andric .addReg(TIDReg); 1304*0b57cec5SDimitry Andric MFI->setTIDReg(TIDReg); 1305*0b57cec5SDimitry Andric } 1306*0b57cec5SDimitry Andric 1307*0b57cec5SDimitry Andric // Add FrameIndex to LDS offset 1308*0b57cec5SDimitry Andric unsigned LDSOffset = MFI->getLDSSize() + (FrameOffset * WorkGroupSize); 1309*0b57cec5SDimitry Andric getAddNoCarry(MBB, MI, DL, TmpReg) 1310*0b57cec5SDimitry Andric .addImm(LDSOffset) 1311*0b57cec5SDimitry Andric .addReg(TIDReg) 1312*0b57cec5SDimitry Andric .addImm(0); // clamp bit 1313*0b57cec5SDimitry Andric 1314*0b57cec5SDimitry Andric return TmpReg; 1315*0b57cec5SDimitry Andric } 1316*0b57cec5SDimitry Andric 1317*0b57cec5SDimitry Andric void SIInstrInfo::insertWaitStates(MachineBasicBlock &MBB, 1318*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 1319*0b57cec5SDimitry Andric int Count) const { 1320*0b57cec5SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 1321*0b57cec5SDimitry Andric while (Count > 0) { 1322*0b57cec5SDimitry Andric int Arg; 1323*0b57cec5SDimitry Andric if (Count >= 8) 1324*0b57cec5SDimitry Andric Arg = 7; 1325*0b57cec5SDimitry Andric else 1326*0b57cec5SDimitry Andric Arg = Count - 1; 1327*0b57cec5SDimitry Andric Count -= 8; 1328*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)) 1329*0b57cec5SDimitry Andric .addImm(Arg); 1330*0b57cec5SDimitry Andric } 1331*0b57cec5SDimitry Andric } 1332*0b57cec5SDimitry Andric 1333*0b57cec5SDimitry Andric void SIInstrInfo::insertNoop(MachineBasicBlock &MBB, 1334*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const { 1335*0b57cec5SDimitry Andric insertWaitStates(MBB, MI, 1); 1336*0b57cec5SDimitry Andric } 1337*0b57cec5SDimitry Andric 1338*0b57cec5SDimitry Andric void SIInstrInfo::insertReturn(MachineBasicBlock &MBB) const { 1339*0b57cec5SDimitry Andric auto MF = MBB.getParent(); 1340*0b57cec5SDimitry Andric SIMachineFunctionInfo *Info = MF->getInfo<SIMachineFunctionInfo>(); 1341*0b57cec5SDimitry Andric 1342*0b57cec5SDimitry Andric assert(Info->isEntryFunction()); 1343*0b57cec5SDimitry Andric 1344*0b57cec5SDimitry Andric if (MBB.succ_empty()) { 1345*0b57cec5SDimitry Andric bool HasNoTerminator = MBB.getFirstTerminator() == MBB.end(); 1346*0b57cec5SDimitry Andric if (HasNoTerminator) { 1347*0b57cec5SDimitry Andric if (Info->returnsVoid()) { 1348*0b57cec5SDimitry Andric BuildMI(MBB, MBB.end(), DebugLoc(), get(AMDGPU::S_ENDPGM)).addImm(0); 1349*0b57cec5SDimitry Andric } else { 1350*0b57cec5SDimitry Andric BuildMI(MBB, MBB.end(), DebugLoc(), get(AMDGPU::SI_RETURN_TO_EPILOG)); 1351*0b57cec5SDimitry Andric } 1352*0b57cec5SDimitry Andric } 1353*0b57cec5SDimitry Andric } 1354*0b57cec5SDimitry Andric } 1355*0b57cec5SDimitry Andric 1356*0b57cec5SDimitry Andric unsigned SIInstrInfo::getNumWaitStates(const MachineInstr &MI) { 1357*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 1358*0b57cec5SDimitry Andric default: return 1; // FIXME: Do wait states equal cycles? 1359*0b57cec5SDimitry Andric 1360*0b57cec5SDimitry Andric case AMDGPU::S_NOP: 1361*0b57cec5SDimitry Andric return MI.getOperand(0).getImm() + 1; 1362*0b57cec5SDimitry Andric } 1363*0b57cec5SDimitry Andric } 1364*0b57cec5SDimitry Andric 1365*0b57cec5SDimitry Andric bool SIInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 1366*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 1367*0b57cec5SDimitry Andric DebugLoc DL = MBB.findDebugLoc(MI); 1368*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 1369*0b57cec5SDimitry Andric default: return TargetInstrInfo::expandPostRAPseudo(MI); 1370*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B64_term: 1371*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1372*0b57cec5SDimitry Andric // register allocation. 1373*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_MOV_B64)); 1374*0b57cec5SDimitry Andric break; 1375*0b57cec5SDimitry Andric 1376*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B32_term: 1377*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1378*0b57cec5SDimitry Andric // register allocation. 1379*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_MOV_B32)); 1380*0b57cec5SDimitry Andric break; 1381*0b57cec5SDimitry Andric 1382*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B64_term: 1383*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1384*0b57cec5SDimitry Andric // register allocation. 1385*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_XOR_B64)); 1386*0b57cec5SDimitry Andric break; 1387*0b57cec5SDimitry Andric 1388*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B32_term: 1389*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1390*0b57cec5SDimitry Andric // register allocation. 1391*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_XOR_B32)); 1392*0b57cec5SDimitry Andric break; 1393*0b57cec5SDimitry Andric 1394*0b57cec5SDimitry Andric case AMDGPU::S_OR_B32_term: 1395*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1396*0b57cec5SDimitry Andric // register allocation. 1397*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_OR_B32)); 1398*0b57cec5SDimitry Andric break; 1399*0b57cec5SDimitry Andric 1400*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B64_term: 1401*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1402*0b57cec5SDimitry Andric // register allocation. 1403*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_ANDN2_B64)); 1404*0b57cec5SDimitry Andric break; 1405*0b57cec5SDimitry Andric 1406*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B32_term: 1407*0b57cec5SDimitry Andric // This is only a terminator to get the correct spill code placement during 1408*0b57cec5SDimitry Andric // register allocation. 1409*0b57cec5SDimitry Andric MI.setDesc(get(AMDGPU::S_ANDN2_B32)); 1410*0b57cec5SDimitry Andric break; 1411*0b57cec5SDimitry Andric 1412*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B64_PSEUDO: { 1413*0b57cec5SDimitry Andric unsigned Dst = MI.getOperand(0).getReg(); 1414*0b57cec5SDimitry Andric unsigned DstLo = RI.getSubReg(Dst, AMDGPU::sub0); 1415*0b57cec5SDimitry Andric unsigned DstHi = RI.getSubReg(Dst, AMDGPU::sub1); 1416*0b57cec5SDimitry Andric 1417*0b57cec5SDimitry Andric const MachineOperand &SrcOp = MI.getOperand(1); 1418*0b57cec5SDimitry Andric // FIXME: Will this work for 64-bit floating point immediates? 1419*0b57cec5SDimitry Andric assert(!SrcOp.isFPImm()); 1420*0b57cec5SDimitry Andric if (SrcOp.isImm()) { 1421*0b57cec5SDimitry Andric APInt Imm(64, SrcOp.getImm()); 1422*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo) 1423*0b57cec5SDimitry Andric .addImm(Imm.getLoBits(32).getZExtValue()) 1424*0b57cec5SDimitry Andric .addReg(Dst, RegState::Implicit | RegState::Define); 1425*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi) 1426*0b57cec5SDimitry Andric .addImm(Imm.getHiBits(32).getZExtValue()) 1427*0b57cec5SDimitry Andric .addReg(Dst, RegState::Implicit | RegState::Define); 1428*0b57cec5SDimitry Andric } else { 1429*0b57cec5SDimitry Andric assert(SrcOp.isReg()); 1430*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo) 1431*0b57cec5SDimitry Andric .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0)) 1432*0b57cec5SDimitry Andric .addReg(Dst, RegState::Implicit | RegState::Define); 1433*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi) 1434*0b57cec5SDimitry Andric .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1)) 1435*0b57cec5SDimitry Andric .addReg(Dst, RegState::Implicit | RegState::Define); 1436*0b57cec5SDimitry Andric } 1437*0b57cec5SDimitry Andric MI.eraseFromParent(); 1438*0b57cec5SDimitry Andric break; 1439*0b57cec5SDimitry Andric } 1440*0b57cec5SDimitry Andric case AMDGPU::V_SET_INACTIVE_B32: { 1441*0b57cec5SDimitry Andric unsigned NotOpc = ST.isWave32() ? AMDGPU::S_NOT_B32 : AMDGPU::S_NOT_B64; 1442*0b57cec5SDimitry Andric unsigned Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC; 1443*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(NotOpc), Exec) 1444*0b57cec5SDimitry Andric .addReg(Exec); 1445*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), MI.getOperand(0).getReg()) 1446*0b57cec5SDimitry Andric .add(MI.getOperand(2)); 1447*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(NotOpc), Exec) 1448*0b57cec5SDimitry Andric .addReg(Exec); 1449*0b57cec5SDimitry Andric MI.eraseFromParent(); 1450*0b57cec5SDimitry Andric break; 1451*0b57cec5SDimitry Andric } 1452*0b57cec5SDimitry Andric case AMDGPU::V_SET_INACTIVE_B64: { 1453*0b57cec5SDimitry Andric unsigned NotOpc = ST.isWave32() ? AMDGPU::S_NOT_B32 : AMDGPU::S_NOT_B64; 1454*0b57cec5SDimitry Andric unsigned Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC; 1455*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(NotOpc), Exec) 1456*0b57cec5SDimitry Andric .addReg(Exec); 1457*0b57cec5SDimitry Andric MachineInstr *Copy = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_PSEUDO), 1458*0b57cec5SDimitry Andric MI.getOperand(0).getReg()) 1459*0b57cec5SDimitry Andric .add(MI.getOperand(2)); 1460*0b57cec5SDimitry Andric expandPostRAPseudo(*Copy); 1461*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(NotOpc), Exec) 1462*0b57cec5SDimitry Andric .addReg(Exec); 1463*0b57cec5SDimitry Andric MI.eraseFromParent(); 1464*0b57cec5SDimitry Andric break; 1465*0b57cec5SDimitry Andric } 1466*0b57cec5SDimitry Andric case AMDGPU::V_MOVRELD_B32_V1: 1467*0b57cec5SDimitry Andric case AMDGPU::V_MOVRELD_B32_V2: 1468*0b57cec5SDimitry Andric case AMDGPU::V_MOVRELD_B32_V4: 1469*0b57cec5SDimitry Andric case AMDGPU::V_MOVRELD_B32_V8: 1470*0b57cec5SDimitry Andric case AMDGPU::V_MOVRELD_B32_V16: { 1471*0b57cec5SDimitry Andric const MCInstrDesc &MovRelDesc = get(AMDGPU::V_MOVRELD_B32_e32); 1472*0b57cec5SDimitry Andric unsigned VecReg = MI.getOperand(0).getReg(); 1473*0b57cec5SDimitry Andric bool IsUndef = MI.getOperand(1).isUndef(); 1474*0b57cec5SDimitry Andric unsigned SubReg = AMDGPU::sub0 + MI.getOperand(3).getImm(); 1475*0b57cec5SDimitry Andric assert(VecReg == MI.getOperand(1).getReg()); 1476*0b57cec5SDimitry Andric 1477*0b57cec5SDimitry Andric MachineInstr *MovRel = 1478*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, MovRelDesc) 1479*0b57cec5SDimitry Andric .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef) 1480*0b57cec5SDimitry Andric .add(MI.getOperand(2)) 1481*0b57cec5SDimitry Andric .addReg(VecReg, RegState::ImplicitDefine) 1482*0b57cec5SDimitry Andric .addReg(VecReg, 1483*0b57cec5SDimitry Andric RegState::Implicit | (IsUndef ? RegState::Undef : 0)); 1484*0b57cec5SDimitry Andric 1485*0b57cec5SDimitry Andric const int ImpDefIdx = 1486*0b57cec5SDimitry Andric MovRelDesc.getNumOperands() + MovRelDesc.getNumImplicitUses(); 1487*0b57cec5SDimitry Andric const int ImpUseIdx = ImpDefIdx + 1; 1488*0b57cec5SDimitry Andric MovRel->tieOperands(ImpDefIdx, ImpUseIdx); 1489*0b57cec5SDimitry Andric 1490*0b57cec5SDimitry Andric MI.eraseFromParent(); 1491*0b57cec5SDimitry Andric break; 1492*0b57cec5SDimitry Andric } 1493*0b57cec5SDimitry Andric case AMDGPU::SI_PC_ADD_REL_OFFSET: { 1494*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 1495*0b57cec5SDimitry Andric unsigned Reg = MI.getOperand(0).getReg(); 1496*0b57cec5SDimitry Andric unsigned RegLo = RI.getSubReg(Reg, AMDGPU::sub0); 1497*0b57cec5SDimitry Andric unsigned RegHi = RI.getSubReg(Reg, AMDGPU::sub1); 1498*0b57cec5SDimitry Andric 1499*0b57cec5SDimitry Andric // Create a bundle so these instructions won't be re-ordered by the 1500*0b57cec5SDimitry Andric // post-RA scheduler. 1501*0b57cec5SDimitry Andric MIBundleBuilder Bundler(MBB, MI); 1502*0b57cec5SDimitry Andric Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg)); 1503*0b57cec5SDimitry Andric 1504*0b57cec5SDimitry Andric // Add 32-bit offset from this instruction to the start of the 1505*0b57cec5SDimitry Andric // constant data. 1506*0b57cec5SDimitry Andric Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo) 1507*0b57cec5SDimitry Andric .addReg(RegLo) 1508*0b57cec5SDimitry Andric .add(MI.getOperand(1))); 1509*0b57cec5SDimitry Andric 1510*0b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi) 1511*0b57cec5SDimitry Andric .addReg(RegHi); 1512*0b57cec5SDimitry Andric MIB.add(MI.getOperand(2)); 1513*0b57cec5SDimitry Andric 1514*0b57cec5SDimitry Andric Bundler.append(MIB); 1515*0b57cec5SDimitry Andric finalizeBundle(MBB, Bundler.begin()); 1516*0b57cec5SDimitry Andric 1517*0b57cec5SDimitry Andric MI.eraseFromParent(); 1518*0b57cec5SDimitry Andric break; 1519*0b57cec5SDimitry Andric } 1520*0b57cec5SDimitry Andric case AMDGPU::ENTER_WWM: { 1521*0b57cec5SDimitry Andric // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when 1522*0b57cec5SDimitry Andric // WWM is entered. 1523*0b57cec5SDimitry Andric MI.setDesc(get(ST.isWave32() ? AMDGPU::S_OR_SAVEEXEC_B32 1524*0b57cec5SDimitry Andric : AMDGPU::S_OR_SAVEEXEC_B64)); 1525*0b57cec5SDimitry Andric break; 1526*0b57cec5SDimitry Andric } 1527*0b57cec5SDimitry Andric case AMDGPU::EXIT_WWM: { 1528*0b57cec5SDimitry Andric // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when 1529*0b57cec5SDimitry Andric // WWM is exited. 1530*0b57cec5SDimitry Andric MI.setDesc(get(ST.isWave32() ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64)); 1531*0b57cec5SDimitry Andric break; 1532*0b57cec5SDimitry Andric } 1533*0b57cec5SDimitry Andric case TargetOpcode::BUNDLE: { 1534*0b57cec5SDimitry Andric if (!MI.mayLoad()) 1535*0b57cec5SDimitry Andric return false; 1536*0b57cec5SDimitry Andric 1537*0b57cec5SDimitry Andric // If it is a load it must be a memory clause 1538*0b57cec5SDimitry Andric for (MachineBasicBlock::instr_iterator I = MI.getIterator(); 1539*0b57cec5SDimitry Andric I->isBundledWithSucc(); ++I) { 1540*0b57cec5SDimitry Andric I->unbundleFromSucc(); 1541*0b57cec5SDimitry Andric for (MachineOperand &MO : I->operands()) 1542*0b57cec5SDimitry Andric if (MO.isReg()) 1543*0b57cec5SDimitry Andric MO.setIsInternalRead(false); 1544*0b57cec5SDimitry Andric } 1545*0b57cec5SDimitry Andric 1546*0b57cec5SDimitry Andric MI.eraseFromParent(); 1547*0b57cec5SDimitry Andric break; 1548*0b57cec5SDimitry Andric } 1549*0b57cec5SDimitry Andric } 1550*0b57cec5SDimitry Andric return true; 1551*0b57cec5SDimitry Andric } 1552*0b57cec5SDimitry Andric 1553*0b57cec5SDimitry Andric bool SIInstrInfo::swapSourceModifiers(MachineInstr &MI, 1554*0b57cec5SDimitry Andric MachineOperand &Src0, 1555*0b57cec5SDimitry Andric unsigned Src0OpName, 1556*0b57cec5SDimitry Andric MachineOperand &Src1, 1557*0b57cec5SDimitry Andric unsigned Src1OpName) const { 1558*0b57cec5SDimitry Andric MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName); 1559*0b57cec5SDimitry Andric if (!Src0Mods) 1560*0b57cec5SDimitry Andric return false; 1561*0b57cec5SDimitry Andric 1562*0b57cec5SDimitry Andric MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName); 1563*0b57cec5SDimitry Andric assert(Src1Mods && 1564*0b57cec5SDimitry Andric "All commutable instructions have both src0 and src1 modifiers"); 1565*0b57cec5SDimitry Andric 1566*0b57cec5SDimitry Andric int Src0ModsVal = Src0Mods->getImm(); 1567*0b57cec5SDimitry Andric int Src1ModsVal = Src1Mods->getImm(); 1568*0b57cec5SDimitry Andric 1569*0b57cec5SDimitry Andric Src1Mods->setImm(Src0ModsVal); 1570*0b57cec5SDimitry Andric Src0Mods->setImm(Src1ModsVal); 1571*0b57cec5SDimitry Andric return true; 1572*0b57cec5SDimitry Andric } 1573*0b57cec5SDimitry Andric 1574*0b57cec5SDimitry Andric static MachineInstr *swapRegAndNonRegOperand(MachineInstr &MI, 1575*0b57cec5SDimitry Andric MachineOperand &RegOp, 1576*0b57cec5SDimitry Andric MachineOperand &NonRegOp) { 1577*0b57cec5SDimitry Andric unsigned Reg = RegOp.getReg(); 1578*0b57cec5SDimitry Andric unsigned SubReg = RegOp.getSubReg(); 1579*0b57cec5SDimitry Andric bool IsKill = RegOp.isKill(); 1580*0b57cec5SDimitry Andric bool IsDead = RegOp.isDead(); 1581*0b57cec5SDimitry Andric bool IsUndef = RegOp.isUndef(); 1582*0b57cec5SDimitry Andric bool IsDebug = RegOp.isDebug(); 1583*0b57cec5SDimitry Andric 1584*0b57cec5SDimitry Andric if (NonRegOp.isImm()) 1585*0b57cec5SDimitry Andric RegOp.ChangeToImmediate(NonRegOp.getImm()); 1586*0b57cec5SDimitry Andric else if (NonRegOp.isFI()) 1587*0b57cec5SDimitry Andric RegOp.ChangeToFrameIndex(NonRegOp.getIndex()); 1588*0b57cec5SDimitry Andric else 1589*0b57cec5SDimitry Andric return nullptr; 1590*0b57cec5SDimitry Andric 1591*0b57cec5SDimitry Andric NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug); 1592*0b57cec5SDimitry Andric NonRegOp.setSubReg(SubReg); 1593*0b57cec5SDimitry Andric 1594*0b57cec5SDimitry Andric return &MI; 1595*0b57cec5SDimitry Andric } 1596*0b57cec5SDimitry Andric 1597*0b57cec5SDimitry Andric MachineInstr *SIInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, 1598*0b57cec5SDimitry Andric unsigned Src0Idx, 1599*0b57cec5SDimitry Andric unsigned Src1Idx) const { 1600*0b57cec5SDimitry Andric assert(!NewMI && "this should never be used"); 1601*0b57cec5SDimitry Andric 1602*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 1603*0b57cec5SDimitry Andric int CommutedOpcode = commuteOpcode(Opc); 1604*0b57cec5SDimitry Andric if (CommutedOpcode == -1) 1605*0b57cec5SDimitry Andric return nullptr; 1606*0b57cec5SDimitry Andric 1607*0b57cec5SDimitry Andric assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) == 1608*0b57cec5SDimitry Andric static_cast<int>(Src0Idx) && 1609*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) == 1610*0b57cec5SDimitry Andric static_cast<int>(Src1Idx) && 1611*0b57cec5SDimitry Andric "inconsistency with findCommutedOpIndices"); 1612*0b57cec5SDimitry Andric 1613*0b57cec5SDimitry Andric MachineOperand &Src0 = MI.getOperand(Src0Idx); 1614*0b57cec5SDimitry Andric MachineOperand &Src1 = MI.getOperand(Src1Idx); 1615*0b57cec5SDimitry Andric 1616*0b57cec5SDimitry Andric MachineInstr *CommutedMI = nullptr; 1617*0b57cec5SDimitry Andric if (Src0.isReg() && Src1.isReg()) { 1618*0b57cec5SDimitry Andric if (isOperandLegal(MI, Src1Idx, &Src0)) { 1619*0b57cec5SDimitry Andric // Be sure to copy the source modifiers to the right place. 1620*0b57cec5SDimitry Andric CommutedMI 1621*0b57cec5SDimitry Andric = TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx); 1622*0b57cec5SDimitry Andric } 1623*0b57cec5SDimitry Andric 1624*0b57cec5SDimitry Andric } else if (Src0.isReg() && !Src1.isReg()) { 1625*0b57cec5SDimitry Andric // src0 should always be able to support any operand type, so no need to 1626*0b57cec5SDimitry Andric // check operand legality. 1627*0b57cec5SDimitry Andric CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1); 1628*0b57cec5SDimitry Andric } else if (!Src0.isReg() && Src1.isReg()) { 1629*0b57cec5SDimitry Andric if (isOperandLegal(MI, Src1Idx, &Src0)) 1630*0b57cec5SDimitry Andric CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0); 1631*0b57cec5SDimitry Andric } else { 1632*0b57cec5SDimitry Andric // FIXME: Found two non registers to commute. This does happen. 1633*0b57cec5SDimitry Andric return nullptr; 1634*0b57cec5SDimitry Andric } 1635*0b57cec5SDimitry Andric 1636*0b57cec5SDimitry Andric if (CommutedMI) { 1637*0b57cec5SDimitry Andric swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers, 1638*0b57cec5SDimitry Andric Src1, AMDGPU::OpName::src1_modifiers); 1639*0b57cec5SDimitry Andric 1640*0b57cec5SDimitry Andric CommutedMI->setDesc(get(CommutedOpcode)); 1641*0b57cec5SDimitry Andric } 1642*0b57cec5SDimitry Andric 1643*0b57cec5SDimitry Andric return CommutedMI; 1644*0b57cec5SDimitry Andric } 1645*0b57cec5SDimitry Andric 1646*0b57cec5SDimitry Andric // This needs to be implemented because the source modifiers may be inserted 1647*0b57cec5SDimitry Andric // between the true commutable operands, and the base 1648*0b57cec5SDimitry Andric // TargetInstrInfo::commuteInstruction uses it. 1649*0b57cec5SDimitry Andric bool SIInstrInfo::findCommutedOpIndices(MachineInstr &MI, unsigned &SrcOpIdx0, 1650*0b57cec5SDimitry Andric unsigned &SrcOpIdx1) const { 1651*0b57cec5SDimitry Andric return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1); 1652*0b57cec5SDimitry Andric } 1653*0b57cec5SDimitry Andric 1654*0b57cec5SDimitry Andric bool SIInstrInfo::findCommutedOpIndices(MCInstrDesc Desc, unsigned &SrcOpIdx0, 1655*0b57cec5SDimitry Andric unsigned &SrcOpIdx1) const { 1656*0b57cec5SDimitry Andric if (!Desc.isCommutable()) 1657*0b57cec5SDimitry Andric return false; 1658*0b57cec5SDimitry Andric 1659*0b57cec5SDimitry Andric unsigned Opc = Desc.getOpcode(); 1660*0b57cec5SDimitry Andric int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 1661*0b57cec5SDimitry Andric if (Src0Idx == -1) 1662*0b57cec5SDimitry Andric return false; 1663*0b57cec5SDimitry Andric 1664*0b57cec5SDimitry Andric int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1); 1665*0b57cec5SDimitry Andric if (Src1Idx == -1) 1666*0b57cec5SDimitry Andric return false; 1667*0b57cec5SDimitry Andric 1668*0b57cec5SDimitry Andric return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx); 1669*0b57cec5SDimitry Andric } 1670*0b57cec5SDimitry Andric 1671*0b57cec5SDimitry Andric bool SIInstrInfo::isBranchOffsetInRange(unsigned BranchOp, 1672*0b57cec5SDimitry Andric int64_t BrOffset) const { 1673*0b57cec5SDimitry Andric // BranchRelaxation should never have to check s_setpc_b64 because its dest 1674*0b57cec5SDimitry Andric // block is unanalyzable. 1675*0b57cec5SDimitry Andric assert(BranchOp != AMDGPU::S_SETPC_B64); 1676*0b57cec5SDimitry Andric 1677*0b57cec5SDimitry Andric // Convert to dwords. 1678*0b57cec5SDimitry Andric BrOffset /= 4; 1679*0b57cec5SDimitry Andric 1680*0b57cec5SDimitry Andric // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is 1681*0b57cec5SDimitry Andric // from the next instruction. 1682*0b57cec5SDimitry Andric BrOffset -= 1; 1683*0b57cec5SDimitry Andric 1684*0b57cec5SDimitry Andric return isIntN(BranchOffsetBits, BrOffset); 1685*0b57cec5SDimitry Andric } 1686*0b57cec5SDimitry Andric 1687*0b57cec5SDimitry Andric MachineBasicBlock *SIInstrInfo::getBranchDestBlock( 1688*0b57cec5SDimitry Andric const MachineInstr &MI) const { 1689*0b57cec5SDimitry Andric if (MI.getOpcode() == AMDGPU::S_SETPC_B64) { 1690*0b57cec5SDimitry Andric // This would be a difficult analysis to perform, but can always be legal so 1691*0b57cec5SDimitry Andric // there's no need to analyze it. 1692*0b57cec5SDimitry Andric return nullptr; 1693*0b57cec5SDimitry Andric } 1694*0b57cec5SDimitry Andric 1695*0b57cec5SDimitry Andric return MI.getOperand(0).getMBB(); 1696*0b57cec5SDimitry Andric } 1697*0b57cec5SDimitry Andric 1698*0b57cec5SDimitry Andric unsigned SIInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, 1699*0b57cec5SDimitry Andric MachineBasicBlock &DestBB, 1700*0b57cec5SDimitry Andric const DebugLoc &DL, 1701*0b57cec5SDimitry Andric int64_t BrOffset, 1702*0b57cec5SDimitry Andric RegScavenger *RS) const { 1703*0b57cec5SDimitry Andric assert(RS && "RegScavenger required for long branching"); 1704*0b57cec5SDimitry Andric assert(MBB.empty() && 1705*0b57cec5SDimitry Andric "new block should be inserted for expanding unconditional branch"); 1706*0b57cec5SDimitry Andric assert(MBB.pred_size() == 1); 1707*0b57cec5SDimitry Andric 1708*0b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1709*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1710*0b57cec5SDimitry Andric 1711*0b57cec5SDimitry Andric // FIXME: Virtual register workaround for RegScavenger not working with empty 1712*0b57cec5SDimitry Andric // blocks. 1713*0b57cec5SDimitry Andric unsigned PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass); 1714*0b57cec5SDimitry Andric 1715*0b57cec5SDimitry Andric auto I = MBB.end(); 1716*0b57cec5SDimitry Andric 1717*0b57cec5SDimitry Andric // We need to compute the offset relative to the instruction immediately after 1718*0b57cec5SDimitry Andric // s_getpc_b64. Insert pc arithmetic code before last terminator. 1719*0b57cec5SDimitry Andric MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg); 1720*0b57cec5SDimitry Andric 1721*0b57cec5SDimitry Andric // TODO: Handle > 32-bit block address. 1722*0b57cec5SDimitry Andric if (BrOffset >= 0) { 1723*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32)) 1724*0b57cec5SDimitry Andric .addReg(PCReg, RegState::Define, AMDGPU::sub0) 1725*0b57cec5SDimitry Andric .addReg(PCReg, 0, AMDGPU::sub0) 1726*0b57cec5SDimitry Andric .addMBB(&DestBB, MO_LONG_BRANCH_FORWARD); 1727*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32)) 1728*0b57cec5SDimitry Andric .addReg(PCReg, RegState::Define, AMDGPU::sub1) 1729*0b57cec5SDimitry Andric .addReg(PCReg, 0, AMDGPU::sub1) 1730*0b57cec5SDimitry Andric .addImm(0); 1731*0b57cec5SDimitry Andric } else { 1732*0b57cec5SDimitry Andric // Backwards branch. 1733*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::S_SUB_U32)) 1734*0b57cec5SDimitry Andric .addReg(PCReg, RegState::Define, AMDGPU::sub0) 1735*0b57cec5SDimitry Andric .addReg(PCReg, 0, AMDGPU::sub0) 1736*0b57cec5SDimitry Andric .addMBB(&DestBB, MO_LONG_BRANCH_BACKWARD); 1737*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::S_SUBB_U32)) 1738*0b57cec5SDimitry Andric .addReg(PCReg, RegState::Define, AMDGPU::sub1) 1739*0b57cec5SDimitry Andric .addReg(PCReg, 0, AMDGPU::sub1) 1740*0b57cec5SDimitry Andric .addImm(0); 1741*0b57cec5SDimitry Andric } 1742*0b57cec5SDimitry Andric 1743*0b57cec5SDimitry Andric // Insert the indirect branch after the other terminator. 1744*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64)) 1745*0b57cec5SDimitry Andric .addReg(PCReg); 1746*0b57cec5SDimitry Andric 1747*0b57cec5SDimitry Andric // FIXME: If spilling is necessary, this will fail because this scavenger has 1748*0b57cec5SDimitry Andric // no emergency stack slots. It is non-trivial to spill in this situation, 1749*0b57cec5SDimitry Andric // because the restore code needs to be specially placed after the 1750*0b57cec5SDimitry Andric // jump. BranchRelaxation then needs to be made aware of the newly inserted 1751*0b57cec5SDimitry Andric // block. 1752*0b57cec5SDimitry Andric // 1753*0b57cec5SDimitry Andric // If a spill is needed for the pc register pair, we need to insert a spill 1754*0b57cec5SDimitry Andric // restore block right before the destination block, and insert a short branch 1755*0b57cec5SDimitry Andric // into the old destination block's fallthrough predecessor. 1756*0b57cec5SDimitry Andric // e.g.: 1757*0b57cec5SDimitry Andric // 1758*0b57cec5SDimitry Andric // s_cbranch_scc0 skip_long_branch: 1759*0b57cec5SDimitry Andric // 1760*0b57cec5SDimitry Andric // long_branch_bb: 1761*0b57cec5SDimitry Andric // spill s[8:9] 1762*0b57cec5SDimitry Andric // s_getpc_b64 s[8:9] 1763*0b57cec5SDimitry Andric // s_add_u32 s8, s8, restore_bb 1764*0b57cec5SDimitry Andric // s_addc_u32 s9, s9, 0 1765*0b57cec5SDimitry Andric // s_setpc_b64 s[8:9] 1766*0b57cec5SDimitry Andric // 1767*0b57cec5SDimitry Andric // skip_long_branch: 1768*0b57cec5SDimitry Andric // foo; 1769*0b57cec5SDimitry Andric // 1770*0b57cec5SDimitry Andric // ..... 1771*0b57cec5SDimitry Andric // 1772*0b57cec5SDimitry Andric // dest_bb_fallthrough_predecessor: 1773*0b57cec5SDimitry Andric // bar; 1774*0b57cec5SDimitry Andric // s_branch dest_bb 1775*0b57cec5SDimitry Andric // 1776*0b57cec5SDimitry Andric // restore_bb: 1777*0b57cec5SDimitry Andric // restore s[8:9] 1778*0b57cec5SDimitry Andric // fallthrough dest_bb 1779*0b57cec5SDimitry Andric /// 1780*0b57cec5SDimitry Andric // dest_bb: 1781*0b57cec5SDimitry Andric // buzz; 1782*0b57cec5SDimitry Andric 1783*0b57cec5SDimitry Andric RS->enterBasicBlockEnd(MBB); 1784*0b57cec5SDimitry Andric unsigned Scav = RS->scavengeRegisterBackwards( 1785*0b57cec5SDimitry Andric AMDGPU::SReg_64RegClass, 1786*0b57cec5SDimitry Andric MachineBasicBlock::iterator(GetPC), false, 0); 1787*0b57cec5SDimitry Andric MRI.replaceRegWith(PCReg, Scav); 1788*0b57cec5SDimitry Andric MRI.clearVirtRegs(); 1789*0b57cec5SDimitry Andric RS->setRegUsed(Scav); 1790*0b57cec5SDimitry Andric 1791*0b57cec5SDimitry Andric return 4 + 8 + 4 + 4; 1792*0b57cec5SDimitry Andric } 1793*0b57cec5SDimitry Andric 1794*0b57cec5SDimitry Andric unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) { 1795*0b57cec5SDimitry Andric switch (Cond) { 1796*0b57cec5SDimitry Andric case SIInstrInfo::SCC_TRUE: 1797*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_SCC1; 1798*0b57cec5SDimitry Andric case SIInstrInfo::SCC_FALSE: 1799*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_SCC0; 1800*0b57cec5SDimitry Andric case SIInstrInfo::VCCNZ: 1801*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_VCCNZ; 1802*0b57cec5SDimitry Andric case SIInstrInfo::VCCZ: 1803*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_VCCZ; 1804*0b57cec5SDimitry Andric case SIInstrInfo::EXECNZ: 1805*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_EXECNZ; 1806*0b57cec5SDimitry Andric case SIInstrInfo::EXECZ: 1807*0b57cec5SDimitry Andric return AMDGPU::S_CBRANCH_EXECZ; 1808*0b57cec5SDimitry Andric default: 1809*0b57cec5SDimitry Andric llvm_unreachable("invalid branch predicate"); 1810*0b57cec5SDimitry Andric } 1811*0b57cec5SDimitry Andric } 1812*0b57cec5SDimitry Andric 1813*0b57cec5SDimitry Andric SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) { 1814*0b57cec5SDimitry Andric switch (Opcode) { 1815*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC0: 1816*0b57cec5SDimitry Andric return SCC_FALSE; 1817*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC1: 1818*0b57cec5SDimitry Andric return SCC_TRUE; 1819*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_VCCNZ: 1820*0b57cec5SDimitry Andric return VCCNZ; 1821*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_VCCZ: 1822*0b57cec5SDimitry Andric return VCCZ; 1823*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_EXECNZ: 1824*0b57cec5SDimitry Andric return EXECNZ; 1825*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_EXECZ: 1826*0b57cec5SDimitry Andric return EXECZ; 1827*0b57cec5SDimitry Andric default: 1828*0b57cec5SDimitry Andric return INVALID_BR; 1829*0b57cec5SDimitry Andric } 1830*0b57cec5SDimitry Andric } 1831*0b57cec5SDimitry Andric 1832*0b57cec5SDimitry Andric bool SIInstrInfo::analyzeBranchImpl(MachineBasicBlock &MBB, 1833*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 1834*0b57cec5SDimitry Andric MachineBasicBlock *&TBB, 1835*0b57cec5SDimitry Andric MachineBasicBlock *&FBB, 1836*0b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 1837*0b57cec5SDimitry Andric bool AllowModify) const { 1838*0b57cec5SDimitry Andric if (I->getOpcode() == AMDGPU::S_BRANCH) { 1839*0b57cec5SDimitry Andric // Unconditional Branch 1840*0b57cec5SDimitry Andric TBB = I->getOperand(0).getMBB(); 1841*0b57cec5SDimitry Andric return false; 1842*0b57cec5SDimitry Andric } 1843*0b57cec5SDimitry Andric 1844*0b57cec5SDimitry Andric MachineBasicBlock *CondBB = nullptr; 1845*0b57cec5SDimitry Andric 1846*0b57cec5SDimitry Andric if (I->getOpcode() == AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO) { 1847*0b57cec5SDimitry Andric CondBB = I->getOperand(1).getMBB(); 1848*0b57cec5SDimitry Andric Cond.push_back(I->getOperand(0)); 1849*0b57cec5SDimitry Andric } else { 1850*0b57cec5SDimitry Andric BranchPredicate Pred = getBranchPredicate(I->getOpcode()); 1851*0b57cec5SDimitry Andric if (Pred == INVALID_BR) 1852*0b57cec5SDimitry Andric return true; 1853*0b57cec5SDimitry Andric 1854*0b57cec5SDimitry Andric CondBB = I->getOperand(0).getMBB(); 1855*0b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(Pred)); 1856*0b57cec5SDimitry Andric Cond.push_back(I->getOperand(1)); // Save the branch register. 1857*0b57cec5SDimitry Andric } 1858*0b57cec5SDimitry Andric ++I; 1859*0b57cec5SDimitry Andric 1860*0b57cec5SDimitry Andric if (I == MBB.end()) { 1861*0b57cec5SDimitry Andric // Conditional branch followed by fall-through. 1862*0b57cec5SDimitry Andric TBB = CondBB; 1863*0b57cec5SDimitry Andric return false; 1864*0b57cec5SDimitry Andric } 1865*0b57cec5SDimitry Andric 1866*0b57cec5SDimitry Andric if (I->getOpcode() == AMDGPU::S_BRANCH) { 1867*0b57cec5SDimitry Andric TBB = CondBB; 1868*0b57cec5SDimitry Andric FBB = I->getOperand(0).getMBB(); 1869*0b57cec5SDimitry Andric return false; 1870*0b57cec5SDimitry Andric } 1871*0b57cec5SDimitry Andric 1872*0b57cec5SDimitry Andric return true; 1873*0b57cec5SDimitry Andric } 1874*0b57cec5SDimitry Andric 1875*0b57cec5SDimitry Andric bool SIInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 1876*0b57cec5SDimitry Andric MachineBasicBlock *&FBB, 1877*0b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 1878*0b57cec5SDimitry Andric bool AllowModify) const { 1879*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.getFirstTerminator(); 1880*0b57cec5SDimitry Andric auto E = MBB.end(); 1881*0b57cec5SDimitry Andric if (I == E) 1882*0b57cec5SDimitry Andric return false; 1883*0b57cec5SDimitry Andric 1884*0b57cec5SDimitry Andric // Skip over the instructions that are artificially terminators for special 1885*0b57cec5SDimitry Andric // exec management. 1886*0b57cec5SDimitry Andric while (I != E && !I->isBranch() && !I->isReturn() && 1887*0b57cec5SDimitry Andric I->getOpcode() != AMDGPU::SI_MASK_BRANCH) { 1888*0b57cec5SDimitry Andric switch (I->getOpcode()) { 1889*0b57cec5SDimitry Andric case AMDGPU::SI_MASK_BRANCH: 1890*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B64_term: 1891*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B64_term: 1892*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B64_term: 1893*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B32_term: 1894*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B32_term: 1895*0b57cec5SDimitry Andric case AMDGPU::S_OR_B32_term: 1896*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B32_term: 1897*0b57cec5SDimitry Andric break; 1898*0b57cec5SDimitry Andric case AMDGPU::SI_IF: 1899*0b57cec5SDimitry Andric case AMDGPU::SI_ELSE: 1900*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_I1_TERMINATOR: 1901*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR: 1902*0b57cec5SDimitry Andric // FIXME: It's messy that these need to be considered here at all. 1903*0b57cec5SDimitry Andric return true; 1904*0b57cec5SDimitry Andric default: 1905*0b57cec5SDimitry Andric llvm_unreachable("unexpected non-branch terminator inst"); 1906*0b57cec5SDimitry Andric } 1907*0b57cec5SDimitry Andric 1908*0b57cec5SDimitry Andric ++I; 1909*0b57cec5SDimitry Andric } 1910*0b57cec5SDimitry Andric 1911*0b57cec5SDimitry Andric if (I == E) 1912*0b57cec5SDimitry Andric return false; 1913*0b57cec5SDimitry Andric 1914*0b57cec5SDimitry Andric if (I->getOpcode() != AMDGPU::SI_MASK_BRANCH) 1915*0b57cec5SDimitry Andric return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify); 1916*0b57cec5SDimitry Andric 1917*0b57cec5SDimitry Andric ++I; 1918*0b57cec5SDimitry Andric 1919*0b57cec5SDimitry Andric // TODO: Should be able to treat as fallthrough? 1920*0b57cec5SDimitry Andric if (I == MBB.end()) 1921*0b57cec5SDimitry Andric return true; 1922*0b57cec5SDimitry Andric 1923*0b57cec5SDimitry Andric if (analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify)) 1924*0b57cec5SDimitry Andric return true; 1925*0b57cec5SDimitry Andric 1926*0b57cec5SDimitry Andric MachineBasicBlock *MaskBrDest = I->getOperand(0).getMBB(); 1927*0b57cec5SDimitry Andric 1928*0b57cec5SDimitry Andric // Specifically handle the case where the conditional branch is to the same 1929*0b57cec5SDimitry Andric // destination as the mask branch. e.g. 1930*0b57cec5SDimitry Andric // 1931*0b57cec5SDimitry Andric // si_mask_branch BB8 1932*0b57cec5SDimitry Andric // s_cbranch_execz BB8 1933*0b57cec5SDimitry Andric // s_cbranch BB9 1934*0b57cec5SDimitry Andric // 1935*0b57cec5SDimitry Andric // This is required to understand divergent loops which may need the branches 1936*0b57cec5SDimitry Andric // to be relaxed. 1937*0b57cec5SDimitry Andric if (TBB != MaskBrDest || Cond.empty()) 1938*0b57cec5SDimitry Andric return true; 1939*0b57cec5SDimitry Andric 1940*0b57cec5SDimitry Andric auto Pred = Cond[0].getImm(); 1941*0b57cec5SDimitry Andric return (Pred != EXECZ && Pred != EXECNZ); 1942*0b57cec5SDimitry Andric } 1943*0b57cec5SDimitry Andric 1944*0b57cec5SDimitry Andric unsigned SIInstrInfo::removeBranch(MachineBasicBlock &MBB, 1945*0b57cec5SDimitry Andric int *BytesRemoved) const { 1946*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.getFirstTerminator(); 1947*0b57cec5SDimitry Andric 1948*0b57cec5SDimitry Andric unsigned Count = 0; 1949*0b57cec5SDimitry Andric unsigned RemovedSize = 0; 1950*0b57cec5SDimitry Andric while (I != MBB.end()) { 1951*0b57cec5SDimitry Andric MachineBasicBlock::iterator Next = std::next(I); 1952*0b57cec5SDimitry Andric if (I->getOpcode() == AMDGPU::SI_MASK_BRANCH) { 1953*0b57cec5SDimitry Andric I = Next; 1954*0b57cec5SDimitry Andric continue; 1955*0b57cec5SDimitry Andric } 1956*0b57cec5SDimitry Andric 1957*0b57cec5SDimitry Andric RemovedSize += getInstSizeInBytes(*I); 1958*0b57cec5SDimitry Andric I->eraseFromParent(); 1959*0b57cec5SDimitry Andric ++Count; 1960*0b57cec5SDimitry Andric I = Next; 1961*0b57cec5SDimitry Andric } 1962*0b57cec5SDimitry Andric 1963*0b57cec5SDimitry Andric if (BytesRemoved) 1964*0b57cec5SDimitry Andric *BytesRemoved = RemovedSize; 1965*0b57cec5SDimitry Andric 1966*0b57cec5SDimitry Andric return Count; 1967*0b57cec5SDimitry Andric } 1968*0b57cec5SDimitry Andric 1969*0b57cec5SDimitry Andric // Copy the flags onto the implicit condition register operand. 1970*0b57cec5SDimitry Andric static void preserveCondRegFlags(MachineOperand &CondReg, 1971*0b57cec5SDimitry Andric const MachineOperand &OrigCond) { 1972*0b57cec5SDimitry Andric CondReg.setIsUndef(OrigCond.isUndef()); 1973*0b57cec5SDimitry Andric CondReg.setIsKill(OrigCond.isKill()); 1974*0b57cec5SDimitry Andric } 1975*0b57cec5SDimitry Andric 1976*0b57cec5SDimitry Andric unsigned SIInstrInfo::insertBranch(MachineBasicBlock &MBB, 1977*0b57cec5SDimitry Andric MachineBasicBlock *TBB, 1978*0b57cec5SDimitry Andric MachineBasicBlock *FBB, 1979*0b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 1980*0b57cec5SDimitry Andric const DebugLoc &DL, 1981*0b57cec5SDimitry Andric int *BytesAdded) const { 1982*0b57cec5SDimitry Andric if (!FBB && Cond.empty()) { 1983*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH)) 1984*0b57cec5SDimitry Andric .addMBB(TBB); 1985*0b57cec5SDimitry Andric if (BytesAdded) 1986*0b57cec5SDimitry Andric *BytesAdded = 4; 1987*0b57cec5SDimitry Andric return 1; 1988*0b57cec5SDimitry Andric } 1989*0b57cec5SDimitry Andric 1990*0b57cec5SDimitry Andric if(Cond.size() == 1 && Cond[0].isReg()) { 1991*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO)) 1992*0b57cec5SDimitry Andric .add(Cond[0]) 1993*0b57cec5SDimitry Andric .addMBB(TBB); 1994*0b57cec5SDimitry Andric return 1; 1995*0b57cec5SDimitry Andric } 1996*0b57cec5SDimitry Andric 1997*0b57cec5SDimitry Andric assert(TBB && Cond[0].isImm()); 1998*0b57cec5SDimitry Andric 1999*0b57cec5SDimitry Andric unsigned Opcode 2000*0b57cec5SDimitry Andric = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm())); 2001*0b57cec5SDimitry Andric 2002*0b57cec5SDimitry Andric if (!FBB) { 2003*0b57cec5SDimitry Andric Cond[1].isUndef(); 2004*0b57cec5SDimitry Andric MachineInstr *CondBr = 2005*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(Opcode)) 2006*0b57cec5SDimitry Andric .addMBB(TBB); 2007*0b57cec5SDimitry Andric 2008*0b57cec5SDimitry Andric // Copy the flags onto the implicit condition register operand. 2009*0b57cec5SDimitry Andric preserveCondRegFlags(CondBr->getOperand(1), Cond[1]); 2010*0b57cec5SDimitry Andric 2011*0b57cec5SDimitry Andric if (BytesAdded) 2012*0b57cec5SDimitry Andric *BytesAdded = 4; 2013*0b57cec5SDimitry Andric return 1; 2014*0b57cec5SDimitry Andric } 2015*0b57cec5SDimitry Andric 2016*0b57cec5SDimitry Andric assert(TBB && FBB); 2017*0b57cec5SDimitry Andric 2018*0b57cec5SDimitry Andric MachineInstr *CondBr = 2019*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(Opcode)) 2020*0b57cec5SDimitry Andric .addMBB(TBB); 2021*0b57cec5SDimitry Andric BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH)) 2022*0b57cec5SDimitry Andric .addMBB(FBB); 2023*0b57cec5SDimitry Andric 2024*0b57cec5SDimitry Andric MachineOperand &CondReg = CondBr->getOperand(1); 2025*0b57cec5SDimitry Andric CondReg.setIsUndef(Cond[1].isUndef()); 2026*0b57cec5SDimitry Andric CondReg.setIsKill(Cond[1].isKill()); 2027*0b57cec5SDimitry Andric 2028*0b57cec5SDimitry Andric if (BytesAdded) 2029*0b57cec5SDimitry Andric *BytesAdded = 8; 2030*0b57cec5SDimitry Andric 2031*0b57cec5SDimitry Andric return 2; 2032*0b57cec5SDimitry Andric } 2033*0b57cec5SDimitry Andric 2034*0b57cec5SDimitry Andric bool SIInstrInfo::reverseBranchCondition( 2035*0b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const { 2036*0b57cec5SDimitry Andric if (Cond.size() != 2) { 2037*0b57cec5SDimitry Andric return true; 2038*0b57cec5SDimitry Andric } 2039*0b57cec5SDimitry Andric 2040*0b57cec5SDimitry Andric if (Cond[0].isImm()) { 2041*0b57cec5SDimitry Andric Cond[0].setImm(-Cond[0].getImm()); 2042*0b57cec5SDimitry Andric return false; 2043*0b57cec5SDimitry Andric } 2044*0b57cec5SDimitry Andric 2045*0b57cec5SDimitry Andric return true; 2046*0b57cec5SDimitry Andric } 2047*0b57cec5SDimitry Andric 2048*0b57cec5SDimitry Andric bool SIInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, 2049*0b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 2050*0b57cec5SDimitry Andric unsigned TrueReg, unsigned FalseReg, 2051*0b57cec5SDimitry Andric int &CondCycles, 2052*0b57cec5SDimitry Andric int &TrueCycles, int &FalseCycles) const { 2053*0b57cec5SDimitry Andric switch (Cond[0].getImm()) { 2054*0b57cec5SDimitry Andric case VCCNZ: 2055*0b57cec5SDimitry Andric case VCCZ: { 2056*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 2057*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI.getRegClass(TrueReg); 2058*0b57cec5SDimitry Andric assert(MRI.getRegClass(FalseReg) == RC); 2059*0b57cec5SDimitry Andric 2060*0b57cec5SDimitry Andric int NumInsts = AMDGPU::getRegBitWidth(RC->getID()) / 32; 2061*0b57cec5SDimitry Andric CondCycles = TrueCycles = FalseCycles = NumInsts; // ??? 2062*0b57cec5SDimitry Andric 2063*0b57cec5SDimitry Andric // Limit to equal cost for branch vs. N v_cndmask_b32s. 2064*0b57cec5SDimitry Andric return RI.hasVGPRs(RC) && NumInsts <= 6; 2065*0b57cec5SDimitry Andric } 2066*0b57cec5SDimitry Andric case SCC_TRUE: 2067*0b57cec5SDimitry Andric case SCC_FALSE: { 2068*0b57cec5SDimitry Andric // FIXME: We could insert for VGPRs if we could replace the original compare 2069*0b57cec5SDimitry Andric // with a vector one. 2070*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 2071*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MRI.getRegClass(TrueReg); 2072*0b57cec5SDimitry Andric assert(MRI.getRegClass(FalseReg) == RC); 2073*0b57cec5SDimitry Andric 2074*0b57cec5SDimitry Andric int NumInsts = AMDGPU::getRegBitWidth(RC->getID()) / 32; 2075*0b57cec5SDimitry Andric 2076*0b57cec5SDimitry Andric // Multiples of 8 can do s_cselect_b64 2077*0b57cec5SDimitry Andric if (NumInsts % 2 == 0) 2078*0b57cec5SDimitry Andric NumInsts /= 2; 2079*0b57cec5SDimitry Andric 2080*0b57cec5SDimitry Andric CondCycles = TrueCycles = FalseCycles = NumInsts; // ??? 2081*0b57cec5SDimitry Andric return RI.isSGPRClass(RC); 2082*0b57cec5SDimitry Andric } 2083*0b57cec5SDimitry Andric default: 2084*0b57cec5SDimitry Andric return false; 2085*0b57cec5SDimitry Andric } 2086*0b57cec5SDimitry Andric } 2087*0b57cec5SDimitry Andric 2088*0b57cec5SDimitry Andric void SIInstrInfo::insertSelect(MachineBasicBlock &MBB, 2089*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, const DebugLoc &DL, 2090*0b57cec5SDimitry Andric unsigned DstReg, ArrayRef<MachineOperand> Cond, 2091*0b57cec5SDimitry Andric unsigned TrueReg, unsigned FalseReg) const { 2092*0b57cec5SDimitry Andric BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm()); 2093*0b57cec5SDimitry Andric if (Pred == VCCZ || Pred == SCC_FALSE) { 2094*0b57cec5SDimitry Andric Pred = static_cast<BranchPredicate>(-Pred); 2095*0b57cec5SDimitry Andric std::swap(TrueReg, FalseReg); 2096*0b57cec5SDimitry Andric } 2097*0b57cec5SDimitry Andric 2098*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 2099*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg); 2100*0b57cec5SDimitry Andric unsigned DstSize = RI.getRegSizeInBits(*DstRC); 2101*0b57cec5SDimitry Andric 2102*0b57cec5SDimitry Andric if (DstSize == 32) { 2103*0b57cec5SDimitry Andric unsigned SelOp = Pred == SCC_TRUE ? 2104*0b57cec5SDimitry Andric AMDGPU::S_CSELECT_B32 : AMDGPU::V_CNDMASK_B32_e32; 2105*0b57cec5SDimitry Andric 2106*0b57cec5SDimitry Andric // Instruction's operands are backwards from what is expected. 2107*0b57cec5SDimitry Andric MachineInstr *Select = 2108*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(SelOp), DstReg) 2109*0b57cec5SDimitry Andric .addReg(FalseReg) 2110*0b57cec5SDimitry Andric .addReg(TrueReg); 2111*0b57cec5SDimitry Andric 2112*0b57cec5SDimitry Andric preserveCondRegFlags(Select->getOperand(3), Cond[1]); 2113*0b57cec5SDimitry Andric return; 2114*0b57cec5SDimitry Andric } 2115*0b57cec5SDimitry Andric 2116*0b57cec5SDimitry Andric if (DstSize == 64 && Pred == SCC_TRUE) { 2117*0b57cec5SDimitry Andric MachineInstr *Select = 2118*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg) 2119*0b57cec5SDimitry Andric .addReg(FalseReg) 2120*0b57cec5SDimitry Andric .addReg(TrueReg); 2121*0b57cec5SDimitry Andric 2122*0b57cec5SDimitry Andric preserveCondRegFlags(Select->getOperand(3), Cond[1]); 2123*0b57cec5SDimitry Andric return; 2124*0b57cec5SDimitry Andric } 2125*0b57cec5SDimitry Andric 2126*0b57cec5SDimitry Andric static const int16_t Sub0_15[] = { 2127*0b57cec5SDimitry Andric AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 2128*0b57cec5SDimitry Andric AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7, 2129*0b57cec5SDimitry Andric AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11, 2130*0b57cec5SDimitry Andric AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15, 2131*0b57cec5SDimitry Andric }; 2132*0b57cec5SDimitry Andric 2133*0b57cec5SDimitry Andric static const int16_t Sub0_15_64[] = { 2134*0b57cec5SDimitry Andric AMDGPU::sub0_sub1, AMDGPU::sub2_sub3, 2135*0b57cec5SDimitry Andric AMDGPU::sub4_sub5, AMDGPU::sub6_sub7, 2136*0b57cec5SDimitry Andric AMDGPU::sub8_sub9, AMDGPU::sub10_sub11, 2137*0b57cec5SDimitry Andric AMDGPU::sub12_sub13, AMDGPU::sub14_sub15, 2138*0b57cec5SDimitry Andric }; 2139*0b57cec5SDimitry Andric 2140*0b57cec5SDimitry Andric unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32; 2141*0b57cec5SDimitry Andric const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass; 2142*0b57cec5SDimitry Andric const int16_t *SubIndices = Sub0_15; 2143*0b57cec5SDimitry Andric int NElts = DstSize / 32; 2144*0b57cec5SDimitry Andric 2145*0b57cec5SDimitry Andric // 64-bit select is only available for SALU. 2146*0b57cec5SDimitry Andric // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit. 2147*0b57cec5SDimitry Andric if (Pred == SCC_TRUE) { 2148*0b57cec5SDimitry Andric if (NElts % 2) { 2149*0b57cec5SDimitry Andric SelOp = AMDGPU::S_CSELECT_B32; 2150*0b57cec5SDimitry Andric EltRC = &AMDGPU::SGPR_32RegClass; 2151*0b57cec5SDimitry Andric } else { 2152*0b57cec5SDimitry Andric SelOp = AMDGPU::S_CSELECT_B64; 2153*0b57cec5SDimitry Andric EltRC = &AMDGPU::SGPR_64RegClass; 2154*0b57cec5SDimitry Andric SubIndices = Sub0_15_64; 2155*0b57cec5SDimitry Andric NElts /= 2; 2156*0b57cec5SDimitry Andric } 2157*0b57cec5SDimitry Andric } 2158*0b57cec5SDimitry Andric 2159*0b57cec5SDimitry Andric MachineInstrBuilder MIB = BuildMI( 2160*0b57cec5SDimitry Andric MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg); 2161*0b57cec5SDimitry Andric 2162*0b57cec5SDimitry Andric I = MIB->getIterator(); 2163*0b57cec5SDimitry Andric 2164*0b57cec5SDimitry Andric SmallVector<unsigned, 8> Regs; 2165*0b57cec5SDimitry Andric for (int Idx = 0; Idx != NElts; ++Idx) { 2166*0b57cec5SDimitry Andric unsigned DstElt = MRI.createVirtualRegister(EltRC); 2167*0b57cec5SDimitry Andric Regs.push_back(DstElt); 2168*0b57cec5SDimitry Andric 2169*0b57cec5SDimitry Andric unsigned SubIdx = SubIndices[Idx]; 2170*0b57cec5SDimitry Andric 2171*0b57cec5SDimitry Andric MachineInstr *Select = 2172*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(SelOp), DstElt) 2173*0b57cec5SDimitry Andric .addReg(FalseReg, 0, SubIdx) 2174*0b57cec5SDimitry Andric .addReg(TrueReg, 0, SubIdx); 2175*0b57cec5SDimitry Andric preserveCondRegFlags(Select->getOperand(3), Cond[1]); 2176*0b57cec5SDimitry Andric fixImplicitOperands(*Select); 2177*0b57cec5SDimitry Andric 2178*0b57cec5SDimitry Andric MIB.addReg(DstElt) 2179*0b57cec5SDimitry Andric .addImm(SubIdx); 2180*0b57cec5SDimitry Andric } 2181*0b57cec5SDimitry Andric } 2182*0b57cec5SDimitry Andric 2183*0b57cec5SDimitry Andric bool SIInstrInfo::isFoldableCopy(const MachineInstr &MI) const { 2184*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 2185*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e32: 2186*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e64: 2187*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B64_PSEUDO: { 2188*0b57cec5SDimitry Andric // If there are additional implicit register operands, this may be used for 2189*0b57cec5SDimitry Andric // register indexing so the source register operand isn't simply copied. 2190*0b57cec5SDimitry Andric unsigned NumOps = MI.getDesc().getNumOperands() + 2191*0b57cec5SDimitry Andric MI.getDesc().getNumImplicitUses(); 2192*0b57cec5SDimitry Andric 2193*0b57cec5SDimitry Andric return MI.getNumOperands() == NumOps; 2194*0b57cec5SDimitry Andric } 2195*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B32: 2196*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B64: 2197*0b57cec5SDimitry Andric case AMDGPU::COPY: 2198*0b57cec5SDimitry Andric case AMDGPU::V_ACCVGPR_WRITE_B32: 2199*0b57cec5SDimitry Andric case AMDGPU::V_ACCVGPR_READ_B32: 2200*0b57cec5SDimitry Andric return true; 2201*0b57cec5SDimitry Andric default: 2202*0b57cec5SDimitry Andric return false; 2203*0b57cec5SDimitry Andric } 2204*0b57cec5SDimitry Andric } 2205*0b57cec5SDimitry Andric 2206*0b57cec5SDimitry Andric unsigned SIInstrInfo::getAddressSpaceForPseudoSourceKind( 2207*0b57cec5SDimitry Andric unsigned Kind) const { 2208*0b57cec5SDimitry Andric switch(Kind) { 2209*0b57cec5SDimitry Andric case PseudoSourceValue::Stack: 2210*0b57cec5SDimitry Andric case PseudoSourceValue::FixedStack: 2211*0b57cec5SDimitry Andric return AMDGPUAS::PRIVATE_ADDRESS; 2212*0b57cec5SDimitry Andric case PseudoSourceValue::ConstantPool: 2213*0b57cec5SDimitry Andric case PseudoSourceValue::GOT: 2214*0b57cec5SDimitry Andric case PseudoSourceValue::JumpTable: 2215*0b57cec5SDimitry Andric case PseudoSourceValue::GlobalValueCallEntry: 2216*0b57cec5SDimitry Andric case PseudoSourceValue::ExternalSymbolCallEntry: 2217*0b57cec5SDimitry Andric case PseudoSourceValue::TargetCustom: 2218*0b57cec5SDimitry Andric return AMDGPUAS::CONSTANT_ADDRESS; 2219*0b57cec5SDimitry Andric } 2220*0b57cec5SDimitry Andric return AMDGPUAS::FLAT_ADDRESS; 2221*0b57cec5SDimitry Andric } 2222*0b57cec5SDimitry Andric 2223*0b57cec5SDimitry Andric static void removeModOperands(MachineInstr &MI) { 2224*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2225*0b57cec5SDimitry Andric int Src0ModIdx = AMDGPU::getNamedOperandIdx(Opc, 2226*0b57cec5SDimitry Andric AMDGPU::OpName::src0_modifiers); 2227*0b57cec5SDimitry Andric int Src1ModIdx = AMDGPU::getNamedOperandIdx(Opc, 2228*0b57cec5SDimitry Andric AMDGPU::OpName::src1_modifiers); 2229*0b57cec5SDimitry Andric int Src2ModIdx = AMDGPU::getNamedOperandIdx(Opc, 2230*0b57cec5SDimitry Andric AMDGPU::OpName::src2_modifiers); 2231*0b57cec5SDimitry Andric 2232*0b57cec5SDimitry Andric MI.RemoveOperand(Src2ModIdx); 2233*0b57cec5SDimitry Andric MI.RemoveOperand(Src1ModIdx); 2234*0b57cec5SDimitry Andric MI.RemoveOperand(Src0ModIdx); 2235*0b57cec5SDimitry Andric } 2236*0b57cec5SDimitry Andric 2237*0b57cec5SDimitry Andric bool SIInstrInfo::FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, 2238*0b57cec5SDimitry Andric unsigned Reg, MachineRegisterInfo *MRI) const { 2239*0b57cec5SDimitry Andric if (!MRI->hasOneNonDBGUse(Reg)) 2240*0b57cec5SDimitry Andric return false; 2241*0b57cec5SDimitry Andric 2242*0b57cec5SDimitry Andric switch (DefMI.getOpcode()) { 2243*0b57cec5SDimitry Andric default: 2244*0b57cec5SDimitry Andric return false; 2245*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B64: 2246*0b57cec5SDimitry Andric // TODO: We could fold 64-bit immediates, but this get compilicated 2247*0b57cec5SDimitry Andric // when there are sub-registers. 2248*0b57cec5SDimitry Andric return false; 2249*0b57cec5SDimitry Andric 2250*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e32: 2251*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B32: 2252*0b57cec5SDimitry Andric case AMDGPU::V_ACCVGPR_WRITE_B32: 2253*0b57cec5SDimitry Andric break; 2254*0b57cec5SDimitry Andric } 2255*0b57cec5SDimitry Andric 2256*0b57cec5SDimitry Andric const MachineOperand *ImmOp = getNamedOperand(DefMI, AMDGPU::OpName::src0); 2257*0b57cec5SDimitry Andric assert(ImmOp); 2258*0b57cec5SDimitry Andric // FIXME: We could handle FrameIndex values here. 2259*0b57cec5SDimitry Andric if (!ImmOp->isImm()) 2260*0b57cec5SDimitry Andric return false; 2261*0b57cec5SDimitry Andric 2262*0b57cec5SDimitry Andric unsigned Opc = UseMI.getOpcode(); 2263*0b57cec5SDimitry Andric if (Opc == AMDGPU::COPY) { 2264*0b57cec5SDimitry Andric bool isVGPRCopy = RI.isVGPR(*MRI, UseMI.getOperand(0).getReg()); 2265*0b57cec5SDimitry Andric unsigned NewOpc = isVGPRCopy ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32; 2266*0b57cec5SDimitry Andric if (RI.isAGPR(*MRI, UseMI.getOperand(0).getReg())) { 2267*0b57cec5SDimitry Andric if (!isInlineConstant(*ImmOp, AMDGPU::OPERAND_REG_INLINE_AC_INT32)) 2268*0b57cec5SDimitry Andric return false; 2269*0b57cec5SDimitry Andric NewOpc = AMDGPU::V_ACCVGPR_WRITE_B32; 2270*0b57cec5SDimitry Andric } 2271*0b57cec5SDimitry Andric UseMI.setDesc(get(NewOpc)); 2272*0b57cec5SDimitry Andric UseMI.getOperand(1).ChangeToImmediate(ImmOp->getImm()); 2273*0b57cec5SDimitry Andric UseMI.addImplicitDefUseOperands(*UseMI.getParent()->getParent()); 2274*0b57cec5SDimitry Andric return true; 2275*0b57cec5SDimitry Andric } 2276*0b57cec5SDimitry Andric 2277*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_MAD_F32 || Opc == AMDGPU::V_MAC_F32_e64 || 2278*0b57cec5SDimitry Andric Opc == AMDGPU::V_MAD_F16 || Opc == AMDGPU::V_MAC_F16_e64 || 2279*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMA_F32 || Opc == AMDGPU::V_FMAC_F32_e64 || 2280*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMA_F16 || Opc == AMDGPU::V_FMAC_F16_e64) { 2281*0b57cec5SDimitry Andric // Don't fold if we are using source or output modifiers. The new VOP2 2282*0b57cec5SDimitry Andric // instructions don't have them. 2283*0b57cec5SDimitry Andric if (hasAnyModifiersSet(UseMI)) 2284*0b57cec5SDimitry Andric return false; 2285*0b57cec5SDimitry Andric 2286*0b57cec5SDimitry Andric // If this is a free constant, there's no reason to do this. 2287*0b57cec5SDimitry Andric // TODO: We could fold this here instead of letting SIFoldOperands do it 2288*0b57cec5SDimitry Andric // later. 2289*0b57cec5SDimitry Andric MachineOperand *Src0 = getNamedOperand(UseMI, AMDGPU::OpName::src0); 2290*0b57cec5SDimitry Andric 2291*0b57cec5SDimitry Andric // Any src operand can be used for the legality check. 2292*0b57cec5SDimitry Andric if (isInlineConstant(UseMI, *Src0, *ImmOp)) 2293*0b57cec5SDimitry Andric return false; 2294*0b57cec5SDimitry Andric 2295*0b57cec5SDimitry Andric bool IsF32 = Opc == AMDGPU::V_MAD_F32 || Opc == AMDGPU::V_MAC_F32_e64 || 2296*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMA_F32 || Opc == AMDGPU::V_FMAC_F32_e64; 2297*0b57cec5SDimitry Andric bool IsFMA = Opc == AMDGPU::V_FMA_F32 || Opc == AMDGPU::V_FMAC_F32_e64 || 2298*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMA_F16 || Opc == AMDGPU::V_FMAC_F16_e64; 2299*0b57cec5SDimitry Andric MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1); 2300*0b57cec5SDimitry Andric MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2); 2301*0b57cec5SDimitry Andric 2302*0b57cec5SDimitry Andric // Multiplied part is the constant: Use v_madmk_{f16, f32}. 2303*0b57cec5SDimitry Andric // We should only expect these to be on src0 due to canonicalizations. 2304*0b57cec5SDimitry Andric if (Src0->isReg() && Src0->getReg() == Reg) { 2305*0b57cec5SDimitry Andric if (!Src1->isReg() || RI.isSGPRClass(MRI->getRegClass(Src1->getReg()))) 2306*0b57cec5SDimitry Andric return false; 2307*0b57cec5SDimitry Andric 2308*0b57cec5SDimitry Andric if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg()))) 2309*0b57cec5SDimitry Andric return false; 2310*0b57cec5SDimitry Andric 2311*0b57cec5SDimitry Andric unsigned NewOpc = 2312*0b57cec5SDimitry Andric IsFMA ? (IsF32 ? AMDGPU::V_FMAMK_F32 : AMDGPU::V_FMAMK_F16) 2313*0b57cec5SDimitry Andric : (IsF32 ? AMDGPU::V_MADMK_F32 : AMDGPU::V_MADMK_F16); 2314*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) == -1) 2315*0b57cec5SDimitry Andric return false; 2316*0b57cec5SDimitry Andric 2317*0b57cec5SDimitry Andric // We need to swap operands 0 and 1 since madmk constant is at operand 1. 2318*0b57cec5SDimitry Andric 2319*0b57cec5SDimitry Andric const int64_t Imm = ImmOp->getImm(); 2320*0b57cec5SDimitry Andric 2321*0b57cec5SDimitry Andric // FIXME: This would be a lot easier if we could return a new instruction 2322*0b57cec5SDimitry Andric // instead of having to modify in place. 2323*0b57cec5SDimitry Andric 2324*0b57cec5SDimitry Andric // Remove these first since they are at the end. 2325*0b57cec5SDimitry Andric UseMI.RemoveOperand( 2326*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod)); 2327*0b57cec5SDimitry Andric UseMI.RemoveOperand( 2328*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp)); 2329*0b57cec5SDimitry Andric 2330*0b57cec5SDimitry Andric unsigned Src1Reg = Src1->getReg(); 2331*0b57cec5SDimitry Andric unsigned Src1SubReg = Src1->getSubReg(); 2332*0b57cec5SDimitry Andric Src0->setReg(Src1Reg); 2333*0b57cec5SDimitry Andric Src0->setSubReg(Src1SubReg); 2334*0b57cec5SDimitry Andric Src0->setIsKill(Src1->isKill()); 2335*0b57cec5SDimitry Andric 2336*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_MAC_F32_e64 || 2337*0b57cec5SDimitry Andric Opc == AMDGPU::V_MAC_F16_e64 || 2338*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMAC_F32_e64 || 2339*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMAC_F16_e64) 2340*0b57cec5SDimitry Andric UseMI.untieRegOperand( 2341*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)); 2342*0b57cec5SDimitry Andric 2343*0b57cec5SDimitry Andric Src1->ChangeToImmediate(Imm); 2344*0b57cec5SDimitry Andric 2345*0b57cec5SDimitry Andric removeModOperands(UseMI); 2346*0b57cec5SDimitry Andric UseMI.setDesc(get(NewOpc)); 2347*0b57cec5SDimitry Andric 2348*0b57cec5SDimitry Andric bool DeleteDef = MRI->hasOneNonDBGUse(Reg); 2349*0b57cec5SDimitry Andric if (DeleteDef) 2350*0b57cec5SDimitry Andric DefMI.eraseFromParent(); 2351*0b57cec5SDimitry Andric 2352*0b57cec5SDimitry Andric return true; 2353*0b57cec5SDimitry Andric } 2354*0b57cec5SDimitry Andric 2355*0b57cec5SDimitry Andric // Added part is the constant: Use v_madak_{f16, f32}. 2356*0b57cec5SDimitry Andric if (Src2->isReg() && Src2->getReg() == Reg) { 2357*0b57cec5SDimitry Andric // Not allowed to use constant bus for another operand. 2358*0b57cec5SDimitry Andric // We can however allow an inline immediate as src0. 2359*0b57cec5SDimitry Andric bool Src0Inlined = false; 2360*0b57cec5SDimitry Andric if (Src0->isReg()) { 2361*0b57cec5SDimitry Andric // Try to inline constant if possible. 2362*0b57cec5SDimitry Andric // If the Def moves immediate and the use is single 2363*0b57cec5SDimitry Andric // We are saving VGPR here. 2364*0b57cec5SDimitry Andric MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg()); 2365*0b57cec5SDimitry Andric if (Def && Def->isMoveImmediate() && 2366*0b57cec5SDimitry Andric isInlineConstant(Def->getOperand(1)) && 2367*0b57cec5SDimitry Andric MRI->hasOneUse(Src0->getReg())) { 2368*0b57cec5SDimitry Andric Src0->ChangeToImmediate(Def->getOperand(1).getImm()); 2369*0b57cec5SDimitry Andric Src0Inlined = true; 2370*0b57cec5SDimitry Andric } else if ((RI.isPhysicalRegister(Src0->getReg()) && 2371*0b57cec5SDimitry Andric (ST.getConstantBusLimit(Opc) <= 1 && 2372*0b57cec5SDimitry Andric RI.isSGPRClass(RI.getPhysRegClass(Src0->getReg())))) || 2373*0b57cec5SDimitry Andric (RI.isVirtualRegister(Src0->getReg()) && 2374*0b57cec5SDimitry Andric (ST.getConstantBusLimit(Opc) <= 1 && 2375*0b57cec5SDimitry Andric RI.isSGPRClass(MRI->getRegClass(Src0->getReg()))))) 2376*0b57cec5SDimitry Andric return false; 2377*0b57cec5SDimitry Andric // VGPR is okay as Src0 - fallthrough 2378*0b57cec5SDimitry Andric } 2379*0b57cec5SDimitry Andric 2380*0b57cec5SDimitry Andric if (Src1->isReg() && !Src0Inlined ) { 2381*0b57cec5SDimitry Andric // We have one slot for inlinable constant so far - try to fill it 2382*0b57cec5SDimitry Andric MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg()); 2383*0b57cec5SDimitry Andric if (Def && Def->isMoveImmediate() && 2384*0b57cec5SDimitry Andric isInlineConstant(Def->getOperand(1)) && 2385*0b57cec5SDimitry Andric MRI->hasOneUse(Src1->getReg()) && 2386*0b57cec5SDimitry Andric commuteInstruction(UseMI)) { 2387*0b57cec5SDimitry Andric Src0->ChangeToImmediate(Def->getOperand(1).getImm()); 2388*0b57cec5SDimitry Andric } else if ((RI.isPhysicalRegister(Src1->getReg()) && 2389*0b57cec5SDimitry Andric RI.isSGPRClass(RI.getPhysRegClass(Src1->getReg()))) || 2390*0b57cec5SDimitry Andric (RI.isVirtualRegister(Src1->getReg()) && 2391*0b57cec5SDimitry Andric RI.isSGPRClass(MRI->getRegClass(Src1->getReg())))) 2392*0b57cec5SDimitry Andric return false; 2393*0b57cec5SDimitry Andric // VGPR is okay as Src1 - fallthrough 2394*0b57cec5SDimitry Andric } 2395*0b57cec5SDimitry Andric 2396*0b57cec5SDimitry Andric unsigned NewOpc = 2397*0b57cec5SDimitry Andric IsFMA ? (IsF32 ? AMDGPU::V_FMAAK_F32 : AMDGPU::V_FMAAK_F16) 2398*0b57cec5SDimitry Andric : (IsF32 ? AMDGPU::V_MADAK_F32 : AMDGPU::V_MADAK_F16); 2399*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) == -1) 2400*0b57cec5SDimitry Andric return false; 2401*0b57cec5SDimitry Andric 2402*0b57cec5SDimitry Andric const int64_t Imm = ImmOp->getImm(); 2403*0b57cec5SDimitry Andric 2404*0b57cec5SDimitry Andric // FIXME: This would be a lot easier if we could return a new instruction 2405*0b57cec5SDimitry Andric // instead of having to modify in place. 2406*0b57cec5SDimitry Andric 2407*0b57cec5SDimitry Andric // Remove these first since they are at the end. 2408*0b57cec5SDimitry Andric UseMI.RemoveOperand( 2409*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod)); 2410*0b57cec5SDimitry Andric UseMI.RemoveOperand( 2411*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp)); 2412*0b57cec5SDimitry Andric 2413*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_MAC_F32_e64 || 2414*0b57cec5SDimitry Andric Opc == AMDGPU::V_MAC_F16_e64 || 2415*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMAC_F32_e64 || 2416*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMAC_F16_e64) 2417*0b57cec5SDimitry Andric UseMI.untieRegOperand( 2418*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)); 2419*0b57cec5SDimitry Andric 2420*0b57cec5SDimitry Andric // ChangingToImmediate adds Src2 back to the instruction. 2421*0b57cec5SDimitry Andric Src2->ChangeToImmediate(Imm); 2422*0b57cec5SDimitry Andric 2423*0b57cec5SDimitry Andric // These come before src2. 2424*0b57cec5SDimitry Andric removeModOperands(UseMI); 2425*0b57cec5SDimitry Andric UseMI.setDesc(get(NewOpc)); 2426*0b57cec5SDimitry Andric // It might happen that UseMI was commuted 2427*0b57cec5SDimitry Andric // and we now have SGPR as SRC1. If so 2 inlined 2428*0b57cec5SDimitry Andric // constant and SGPR are illegal. 2429*0b57cec5SDimitry Andric legalizeOperands(UseMI); 2430*0b57cec5SDimitry Andric 2431*0b57cec5SDimitry Andric bool DeleteDef = MRI->hasOneNonDBGUse(Reg); 2432*0b57cec5SDimitry Andric if (DeleteDef) 2433*0b57cec5SDimitry Andric DefMI.eraseFromParent(); 2434*0b57cec5SDimitry Andric 2435*0b57cec5SDimitry Andric return true; 2436*0b57cec5SDimitry Andric } 2437*0b57cec5SDimitry Andric } 2438*0b57cec5SDimitry Andric 2439*0b57cec5SDimitry Andric return false; 2440*0b57cec5SDimitry Andric } 2441*0b57cec5SDimitry Andric 2442*0b57cec5SDimitry Andric static bool offsetsDoNotOverlap(int WidthA, int OffsetA, 2443*0b57cec5SDimitry Andric int WidthB, int OffsetB) { 2444*0b57cec5SDimitry Andric int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB; 2445*0b57cec5SDimitry Andric int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA; 2446*0b57cec5SDimitry Andric int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; 2447*0b57cec5SDimitry Andric return LowOffset + LowWidth <= HighOffset; 2448*0b57cec5SDimitry Andric } 2449*0b57cec5SDimitry Andric 2450*0b57cec5SDimitry Andric bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa, 2451*0b57cec5SDimitry Andric const MachineInstr &MIb) const { 2452*0b57cec5SDimitry Andric const MachineOperand *BaseOp0, *BaseOp1; 2453*0b57cec5SDimitry Andric int64_t Offset0, Offset1; 2454*0b57cec5SDimitry Andric 2455*0b57cec5SDimitry Andric if (getMemOperandWithOffset(MIa, BaseOp0, Offset0, &RI) && 2456*0b57cec5SDimitry Andric getMemOperandWithOffset(MIb, BaseOp1, Offset1, &RI)) { 2457*0b57cec5SDimitry Andric if (!BaseOp0->isIdenticalTo(*BaseOp1)) 2458*0b57cec5SDimitry Andric return false; 2459*0b57cec5SDimitry Andric 2460*0b57cec5SDimitry Andric if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) { 2461*0b57cec5SDimitry Andric // FIXME: Handle ds_read2 / ds_write2. 2462*0b57cec5SDimitry Andric return false; 2463*0b57cec5SDimitry Andric } 2464*0b57cec5SDimitry Andric unsigned Width0 = (*MIa.memoperands_begin())->getSize(); 2465*0b57cec5SDimitry Andric unsigned Width1 = (*MIb.memoperands_begin())->getSize(); 2466*0b57cec5SDimitry Andric if (offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1)) { 2467*0b57cec5SDimitry Andric return true; 2468*0b57cec5SDimitry Andric } 2469*0b57cec5SDimitry Andric } 2470*0b57cec5SDimitry Andric 2471*0b57cec5SDimitry Andric return false; 2472*0b57cec5SDimitry Andric } 2473*0b57cec5SDimitry Andric 2474*0b57cec5SDimitry Andric bool SIInstrInfo::areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 2475*0b57cec5SDimitry Andric const MachineInstr &MIb, 2476*0b57cec5SDimitry Andric AliasAnalysis *AA) const { 2477*0b57cec5SDimitry Andric assert((MIa.mayLoad() || MIa.mayStore()) && 2478*0b57cec5SDimitry Andric "MIa must load from or modify a memory location"); 2479*0b57cec5SDimitry Andric assert((MIb.mayLoad() || MIb.mayStore()) && 2480*0b57cec5SDimitry Andric "MIb must load from or modify a memory location"); 2481*0b57cec5SDimitry Andric 2482*0b57cec5SDimitry Andric if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects()) 2483*0b57cec5SDimitry Andric return false; 2484*0b57cec5SDimitry Andric 2485*0b57cec5SDimitry Andric // XXX - Can we relax this between address spaces? 2486*0b57cec5SDimitry Andric if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef()) 2487*0b57cec5SDimitry Andric return false; 2488*0b57cec5SDimitry Andric 2489*0b57cec5SDimitry Andric // TODO: Should we check the address space from the MachineMemOperand? That 2490*0b57cec5SDimitry Andric // would allow us to distinguish objects we know don't alias based on the 2491*0b57cec5SDimitry Andric // underlying address space, even if it was lowered to a different one, 2492*0b57cec5SDimitry Andric // e.g. private accesses lowered to use MUBUF instructions on a scratch 2493*0b57cec5SDimitry Andric // buffer. 2494*0b57cec5SDimitry Andric if (isDS(MIa)) { 2495*0b57cec5SDimitry Andric if (isDS(MIb)) 2496*0b57cec5SDimitry Andric return checkInstOffsetsDoNotOverlap(MIa, MIb); 2497*0b57cec5SDimitry Andric 2498*0b57cec5SDimitry Andric return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb); 2499*0b57cec5SDimitry Andric } 2500*0b57cec5SDimitry Andric 2501*0b57cec5SDimitry Andric if (isMUBUF(MIa) || isMTBUF(MIa)) { 2502*0b57cec5SDimitry Andric if (isMUBUF(MIb) || isMTBUF(MIb)) 2503*0b57cec5SDimitry Andric return checkInstOffsetsDoNotOverlap(MIa, MIb); 2504*0b57cec5SDimitry Andric 2505*0b57cec5SDimitry Andric return !isFLAT(MIb) && !isSMRD(MIb); 2506*0b57cec5SDimitry Andric } 2507*0b57cec5SDimitry Andric 2508*0b57cec5SDimitry Andric if (isSMRD(MIa)) { 2509*0b57cec5SDimitry Andric if (isSMRD(MIb)) 2510*0b57cec5SDimitry Andric return checkInstOffsetsDoNotOverlap(MIa, MIb); 2511*0b57cec5SDimitry Andric 2512*0b57cec5SDimitry Andric return !isFLAT(MIb) && !isMUBUF(MIa) && !isMTBUF(MIa); 2513*0b57cec5SDimitry Andric } 2514*0b57cec5SDimitry Andric 2515*0b57cec5SDimitry Andric if (isFLAT(MIa)) { 2516*0b57cec5SDimitry Andric if (isFLAT(MIb)) 2517*0b57cec5SDimitry Andric return checkInstOffsetsDoNotOverlap(MIa, MIb); 2518*0b57cec5SDimitry Andric 2519*0b57cec5SDimitry Andric return false; 2520*0b57cec5SDimitry Andric } 2521*0b57cec5SDimitry Andric 2522*0b57cec5SDimitry Andric return false; 2523*0b57cec5SDimitry Andric } 2524*0b57cec5SDimitry Andric 2525*0b57cec5SDimitry Andric static int64_t getFoldableImm(const MachineOperand* MO) { 2526*0b57cec5SDimitry Andric if (!MO->isReg()) 2527*0b57cec5SDimitry Andric return false; 2528*0b57cec5SDimitry Andric const MachineFunction *MF = MO->getParent()->getParent()->getParent(); 2529*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF->getRegInfo(); 2530*0b57cec5SDimitry Andric auto Def = MRI.getUniqueVRegDef(MO->getReg()); 2531*0b57cec5SDimitry Andric if (Def && Def->getOpcode() == AMDGPU::V_MOV_B32_e32 && 2532*0b57cec5SDimitry Andric Def->getOperand(1).isImm()) 2533*0b57cec5SDimitry Andric return Def->getOperand(1).getImm(); 2534*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 2535*0b57cec5SDimitry Andric } 2536*0b57cec5SDimitry Andric 2537*0b57cec5SDimitry Andric MachineInstr *SIInstrInfo::convertToThreeAddress(MachineFunction::iterator &MBB, 2538*0b57cec5SDimitry Andric MachineInstr &MI, 2539*0b57cec5SDimitry Andric LiveVariables *LV) const { 2540*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 2541*0b57cec5SDimitry Andric bool IsF16 = false; 2542*0b57cec5SDimitry Andric bool IsFMA = Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F32_e64 || 2543*0b57cec5SDimitry Andric Opc == AMDGPU::V_FMAC_F16_e32 || Opc == AMDGPU::V_FMAC_F16_e64; 2544*0b57cec5SDimitry Andric 2545*0b57cec5SDimitry Andric switch (Opc) { 2546*0b57cec5SDimitry Andric default: 2547*0b57cec5SDimitry Andric return nullptr; 2548*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F16_e64: 2549*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F16_e64: 2550*0b57cec5SDimitry Andric IsF16 = true; 2551*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 2552*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F32_e64: 2553*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F32_e64: 2554*0b57cec5SDimitry Andric break; 2555*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F16_e32: 2556*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F16_e32: 2557*0b57cec5SDimitry Andric IsF16 = true; 2558*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 2559*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F32_e32: 2560*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F32_e32: { 2561*0b57cec5SDimitry Andric int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), 2562*0b57cec5SDimitry Andric AMDGPU::OpName::src0); 2563*0b57cec5SDimitry Andric const MachineOperand *Src0 = &MI.getOperand(Src0Idx); 2564*0b57cec5SDimitry Andric if (!Src0->isReg() && !Src0->isImm()) 2565*0b57cec5SDimitry Andric return nullptr; 2566*0b57cec5SDimitry Andric 2567*0b57cec5SDimitry Andric if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0)) 2568*0b57cec5SDimitry Andric return nullptr; 2569*0b57cec5SDimitry Andric 2570*0b57cec5SDimitry Andric break; 2571*0b57cec5SDimitry Andric } 2572*0b57cec5SDimitry Andric } 2573*0b57cec5SDimitry Andric 2574*0b57cec5SDimitry Andric const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst); 2575*0b57cec5SDimitry Andric const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0); 2576*0b57cec5SDimitry Andric const MachineOperand *Src0Mods = 2577*0b57cec5SDimitry Andric getNamedOperand(MI, AMDGPU::OpName::src0_modifiers); 2578*0b57cec5SDimitry Andric const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1); 2579*0b57cec5SDimitry Andric const MachineOperand *Src1Mods = 2580*0b57cec5SDimitry Andric getNamedOperand(MI, AMDGPU::OpName::src1_modifiers); 2581*0b57cec5SDimitry Andric const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2); 2582*0b57cec5SDimitry Andric const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp); 2583*0b57cec5SDimitry Andric const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod); 2584*0b57cec5SDimitry Andric 2585*0b57cec5SDimitry Andric if (!Src0Mods && !Src1Mods && !Clamp && !Omod && 2586*0b57cec5SDimitry Andric // If we have an SGPR input, we will violate the constant bus restriction. 2587*0b57cec5SDimitry Andric (ST.getConstantBusLimit(Opc) > 1 || 2588*0b57cec5SDimitry Andric !Src0->isReg() || 2589*0b57cec5SDimitry Andric !RI.isSGPRReg(MBB->getParent()->getRegInfo(), Src0->getReg()))) { 2590*0b57cec5SDimitry Andric if (auto Imm = getFoldableImm(Src2)) { 2591*0b57cec5SDimitry Andric unsigned NewOpc = 2592*0b57cec5SDimitry Andric IsFMA ? (IsF16 ? AMDGPU::V_FMAAK_F16 : AMDGPU::V_FMAAK_F32) 2593*0b57cec5SDimitry Andric : (IsF16 ? AMDGPU::V_MADAK_F16 : AMDGPU::V_MADAK_F32); 2594*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) != -1) 2595*0b57cec5SDimitry Andric return BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc)) 2596*0b57cec5SDimitry Andric .add(*Dst) 2597*0b57cec5SDimitry Andric .add(*Src0) 2598*0b57cec5SDimitry Andric .add(*Src1) 2599*0b57cec5SDimitry Andric .addImm(Imm); 2600*0b57cec5SDimitry Andric } 2601*0b57cec5SDimitry Andric unsigned NewOpc = 2602*0b57cec5SDimitry Andric IsFMA ? (IsF16 ? AMDGPU::V_FMAMK_F16 : AMDGPU::V_FMAMK_F32) 2603*0b57cec5SDimitry Andric : (IsF16 ? AMDGPU::V_MADMK_F16 : AMDGPU::V_MADMK_F32); 2604*0b57cec5SDimitry Andric if (auto Imm = getFoldableImm(Src1)) { 2605*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) != -1) 2606*0b57cec5SDimitry Andric return BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc)) 2607*0b57cec5SDimitry Andric .add(*Dst) 2608*0b57cec5SDimitry Andric .add(*Src0) 2609*0b57cec5SDimitry Andric .addImm(Imm) 2610*0b57cec5SDimitry Andric .add(*Src2); 2611*0b57cec5SDimitry Andric } 2612*0b57cec5SDimitry Andric if (auto Imm = getFoldableImm(Src0)) { 2613*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) != -1 && 2614*0b57cec5SDimitry Andric isOperandLegal(MI, AMDGPU::getNamedOperandIdx(NewOpc, 2615*0b57cec5SDimitry Andric AMDGPU::OpName::src0), Src1)) 2616*0b57cec5SDimitry Andric return BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc)) 2617*0b57cec5SDimitry Andric .add(*Dst) 2618*0b57cec5SDimitry Andric .add(*Src1) 2619*0b57cec5SDimitry Andric .addImm(Imm) 2620*0b57cec5SDimitry Andric .add(*Src2); 2621*0b57cec5SDimitry Andric } 2622*0b57cec5SDimitry Andric } 2623*0b57cec5SDimitry Andric 2624*0b57cec5SDimitry Andric unsigned NewOpc = IsFMA ? (IsF16 ? AMDGPU::V_FMA_F16 : AMDGPU::V_FMA_F32) 2625*0b57cec5SDimitry Andric : (IsF16 ? AMDGPU::V_MAD_F16 : AMDGPU::V_MAD_F32); 2626*0b57cec5SDimitry Andric if (pseudoToMCOpcode(NewOpc) == -1) 2627*0b57cec5SDimitry Andric return nullptr; 2628*0b57cec5SDimitry Andric 2629*0b57cec5SDimitry Andric return BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc)) 2630*0b57cec5SDimitry Andric .add(*Dst) 2631*0b57cec5SDimitry Andric .addImm(Src0Mods ? Src0Mods->getImm() : 0) 2632*0b57cec5SDimitry Andric .add(*Src0) 2633*0b57cec5SDimitry Andric .addImm(Src1Mods ? Src1Mods->getImm() : 0) 2634*0b57cec5SDimitry Andric .add(*Src1) 2635*0b57cec5SDimitry Andric .addImm(0) // Src mods 2636*0b57cec5SDimitry Andric .add(*Src2) 2637*0b57cec5SDimitry Andric .addImm(Clamp ? Clamp->getImm() : 0) 2638*0b57cec5SDimitry Andric .addImm(Omod ? Omod->getImm() : 0); 2639*0b57cec5SDimitry Andric } 2640*0b57cec5SDimitry Andric 2641*0b57cec5SDimitry Andric // It's not generally safe to move VALU instructions across these since it will 2642*0b57cec5SDimitry Andric // start using the register as a base index rather than directly. 2643*0b57cec5SDimitry Andric // XXX - Why isn't hasSideEffects sufficient for these? 2644*0b57cec5SDimitry Andric static bool changesVGPRIndexingMode(const MachineInstr &MI) { 2645*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 2646*0b57cec5SDimitry Andric case AMDGPU::S_SET_GPR_IDX_ON: 2647*0b57cec5SDimitry Andric case AMDGPU::S_SET_GPR_IDX_MODE: 2648*0b57cec5SDimitry Andric case AMDGPU::S_SET_GPR_IDX_OFF: 2649*0b57cec5SDimitry Andric return true; 2650*0b57cec5SDimitry Andric default: 2651*0b57cec5SDimitry Andric return false; 2652*0b57cec5SDimitry Andric } 2653*0b57cec5SDimitry Andric } 2654*0b57cec5SDimitry Andric 2655*0b57cec5SDimitry Andric bool SIInstrInfo::isSchedulingBoundary(const MachineInstr &MI, 2656*0b57cec5SDimitry Andric const MachineBasicBlock *MBB, 2657*0b57cec5SDimitry Andric const MachineFunction &MF) const { 2658*0b57cec5SDimitry Andric // XXX - Do we want the SP check in the base implementation? 2659*0b57cec5SDimitry Andric 2660*0b57cec5SDimitry Andric // Target-independent instructions do not have an implicit-use of EXEC, even 2661*0b57cec5SDimitry Andric // when they operate on VGPRs. Treating EXEC modifications as scheduling 2662*0b57cec5SDimitry Andric // boundaries prevents incorrect movements of such instructions. 2663*0b57cec5SDimitry Andric return TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF) || 2664*0b57cec5SDimitry Andric MI.modifiesRegister(AMDGPU::EXEC, &RI) || 2665*0b57cec5SDimitry Andric MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 || 2666*0b57cec5SDimitry Andric MI.getOpcode() == AMDGPU::S_SETREG_B32 || 2667*0b57cec5SDimitry Andric changesVGPRIndexingMode(MI); 2668*0b57cec5SDimitry Andric } 2669*0b57cec5SDimitry Andric 2670*0b57cec5SDimitry Andric bool SIInstrInfo::isAlwaysGDS(uint16_t Opcode) const { 2671*0b57cec5SDimitry Andric return Opcode == AMDGPU::DS_ORDERED_COUNT || 2672*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_INIT || 2673*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_SEMA_V || 2674*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_SEMA_BR || 2675*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_SEMA_P || 2676*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_SEMA_RELEASE_ALL || 2677*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_BARRIER; 2678*0b57cec5SDimitry Andric } 2679*0b57cec5SDimitry Andric 2680*0b57cec5SDimitry Andric bool SIInstrInfo::hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const { 2681*0b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 2682*0b57cec5SDimitry Andric 2683*0b57cec5SDimitry Andric if (MI.mayStore() && isSMRD(MI)) 2684*0b57cec5SDimitry Andric return true; // scalar store or atomic 2685*0b57cec5SDimitry Andric 2686*0b57cec5SDimitry Andric // This will terminate the function when other lanes may need to continue. 2687*0b57cec5SDimitry Andric if (MI.isReturn()) 2688*0b57cec5SDimitry Andric return true; 2689*0b57cec5SDimitry Andric 2690*0b57cec5SDimitry Andric // These instructions cause shader I/O that may cause hardware lockups 2691*0b57cec5SDimitry Andric // when executed with an empty EXEC mask. 2692*0b57cec5SDimitry Andric // 2693*0b57cec5SDimitry Andric // Note: exp with VM = DONE = 0 is automatically skipped by hardware when 2694*0b57cec5SDimitry Andric // EXEC = 0, but checking for that case here seems not worth it 2695*0b57cec5SDimitry Andric // given the typical code patterns. 2696*0b57cec5SDimitry Andric if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT || 2697*0b57cec5SDimitry Andric Opcode == AMDGPU::EXP || Opcode == AMDGPU::EXP_DONE || 2698*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_ORDERED_COUNT || Opcode == AMDGPU::S_TRAP || 2699*0b57cec5SDimitry Andric Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_BARRIER) 2700*0b57cec5SDimitry Andric return true; 2701*0b57cec5SDimitry Andric 2702*0b57cec5SDimitry Andric if (MI.isCall() || MI.isInlineAsm()) 2703*0b57cec5SDimitry Andric return true; // conservative assumption 2704*0b57cec5SDimitry Andric 2705*0b57cec5SDimitry Andric // These are like SALU instructions in terms of effects, so it's questionable 2706*0b57cec5SDimitry Andric // whether we should return true for those. 2707*0b57cec5SDimitry Andric // 2708*0b57cec5SDimitry Andric // However, executing them with EXEC = 0 causes them to operate on undefined 2709*0b57cec5SDimitry Andric // data, which we avoid by returning true here. 2710*0b57cec5SDimitry Andric if (Opcode == AMDGPU::V_READFIRSTLANE_B32 || Opcode == AMDGPU::V_READLANE_B32) 2711*0b57cec5SDimitry Andric return true; 2712*0b57cec5SDimitry Andric 2713*0b57cec5SDimitry Andric return false; 2714*0b57cec5SDimitry Andric } 2715*0b57cec5SDimitry Andric 2716*0b57cec5SDimitry Andric bool SIInstrInfo::mayReadEXEC(const MachineRegisterInfo &MRI, 2717*0b57cec5SDimitry Andric const MachineInstr &MI) const { 2718*0b57cec5SDimitry Andric if (MI.isMetaInstruction()) 2719*0b57cec5SDimitry Andric return false; 2720*0b57cec5SDimitry Andric 2721*0b57cec5SDimitry Andric // This won't read exec if this is an SGPR->SGPR copy. 2722*0b57cec5SDimitry Andric if (MI.isCopyLike()) { 2723*0b57cec5SDimitry Andric if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg())) 2724*0b57cec5SDimitry Andric return true; 2725*0b57cec5SDimitry Andric 2726*0b57cec5SDimitry Andric // Make sure this isn't copying exec as a normal operand 2727*0b57cec5SDimitry Andric return MI.readsRegister(AMDGPU::EXEC, &RI); 2728*0b57cec5SDimitry Andric } 2729*0b57cec5SDimitry Andric 2730*0b57cec5SDimitry Andric // Make a conservative assumption about the callee. 2731*0b57cec5SDimitry Andric if (MI.isCall()) 2732*0b57cec5SDimitry Andric return true; 2733*0b57cec5SDimitry Andric 2734*0b57cec5SDimitry Andric // Be conservative with any unhandled generic opcodes. 2735*0b57cec5SDimitry Andric if (!isTargetSpecificOpcode(MI.getOpcode())) 2736*0b57cec5SDimitry Andric return true; 2737*0b57cec5SDimitry Andric 2738*0b57cec5SDimitry Andric return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI); 2739*0b57cec5SDimitry Andric } 2740*0b57cec5SDimitry Andric 2741*0b57cec5SDimitry Andric bool SIInstrInfo::isInlineConstant(const APInt &Imm) const { 2742*0b57cec5SDimitry Andric switch (Imm.getBitWidth()) { 2743*0b57cec5SDimitry Andric case 1: // This likely will be a condition code mask. 2744*0b57cec5SDimitry Andric return true; 2745*0b57cec5SDimitry Andric 2746*0b57cec5SDimitry Andric case 32: 2747*0b57cec5SDimitry Andric return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(), 2748*0b57cec5SDimitry Andric ST.hasInv2PiInlineImm()); 2749*0b57cec5SDimitry Andric case 64: 2750*0b57cec5SDimitry Andric return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(), 2751*0b57cec5SDimitry Andric ST.hasInv2PiInlineImm()); 2752*0b57cec5SDimitry Andric case 16: 2753*0b57cec5SDimitry Andric return ST.has16BitInsts() && 2754*0b57cec5SDimitry Andric AMDGPU::isInlinableLiteral16(Imm.getSExtValue(), 2755*0b57cec5SDimitry Andric ST.hasInv2PiInlineImm()); 2756*0b57cec5SDimitry Andric default: 2757*0b57cec5SDimitry Andric llvm_unreachable("invalid bitwidth"); 2758*0b57cec5SDimitry Andric } 2759*0b57cec5SDimitry Andric } 2760*0b57cec5SDimitry Andric 2761*0b57cec5SDimitry Andric bool SIInstrInfo::isInlineConstant(const MachineOperand &MO, 2762*0b57cec5SDimitry Andric uint8_t OperandType) const { 2763*0b57cec5SDimitry Andric if (!MO.isImm() || 2764*0b57cec5SDimitry Andric OperandType < AMDGPU::OPERAND_SRC_FIRST || 2765*0b57cec5SDimitry Andric OperandType > AMDGPU::OPERAND_SRC_LAST) 2766*0b57cec5SDimitry Andric return false; 2767*0b57cec5SDimitry Andric 2768*0b57cec5SDimitry Andric // MachineOperand provides no way to tell the true operand size, since it only 2769*0b57cec5SDimitry Andric // records a 64-bit value. We need to know the size to determine if a 32-bit 2770*0b57cec5SDimitry Andric // floating point immediate bit pattern is legal for an integer immediate. It 2771*0b57cec5SDimitry Andric // would be for any 32-bit integer operand, but would not be for a 64-bit one. 2772*0b57cec5SDimitry Andric 2773*0b57cec5SDimitry Andric int64_t Imm = MO.getImm(); 2774*0b57cec5SDimitry Andric switch (OperandType) { 2775*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT32: 2776*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32: 2777*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT32: 2778*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP32: 2779*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 2780*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP32: { 2781*0b57cec5SDimitry Andric int32_t Trunc = static_cast<int32_t>(Imm); 2782*0b57cec5SDimitry Andric return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm()); 2783*0b57cec5SDimitry Andric } 2784*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT64: 2785*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP64: 2786*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT64: 2787*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP64: 2788*0b57cec5SDimitry Andric return AMDGPU::isInlinableLiteral64(MO.getImm(), 2789*0b57cec5SDimitry Andric ST.hasInv2PiInlineImm()); 2790*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT16: 2791*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP16: 2792*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT16: 2793*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP16: 2794*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 2795*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP16: { 2796*0b57cec5SDimitry Andric if (isInt<16>(Imm) || isUInt<16>(Imm)) { 2797*0b57cec5SDimitry Andric // A few special case instructions have 16-bit operands on subtargets 2798*0b57cec5SDimitry Andric // where 16-bit instructions are not legal. 2799*0b57cec5SDimitry Andric // TODO: Do the 32-bit immediates work? We shouldn't really need to handle 2800*0b57cec5SDimitry Andric // constants in these cases 2801*0b57cec5SDimitry Andric int16_t Trunc = static_cast<int16_t>(Imm); 2802*0b57cec5SDimitry Andric return ST.has16BitInsts() && 2803*0b57cec5SDimitry Andric AMDGPU::isInlinableLiteral16(Trunc, ST.hasInv2PiInlineImm()); 2804*0b57cec5SDimitry Andric } 2805*0b57cec5SDimitry Andric 2806*0b57cec5SDimitry Andric return false; 2807*0b57cec5SDimitry Andric } 2808*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2INT16: 2809*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2FP16: 2810*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 2811*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 2812*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 2813*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: { 2814*0b57cec5SDimitry Andric uint32_t Trunc = static_cast<uint32_t>(Imm); 2815*0b57cec5SDimitry Andric return AMDGPU::isInlinableLiteralV216(Trunc, ST.hasInv2PiInlineImm()); 2816*0b57cec5SDimitry Andric } 2817*0b57cec5SDimitry Andric default: 2818*0b57cec5SDimitry Andric llvm_unreachable("invalid bitwidth"); 2819*0b57cec5SDimitry Andric } 2820*0b57cec5SDimitry Andric } 2821*0b57cec5SDimitry Andric 2822*0b57cec5SDimitry Andric bool SIInstrInfo::isLiteralConstantLike(const MachineOperand &MO, 2823*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const { 2824*0b57cec5SDimitry Andric switch (MO.getType()) { 2825*0b57cec5SDimitry Andric case MachineOperand::MO_Register: 2826*0b57cec5SDimitry Andric return false; 2827*0b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 2828*0b57cec5SDimitry Andric return !isInlineConstant(MO, OpInfo); 2829*0b57cec5SDimitry Andric case MachineOperand::MO_FrameIndex: 2830*0b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 2831*0b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 2832*0b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 2833*0b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol: 2834*0b57cec5SDimitry Andric return true; 2835*0b57cec5SDimitry Andric default: 2836*0b57cec5SDimitry Andric llvm_unreachable("unexpected operand type"); 2837*0b57cec5SDimitry Andric } 2838*0b57cec5SDimitry Andric } 2839*0b57cec5SDimitry Andric 2840*0b57cec5SDimitry Andric static bool compareMachineOp(const MachineOperand &Op0, 2841*0b57cec5SDimitry Andric const MachineOperand &Op1) { 2842*0b57cec5SDimitry Andric if (Op0.getType() != Op1.getType()) 2843*0b57cec5SDimitry Andric return false; 2844*0b57cec5SDimitry Andric 2845*0b57cec5SDimitry Andric switch (Op0.getType()) { 2846*0b57cec5SDimitry Andric case MachineOperand::MO_Register: 2847*0b57cec5SDimitry Andric return Op0.getReg() == Op1.getReg(); 2848*0b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 2849*0b57cec5SDimitry Andric return Op0.getImm() == Op1.getImm(); 2850*0b57cec5SDimitry Andric default: 2851*0b57cec5SDimitry Andric llvm_unreachable("Didn't expect to be comparing these operand types"); 2852*0b57cec5SDimitry Andric } 2853*0b57cec5SDimitry Andric } 2854*0b57cec5SDimitry Andric 2855*0b57cec5SDimitry Andric bool SIInstrInfo::isImmOperandLegal(const MachineInstr &MI, unsigned OpNo, 2856*0b57cec5SDimitry Andric const MachineOperand &MO) const { 2857*0b57cec5SDimitry Andric const MCInstrDesc &InstDesc = MI.getDesc(); 2858*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo = InstDesc.OpInfo[OpNo]; 2859*0b57cec5SDimitry Andric 2860*0b57cec5SDimitry Andric assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal()); 2861*0b57cec5SDimitry Andric 2862*0b57cec5SDimitry Andric if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE) 2863*0b57cec5SDimitry Andric return true; 2864*0b57cec5SDimitry Andric 2865*0b57cec5SDimitry Andric if (OpInfo.RegClass < 0) 2866*0b57cec5SDimitry Andric return false; 2867*0b57cec5SDimitry Andric 2868*0b57cec5SDimitry Andric if (MO.isImm() && isInlineConstant(MO, OpInfo)) 2869*0b57cec5SDimitry Andric return RI.opCanUseInlineConstant(OpInfo.OperandType); 2870*0b57cec5SDimitry Andric 2871*0b57cec5SDimitry Andric if (!RI.opCanUseLiteralConstant(OpInfo.OperandType)) 2872*0b57cec5SDimitry Andric return false; 2873*0b57cec5SDimitry Andric 2874*0b57cec5SDimitry Andric if (!isVOP3(MI) || !AMDGPU::isSISrcOperand(InstDesc, OpNo)) 2875*0b57cec5SDimitry Andric return true; 2876*0b57cec5SDimitry Andric 2877*0b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent(); 2878*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>(); 2879*0b57cec5SDimitry Andric return ST.hasVOP3Literal(); 2880*0b57cec5SDimitry Andric } 2881*0b57cec5SDimitry Andric 2882*0b57cec5SDimitry Andric bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const { 2883*0b57cec5SDimitry Andric int Op32 = AMDGPU::getVOPe32(Opcode); 2884*0b57cec5SDimitry Andric if (Op32 == -1) 2885*0b57cec5SDimitry Andric return false; 2886*0b57cec5SDimitry Andric 2887*0b57cec5SDimitry Andric return pseudoToMCOpcode(Op32) != -1; 2888*0b57cec5SDimitry Andric } 2889*0b57cec5SDimitry Andric 2890*0b57cec5SDimitry Andric bool SIInstrInfo::hasModifiers(unsigned Opcode) const { 2891*0b57cec5SDimitry Andric // The src0_modifier operand is present on all instructions 2892*0b57cec5SDimitry Andric // that have modifiers. 2893*0b57cec5SDimitry Andric 2894*0b57cec5SDimitry Andric return AMDGPU::getNamedOperandIdx(Opcode, 2895*0b57cec5SDimitry Andric AMDGPU::OpName::src0_modifiers) != -1; 2896*0b57cec5SDimitry Andric } 2897*0b57cec5SDimitry Andric 2898*0b57cec5SDimitry Andric bool SIInstrInfo::hasModifiersSet(const MachineInstr &MI, 2899*0b57cec5SDimitry Andric unsigned OpName) const { 2900*0b57cec5SDimitry Andric const MachineOperand *Mods = getNamedOperand(MI, OpName); 2901*0b57cec5SDimitry Andric return Mods && Mods->getImm(); 2902*0b57cec5SDimitry Andric } 2903*0b57cec5SDimitry Andric 2904*0b57cec5SDimitry Andric bool SIInstrInfo::hasAnyModifiersSet(const MachineInstr &MI) const { 2905*0b57cec5SDimitry Andric return hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers) || 2906*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers) || 2907*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers) || 2908*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::clamp) || 2909*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::omod); 2910*0b57cec5SDimitry Andric } 2911*0b57cec5SDimitry Andric 2912*0b57cec5SDimitry Andric bool SIInstrInfo::canShrink(const MachineInstr &MI, 2913*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI) const { 2914*0b57cec5SDimitry Andric const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2); 2915*0b57cec5SDimitry Andric // Can't shrink instruction with three operands. 2916*0b57cec5SDimitry Andric // FIXME: v_cndmask_b32 has 3 operands and is shrinkable, but we need to add 2917*0b57cec5SDimitry Andric // a special case for it. It can only be shrunk if the third operand 2918*0b57cec5SDimitry Andric // is vcc, and src0_modifiers and src1_modifiers are not set. 2919*0b57cec5SDimitry Andric // We should handle this the same way we handle vopc, by addding 2920*0b57cec5SDimitry Andric // a register allocation hint pre-regalloc and then do the shrinking 2921*0b57cec5SDimitry Andric // post-regalloc. 2922*0b57cec5SDimitry Andric if (Src2) { 2923*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 2924*0b57cec5SDimitry Andric default: return false; 2925*0b57cec5SDimitry Andric 2926*0b57cec5SDimitry Andric case AMDGPU::V_ADDC_U32_e64: 2927*0b57cec5SDimitry Andric case AMDGPU::V_SUBB_U32_e64: 2928*0b57cec5SDimitry Andric case AMDGPU::V_SUBBREV_U32_e64: { 2929*0b57cec5SDimitry Andric const MachineOperand *Src1 2930*0b57cec5SDimitry Andric = getNamedOperand(MI, AMDGPU::OpName::src1); 2931*0b57cec5SDimitry Andric if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg())) 2932*0b57cec5SDimitry Andric return false; 2933*0b57cec5SDimitry Andric // Additional verification is needed for sdst/src2. 2934*0b57cec5SDimitry Andric return true; 2935*0b57cec5SDimitry Andric } 2936*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F32_e64: 2937*0b57cec5SDimitry Andric case AMDGPU::V_MAC_F16_e64: 2938*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F32_e64: 2939*0b57cec5SDimitry Andric case AMDGPU::V_FMAC_F16_e64: 2940*0b57cec5SDimitry Andric if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) || 2941*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers)) 2942*0b57cec5SDimitry Andric return false; 2943*0b57cec5SDimitry Andric break; 2944*0b57cec5SDimitry Andric 2945*0b57cec5SDimitry Andric case AMDGPU::V_CNDMASK_B32_e64: 2946*0b57cec5SDimitry Andric break; 2947*0b57cec5SDimitry Andric } 2948*0b57cec5SDimitry Andric } 2949*0b57cec5SDimitry Andric 2950*0b57cec5SDimitry Andric const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1); 2951*0b57cec5SDimitry Andric if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) || 2952*0b57cec5SDimitry Andric hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers))) 2953*0b57cec5SDimitry Andric return false; 2954*0b57cec5SDimitry Andric 2955*0b57cec5SDimitry Andric // We don't need to check src0, all input types are legal, so just make sure 2956*0b57cec5SDimitry Andric // src0 isn't using any modifiers. 2957*0b57cec5SDimitry Andric if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers)) 2958*0b57cec5SDimitry Andric return false; 2959*0b57cec5SDimitry Andric 2960*0b57cec5SDimitry Andric // Can it be shrunk to a valid 32 bit opcode? 2961*0b57cec5SDimitry Andric if (!hasVALU32BitEncoding(MI.getOpcode())) 2962*0b57cec5SDimitry Andric return false; 2963*0b57cec5SDimitry Andric 2964*0b57cec5SDimitry Andric // Check output modifiers 2965*0b57cec5SDimitry Andric return !hasModifiersSet(MI, AMDGPU::OpName::omod) && 2966*0b57cec5SDimitry Andric !hasModifiersSet(MI, AMDGPU::OpName::clamp); 2967*0b57cec5SDimitry Andric } 2968*0b57cec5SDimitry Andric 2969*0b57cec5SDimitry Andric // Set VCC operand with all flags from \p Orig, except for setting it as 2970*0b57cec5SDimitry Andric // implicit. 2971*0b57cec5SDimitry Andric static void copyFlagsToImplicitVCC(MachineInstr &MI, 2972*0b57cec5SDimitry Andric const MachineOperand &Orig) { 2973*0b57cec5SDimitry Andric 2974*0b57cec5SDimitry Andric for (MachineOperand &Use : MI.implicit_operands()) { 2975*0b57cec5SDimitry Andric if (Use.isUse() && Use.getReg() == AMDGPU::VCC) { 2976*0b57cec5SDimitry Andric Use.setIsUndef(Orig.isUndef()); 2977*0b57cec5SDimitry Andric Use.setIsKill(Orig.isKill()); 2978*0b57cec5SDimitry Andric return; 2979*0b57cec5SDimitry Andric } 2980*0b57cec5SDimitry Andric } 2981*0b57cec5SDimitry Andric } 2982*0b57cec5SDimitry Andric 2983*0b57cec5SDimitry Andric MachineInstr *SIInstrInfo::buildShrunkInst(MachineInstr &MI, 2984*0b57cec5SDimitry Andric unsigned Op32) const { 2985*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent();; 2986*0b57cec5SDimitry Andric MachineInstrBuilder Inst32 = 2987*0b57cec5SDimitry Andric BuildMI(*MBB, MI, MI.getDebugLoc(), get(Op32)); 2988*0b57cec5SDimitry Andric 2989*0b57cec5SDimitry Andric // Add the dst operand if the 32-bit encoding also has an explicit $vdst. 2990*0b57cec5SDimitry Andric // For VOPC instructions, this is replaced by an implicit def of vcc. 2991*0b57cec5SDimitry Andric int Op32DstIdx = AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::vdst); 2992*0b57cec5SDimitry Andric if (Op32DstIdx != -1) { 2993*0b57cec5SDimitry Andric // dst 2994*0b57cec5SDimitry Andric Inst32.add(MI.getOperand(0)); 2995*0b57cec5SDimitry Andric } else { 2996*0b57cec5SDimitry Andric assert(((MI.getOperand(0).getReg() == AMDGPU::VCC) || 2997*0b57cec5SDimitry Andric (MI.getOperand(0).getReg() == AMDGPU::VCC_LO)) && 2998*0b57cec5SDimitry Andric "Unexpected case"); 2999*0b57cec5SDimitry Andric } 3000*0b57cec5SDimitry Andric 3001*0b57cec5SDimitry Andric Inst32.add(*getNamedOperand(MI, AMDGPU::OpName::src0)); 3002*0b57cec5SDimitry Andric 3003*0b57cec5SDimitry Andric const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1); 3004*0b57cec5SDimitry Andric if (Src1) 3005*0b57cec5SDimitry Andric Inst32.add(*Src1); 3006*0b57cec5SDimitry Andric 3007*0b57cec5SDimitry Andric const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2); 3008*0b57cec5SDimitry Andric 3009*0b57cec5SDimitry Andric if (Src2) { 3010*0b57cec5SDimitry Andric int Op32Src2Idx = AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2); 3011*0b57cec5SDimitry Andric if (Op32Src2Idx != -1) { 3012*0b57cec5SDimitry Andric Inst32.add(*Src2); 3013*0b57cec5SDimitry Andric } else { 3014*0b57cec5SDimitry Andric // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is 3015*0b57cec5SDimitry Andric // replaced with an implicit read of vcc. This was already added 3016*0b57cec5SDimitry Andric // during the initial BuildMI, so find it to preserve the flags. 3017*0b57cec5SDimitry Andric copyFlagsToImplicitVCC(*Inst32, *Src2); 3018*0b57cec5SDimitry Andric } 3019*0b57cec5SDimitry Andric } 3020*0b57cec5SDimitry Andric 3021*0b57cec5SDimitry Andric return Inst32; 3022*0b57cec5SDimitry Andric } 3023*0b57cec5SDimitry Andric 3024*0b57cec5SDimitry Andric bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI, 3025*0b57cec5SDimitry Andric const MachineOperand &MO, 3026*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const { 3027*0b57cec5SDimitry Andric // Literal constants use the constant bus. 3028*0b57cec5SDimitry Andric //if (isLiteralConstantLike(MO, OpInfo)) 3029*0b57cec5SDimitry Andric // return true; 3030*0b57cec5SDimitry Andric if (MO.isImm()) 3031*0b57cec5SDimitry Andric return !isInlineConstant(MO, OpInfo); 3032*0b57cec5SDimitry Andric 3033*0b57cec5SDimitry Andric if (!MO.isReg()) 3034*0b57cec5SDimitry Andric return true; // Misc other operands like FrameIndex 3035*0b57cec5SDimitry Andric 3036*0b57cec5SDimitry Andric if (!MO.isUse()) 3037*0b57cec5SDimitry Andric return false; 3038*0b57cec5SDimitry Andric 3039*0b57cec5SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) 3040*0b57cec5SDimitry Andric return RI.isSGPRClass(MRI.getRegClass(MO.getReg())); 3041*0b57cec5SDimitry Andric 3042*0b57cec5SDimitry Andric // Null is free 3043*0b57cec5SDimitry Andric if (MO.getReg() == AMDGPU::SGPR_NULL) 3044*0b57cec5SDimitry Andric return false; 3045*0b57cec5SDimitry Andric 3046*0b57cec5SDimitry Andric // SGPRs use the constant bus 3047*0b57cec5SDimitry Andric if (MO.isImplicit()) { 3048*0b57cec5SDimitry Andric return MO.getReg() == AMDGPU::M0 || 3049*0b57cec5SDimitry Andric MO.getReg() == AMDGPU::VCC || 3050*0b57cec5SDimitry Andric MO.getReg() == AMDGPU::VCC_LO; 3051*0b57cec5SDimitry Andric } else { 3052*0b57cec5SDimitry Andric return AMDGPU::SReg_32RegClass.contains(MO.getReg()) || 3053*0b57cec5SDimitry Andric AMDGPU::SReg_64RegClass.contains(MO.getReg()); 3054*0b57cec5SDimitry Andric } 3055*0b57cec5SDimitry Andric } 3056*0b57cec5SDimitry Andric 3057*0b57cec5SDimitry Andric static unsigned findImplicitSGPRRead(const MachineInstr &MI) { 3058*0b57cec5SDimitry Andric for (const MachineOperand &MO : MI.implicit_operands()) { 3059*0b57cec5SDimitry Andric // We only care about reads. 3060*0b57cec5SDimitry Andric if (MO.isDef()) 3061*0b57cec5SDimitry Andric continue; 3062*0b57cec5SDimitry Andric 3063*0b57cec5SDimitry Andric switch (MO.getReg()) { 3064*0b57cec5SDimitry Andric case AMDGPU::VCC: 3065*0b57cec5SDimitry Andric case AMDGPU::VCC_LO: 3066*0b57cec5SDimitry Andric case AMDGPU::VCC_HI: 3067*0b57cec5SDimitry Andric case AMDGPU::M0: 3068*0b57cec5SDimitry Andric case AMDGPU::FLAT_SCR: 3069*0b57cec5SDimitry Andric return MO.getReg(); 3070*0b57cec5SDimitry Andric 3071*0b57cec5SDimitry Andric default: 3072*0b57cec5SDimitry Andric break; 3073*0b57cec5SDimitry Andric } 3074*0b57cec5SDimitry Andric } 3075*0b57cec5SDimitry Andric 3076*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 3077*0b57cec5SDimitry Andric } 3078*0b57cec5SDimitry Andric 3079*0b57cec5SDimitry Andric static bool shouldReadExec(const MachineInstr &MI) { 3080*0b57cec5SDimitry Andric if (SIInstrInfo::isVALU(MI)) { 3081*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 3082*0b57cec5SDimitry Andric case AMDGPU::V_READLANE_B32: 3083*0b57cec5SDimitry Andric case AMDGPU::V_READLANE_B32_gfx6_gfx7: 3084*0b57cec5SDimitry Andric case AMDGPU::V_READLANE_B32_gfx10: 3085*0b57cec5SDimitry Andric case AMDGPU::V_READLANE_B32_vi: 3086*0b57cec5SDimitry Andric case AMDGPU::V_WRITELANE_B32: 3087*0b57cec5SDimitry Andric case AMDGPU::V_WRITELANE_B32_gfx6_gfx7: 3088*0b57cec5SDimitry Andric case AMDGPU::V_WRITELANE_B32_gfx10: 3089*0b57cec5SDimitry Andric case AMDGPU::V_WRITELANE_B32_vi: 3090*0b57cec5SDimitry Andric return false; 3091*0b57cec5SDimitry Andric } 3092*0b57cec5SDimitry Andric 3093*0b57cec5SDimitry Andric return true; 3094*0b57cec5SDimitry Andric } 3095*0b57cec5SDimitry Andric 3096*0b57cec5SDimitry Andric if (SIInstrInfo::isGenericOpcode(MI.getOpcode()) || 3097*0b57cec5SDimitry Andric SIInstrInfo::isSALU(MI) || 3098*0b57cec5SDimitry Andric SIInstrInfo::isSMRD(MI)) 3099*0b57cec5SDimitry Andric return false; 3100*0b57cec5SDimitry Andric 3101*0b57cec5SDimitry Andric return true; 3102*0b57cec5SDimitry Andric } 3103*0b57cec5SDimitry Andric 3104*0b57cec5SDimitry Andric static bool isSubRegOf(const SIRegisterInfo &TRI, 3105*0b57cec5SDimitry Andric const MachineOperand &SuperVec, 3106*0b57cec5SDimitry Andric const MachineOperand &SubReg) { 3107*0b57cec5SDimitry Andric if (TargetRegisterInfo::isPhysicalRegister(SubReg.getReg())) 3108*0b57cec5SDimitry Andric return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg()); 3109*0b57cec5SDimitry Andric 3110*0b57cec5SDimitry Andric return SubReg.getSubReg() != AMDGPU::NoSubRegister && 3111*0b57cec5SDimitry Andric SubReg.getReg() == SuperVec.getReg(); 3112*0b57cec5SDimitry Andric } 3113*0b57cec5SDimitry Andric 3114*0b57cec5SDimitry Andric bool SIInstrInfo::verifyInstruction(const MachineInstr &MI, 3115*0b57cec5SDimitry Andric StringRef &ErrInfo) const { 3116*0b57cec5SDimitry Andric uint16_t Opcode = MI.getOpcode(); 3117*0b57cec5SDimitry Andric if (SIInstrInfo::isGenericOpcode(MI.getOpcode())) 3118*0b57cec5SDimitry Andric return true; 3119*0b57cec5SDimitry Andric 3120*0b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent(); 3121*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF->getRegInfo(); 3122*0b57cec5SDimitry Andric 3123*0b57cec5SDimitry Andric int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3124*0b57cec5SDimitry Andric int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3125*0b57cec5SDimitry Andric int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3126*0b57cec5SDimitry Andric 3127*0b57cec5SDimitry Andric // Make sure the number of operands is correct. 3128*0b57cec5SDimitry Andric const MCInstrDesc &Desc = get(Opcode); 3129*0b57cec5SDimitry Andric if (!Desc.isVariadic() && 3130*0b57cec5SDimitry Andric Desc.getNumOperands() != MI.getNumExplicitOperands()) { 3131*0b57cec5SDimitry Andric ErrInfo = "Instruction has wrong number of operands."; 3132*0b57cec5SDimitry Andric return false; 3133*0b57cec5SDimitry Andric } 3134*0b57cec5SDimitry Andric 3135*0b57cec5SDimitry Andric if (MI.isInlineAsm()) { 3136*0b57cec5SDimitry Andric // Verify register classes for inlineasm constraints. 3137*0b57cec5SDimitry Andric for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands(); 3138*0b57cec5SDimitry Andric I != E; ++I) { 3139*0b57cec5SDimitry Andric const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI); 3140*0b57cec5SDimitry Andric if (!RC) 3141*0b57cec5SDimitry Andric continue; 3142*0b57cec5SDimitry Andric 3143*0b57cec5SDimitry Andric const MachineOperand &Op = MI.getOperand(I); 3144*0b57cec5SDimitry Andric if (!Op.isReg()) 3145*0b57cec5SDimitry Andric continue; 3146*0b57cec5SDimitry Andric 3147*0b57cec5SDimitry Andric unsigned Reg = Op.getReg(); 3148*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(Reg) && !RC->contains(Reg)) { 3149*0b57cec5SDimitry Andric ErrInfo = "inlineasm operand has incorrect register class."; 3150*0b57cec5SDimitry Andric return false; 3151*0b57cec5SDimitry Andric } 3152*0b57cec5SDimitry Andric } 3153*0b57cec5SDimitry Andric 3154*0b57cec5SDimitry Andric return true; 3155*0b57cec5SDimitry Andric } 3156*0b57cec5SDimitry Andric 3157*0b57cec5SDimitry Andric // Make sure the register classes are correct. 3158*0b57cec5SDimitry Andric for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) { 3159*0b57cec5SDimitry Andric if (MI.getOperand(i).isFPImm()) { 3160*0b57cec5SDimitry Andric ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast " 3161*0b57cec5SDimitry Andric "all fp values to integers."; 3162*0b57cec5SDimitry Andric return false; 3163*0b57cec5SDimitry Andric } 3164*0b57cec5SDimitry Andric 3165*0b57cec5SDimitry Andric int RegClass = Desc.OpInfo[i].RegClass; 3166*0b57cec5SDimitry Andric 3167*0b57cec5SDimitry Andric switch (Desc.OpInfo[i].OperandType) { 3168*0b57cec5SDimitry Andric case MCOI::OPERAND_REGISTER: 3169*0b57cec5SDimitry Andric if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) { 3170*0b57cec5SDimitry Andric ErrInfo = "Illegal immediate value for operand."; 3171*0b57cec5SDimitry Andric return false; 3172*0b57cec5SDimitry Andric } 3173*0b57cec5SDimitry Andric break; 3174*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT32: 3175*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32: 3176*0b57cec5SDimitry Andric break; 3177*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT32: 3178*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP32: 3179*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT64: 3180*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP64: 3181*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT16: 3182*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP16: 3183*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 3184*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 3185*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 3186*0b57cec5SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP16: { 3187*0b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(i); 3188*0b57cec5SDimitry Andric if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) { 3189*0b57cec5SDimitry Andric ErrInfo = "Illegal immediate value for operand."; 3190*0b57cec5SDimitry Andric return false; 3191*0b57cec5SDimitry Andric } 3192*0b57cec5SDimitry Andric break; 3193*0b57cec5SDimitry Andric } 3194*0b57cec5SDimitry Andric case MCOI::OPERAND_IMMEDIATE: 3195*0b57cec5SDimitry Andric case AMDGPU::OPERAND_KIMM32: 3196*0b57cec5SDimitry Andric // Check if this operand is an immediate. 3197*0b57cec5SDimitry Andric // FrameIndex operands will be replaced by immediates, so they are 3198*0b57cec5SDimitry Andric // allowed. 3199*0b57cec5SDimitry Andric if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) { 3200*0b57cec5SDimitry Andric ErrInfo = "Expected immediate, but got non-immediate"; 3201*0b57cec5SDimitry Andric return false; 3202*0b57cec5SDimitry Andric } 3203*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 3204*0b57cec5SDimitry Andric default: 3205*0b57cec5SDimitry Andric continue; 3206*0b57cec5SDimitry Andric } 3207*0b57cec5SDimitry Andric 3208*0b57cec5SDimitry Andric if (!MI.getOperand(i).isReg()) 3209*0b57cec5SDimitry Andric continue; 3210*0b57cec5SDimitry Andric 3211*0b57cec5SDimitry Andric if (RegClass != -1) { 3212*0b57cec5SDimitry Andric unsigned Reg = MI.getOperand(i).getReg(); 3213*0b57cec5SDimitry Andric if (Reg == AMDGPU::NoRegister || 3214*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(Reg)) 3215*0b57cec5SDimitry Andric continue; 3216*0b57cec5SDimitry Andric 3217*0b57cec5SDimitry Andric const TargetRegisterClass *RC = RI.getRegClass(RegClass); 3218*0b57cec5SDimitry Andric if (!RC->contains(Reg)) { 3219*0b57cec5SDimitry Andric ErrInfo = "Operand has incorrect register class."; 3220*0b57cec5SDimitry Andric return false; 3221*0b57cec5SDimitry Andric } 3222*0b57cec5SDimitry Andric } 3223*0b57cec5SDimitry Andric } 3224*0b57cec5SDimitry Andric 3225*0b57cec5SDimitry Andric // Verify SDWA 3226*0b57cec5SDimitry Andric if (isSDWA(MI)) { 3227*0b57cec5SDimitry Andric if (!ST.hasSDWA()) { 3228*0b57cec5SDimitry Andric ErrInfo = "SDWA is not supported on this target"; 3229*0b57cec5SDimitry Andric return false; 3230*0b57cec5SDimitry Andric } 3231*0b57cec5SDimitry Andric 3232*0b57cec5SDimitry Andric int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst); 3233*0b57cec5SDimitry Andric 3234*0b57cec5SDimitry Andric const int OpIndicies[] = { DstIdx, Src0Idx, Src1Idx, Src2Idx }; 3235*0b57cec5SDimitry Andric 3236*0b57cec5SDimitry Andric for (int OpIdx: OpIndicies) { 3237*0b57cec5SDimitry Andric if (OpIdx == -1) 3238*0b57cec5SDimitry Andric continue; 3239*0b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 3240*0b57cec5SDimitry Andric 3241*0b57cec5SDimitry Andric if (!ST.hasSDWAScalar()) { 3242*0b57cec5SDimitry Andric // Only VGPRS on VI 3243*0b57cec5SDimitry Andric if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) { 3244*0b57cec5SDimitry Andric ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI"; 3245*0b57cec5SDimitry Andric return false; 3246*0b57cec5SDimitry Andric } 3247*0b57cec5SDimitry Andric } else { 3248*0b57cec5SDimitry Andric // No immediates on GFX9 3249*0b57cec5SDimitry Andric if (!MO.isReg()) { 3250*0b57cec5SDimitry Andric ErrInfo = "Only reg allowed as operands in SDWA instructions on GFX9"; 3251*0b57cec5SDimitry Andric return false; 3252*0b57cec5SDimitry Andric } 3253*0b57cec5SDimitry Andric } 3254*0b57cec5SDimitry Andric } 3255*0b57cec5SDimitry Andric 3256*0b57cec5SDimitry Andric if (!ST.hasSDWAOmod()) { 3257*0b57cec5SDimitry Andric // No omod allowed on VI 3258*0b57cec5SDimitry Andric const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod); 3259*0b57cec5SDimitry Andric if (OMod != nullptr && 3260*0b57cec5SDimitry Andric (!OMod->isImm() || OMod->getImm() != 0)) { 3261*0b57cec5SDimitry Andric ErrInfo = "OMod not allowed in SDWA instructions on VI"; 3262*0b57cec5SDimitry Andric return false; 3263*0b57cec5SDimitry Andric } 3264*0b57cec5SDimitry Andric } 3265*0b57cec5SDimitry Andric 3266*0b57cec5SDimitry Andric uint16_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode); 3267*0b57cec5SDimitry Andric if (isVOPC(BasicOpcode)) { 3268*0b57cec5SDimitry Andric if (!ST.hasSDWASdst() && DstIdx != -1) { 3269*0b57cec5SDimitry Andric // Only vcc allowed as dst on VI for VOPC 3270*0b57cec5SDimitry Andric const MachineOperand &Dst = MI.getOperand(DstIdx); 3271*0b57cec5SDimitry Andric if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) { 3272*0b57cec5SDimitry Andric ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI"; 3273*0b57cec5SDimitry Andric return false; 3274*0b57cec5SDimitry Andric } 3275*0b57cec5SDimitry Andric } else if (!ST.hasSDWAOutModsVOPC()) { 3276*0b57cec5SDimitry Andric // No clamp allowed on GFX9 for VOPC 3277*0b57cec5SDimitry Andric const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp); 3278*0b57cec5SDimitry Andric if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) { 3279*0b57cec5SDimitry Andric ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI"; 3280*0b57cec5SDimitry Andric return false; 3281*0b57cec5SDimitry Andric } 3282*0b57cec5SDimitry Andric 3283*0b57cec5SDimitry Andric // No omod allowed on GFX9 for VOPC 3284*0b57cec5SDimitry Andric const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod); 3285*0b57cec5SDimitry Andric if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) { 3286*0b57cec5SDimitry Andric ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI"; 3287*0b57cec5SDimitry Andric return false; 3288*0b57cec5SDimitry Andric } 3289*0b57cec5SDimitry Andric } 3290*0b57cec5SDimitry Andric } 3291*0b57cec5SDimitry Andric 3292*0b57cec5SDimitry Andric const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused); 3293*0b57cec5SDimitry Andric if (DstUnused && DstUnused->isImm() && 3294*0b57cec5SDimitry Andric DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) { 3295*0b57cec5SDimitry Andric const MachineOperand &Dst = MI.getOperand(DstIdx); 3296*0b57cec5SDimitry Andric if (!Dst.isReg() || !Dst.isTied()) { 3297*0b57cec5SDimitry Andric ErrInfo = "Dst register should have tied register"; 3298*0b57cec5SDimitry Andric return false; 3299*0b57cec5SDimitry Andric } 3300*0b57cec5SDimitry Andric 3301*0b57cec5SDimitry Andric const MachineOperand &TiedMO = 3302*0b57cec5SDimitry Andric MI.getOperand(MI.findTiedOperandIdx(DstIdx)); 3303*0b57cec5SDimitry Andric if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) { 3304*0b57cec5SDimitry Andric ErrInfo = 3305*0b57cec5SDimitry Andric "Dst register should be tied to implicit use of preserved register"; 3306*0b57cec5SDimitry Andric return false; 3307*0b57cec5SDimitry Andric } else if (TargetRegisterInfo::isPhysicalRegister(TiedMO.getReg()) && 3308*0b57cec5SDimitry Andric Dst.getReg() != TiedMO.getReg()) { 3309*0b57cec5SDimitry Andric ErrInfo = "Dst register should use same physical register as preserved"; 3310*0b57cec5SDimitry Andric return false; 3311*0b57cec5SDimitry Andric } 3312*0b57cec5SDimitry Andric } 3313*0b57cec5SDimitry Andric } 3314*0b57cec5SDimitry Andric 3315*0b57cec5SDimitry Andric // Verify MIMG 3316*0b57cec5SDimitry Andric if (isMIMG(MI.getOpcode()) && !MI.mayStore()) { 3317*0b57cec5SDimitry Andric // Ensure that the return type used is large enough for all the options 3318*0b57cec5SDimitry Andric // being used TFE/LWE require an extra result register. 3319*0b57cec5SDimitry Andric const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask); 3320*0b57cec5SDimitry Andric if (DMask) { 3321*0b57cec5SDimitry Andric uint64_t DMaskImm = DMask->getImm(); 3322*0b57cec5SDimitry Andric uint32_t RegCount = 3323*0b57cec5SDimitry Andric isGather4(MI.getOpcode()) ? 4 : countPopulation(DMaskImm); 3324*0b57cec5SDimitry Andric const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe); 3325*0b57cec5SDimitry Andric const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe); 3326*0b57cec5SDimitry Andric const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16); 3327*0b57cec5SDimitry Andric 3328*0b57cec5SDimitry Andric // Adjust for packed 16 bit values 3329*0b57cec5SDimitry Andric if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem()) 3330*0b57cec5SDimitry Andric RegCount >>= 1; 3331*0b57cec5SDimitry Andric 3332*0b57cec5SDimitry Andric // Adjust if using LWE or TFE 3333*0b57cec5SDimitry Andric if ((LWE && LWE->getImm()) || (TFE && TFE->getImm())) 3334*0b57cec5SDimitry Andric RegCount += 1; 3335*0b57cec5SDimitry Andric 3336*0b57cec5SDimitry Andric const uint32_t DstIdx = 3337*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata); 3338*0b57cec5SDimitry Andric const MachineOperand &Dst = MI.getOperand(DstIdx); 3339*0b57cec5SDimitry Andric if (Dst.isReg()) { 3340*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx); 3341*0b57cec5SDimitry Andric uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32; 3342*0b57cec5SDimitry Andric if (RegCount > DstSize) { 3343*0b57cec5SDimitry Andric ErrInfo = "MIMG instruction returns too many registers for dst " 3344*0b57cec5SDimitry Andric "register class"; 3345*0b57cec5SDimitry Andric return false; 3346*0b57cec5SDimitry Andric } 3347*0b57cec5SDimitry Andric } 3348*0b57cec5SDimitry Andric } 3349*0b57cec5SDimitry Andric } 3350*0b57cec5SDimitry Andric 3351*0b57cec5SDimitry Andric // Verify VOP*. Ignore multiple sgpr operands on writelane. 3352*0b57cec5SDimitry Andric if (Desc.getOpcode() != AMDGPU::V_WRITELANE_B32 3353*0b57cec5SDimitry Andric && (isVOP1(MI) || isVOP2(MI) || isVOP3(MI) || isVOPC(MI) || isSDWA(MI))) { 3354*0b57cec5SDimitry Andric // Only look at the true operands. Only a real operand can use the constant 3355*0b57cec5SDimitry Andric // bus, and we don't want to check pseudo-operands like the source modifier 3356*0b57cec5SDimitry Andric // flags. 3357*0b57cec5SDimitry Andric const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 3358*0b57cec5SDimitry Andric 3359*0b57cec5SDimitry Andric unsigned ConstantBusCount = 0; 3360*0b57cec5SDimitry Andric unsigned LiteralCount = 0; 3361*0b57cec5SDimitry Andric 3362*0b57cec5SDimitry Andric if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) 3363*0b57cec5SDimitry Andric ++ConstantBusCount; 3364*0b57cec5SDimitry Andric 3365*0b57cec5SDimitry Andric SmallVector<unsigned, 2> SGPRsUsed; 3366*0b57cec5SDimitry Andric unsigned SGPRUsed = findImplicitSGPRRead(MI); 3367*0b57cec5SDimitry Andric if (SGPRUsed != AMDGPU::NoRegister) { 3368*0b57cec5SDimitry Andric ++ConstantBusCount; 3369*0b57cec5SDimitry Andric SGPRsUsed.push_back(SGPRUsed); 3370*0b57cec5SDimitry Andric } 3371*0b57cec5SDimitry Andric 3372*0b57cec5SDimitry Andric for (int OpIdx : OpIndices) { 3373*0b57cec5SDimitry Andric if (OpIdx == -1) 3374*0b57cec5SDimitry Andric break; 3375*0b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 3376*0b57cec5SDimitry Andric if (usesConstantBus(MRI, MO, MI.getDesc().OpInfo[OpIdx])) { 3377*0b57cec5SDimitry Andric if (MO.isReg()) { 3378*0b57cec5SDimitry Andric SGPRUsed = MO.getReg(); 3379*0b57cec5SDimitry Andric if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) { 3380*0b57cec5SDimitry Andric return !RI.regsOverlap(SGPRUsed, SGPR); 3381*0b57cec5SDimitry Andric })) { 3382*0b57cec5SDimitry Andric ++ConstantBusCount; 3383*0b57cec5SDimitry Andric SGPRsUsed.push_back(SGPRUsed); 3384*0b57cec5SDimitry Andric } 3385*0b57cec5SDimitry Andric } else { 3386*0b57cec5SDimitry Andric ++ConstantBusCount; 3387*0b57cec5SDimitry Andric ++LiteralCount; 3388*0b57cec5SDimitry Andric } 3389*0b57cec5SDimitry Andric } 3390*0b57cec5SDimitry Andric } 3391*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>(); 3392*0b57cec5SDimitry Andric // v_writelane_b32 is an exception from constant bus restriction: 3393*0b57cec5SDimitry Andric // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const 3394*0b57cec5SDimitry Andric if (ConstantBusCount > ST.getConstantBusLimit(Opcode) && 3395*0b57cec5SDimitry Andric Opcode != AMDGPU::V_WRITELANE_B32) { 3396*0b57cec5SDimitry Andric ErrInfo = "VOP* instruction violates constant bus restriction"; 3397*0b57cec5SDimitry Andric return false; 3398*0b57cec5SDimitry Andric } 3399*0b57cec5SDimitry Andric 3400*0b57cec5SDimitry Andric if (isVOP3(MI) && LiteralCount) { 3401*0b57cec5SDimitry Andric if (LiteralCount && !ST.hasVOP3Literal()) { 3402*0b57cec5SDimitry Andric ErrInfo = "VOP3 instruction uses literal"; 3403*0b57cec5SDimitry Andric return false; 3404*0b57cec5SDimitry Andric } 3405*0b57cec5SDimitry Andric if (LiteralCount > 1) { 3406*0b57cec5SDimitry Andric ErrInfo = "VOP3 instruction uses more than one literal"; 3407*0b57cec5SDimitry Andric return false; 3408*0b57cec5SDimitry Andric } 3409*0b57cec5SDimitry Andric } 3410*0b57cec5SDimitry Andric } 3411*0b57cec5SDimitry Andric 3412*0b57cec5SDimitry Andric // Verify misc. restrictions on specific instructions. 3413*0b57cec5SDimitry Andric if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32 || 3414*0b57cec5SDimitry Andric Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64) { 3415*0b57cec5SDimitry Andric const MachineOperand &Src0 = MI.getOperand(Src0Idx); 3416*0b57cec5SDimitry Andric const MachineOperand &Src1 = MI.getOperand(Src1Idx); 3417*0b57cec5SDimitry Andric const MachineOperand &Src2 = MI.getOperand(Src2Idx); 3418*0b57cec5SDimitry Andric if (Src0.isReg() && Src1.isReg() && Src2.isReg()) { 3419*0b57cec5SDimitry Andric if (!compareMachineOp(Src0, Src1) && 3420*0b57cec5SDimitry Andric !compareMachineOp(Src0, Src2)) { 3421*0b57cec5SDimitry Andric ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2"; 3422*0b57cec5SDimitry Andric return false; 3423*0b57cec5SDimitry Andric } 3424*0b57cec5SDimitry Andric } 3425*0b57cec5SDimitry Andric } 3426*0b57cec5SDimitry Andric 3427*0b57cec5SDimitry Andric if (isSOP2(MI) || isSOPC(MI)) { 3428*0b57cec5SDimitry Andric const MachineOperand &Src0 = MI.getOperand(Src0Idx); 3429*0b57cec5SDimitry Andric const MachineOperand &Src1 = MI.getOperand(Src1Idx); 3430*0b57cec5SDimitry Andric unsigned Immediates = 0; 3431*0b57cec5SDimitry Andric 3432*0b57cec5SDimitry Andric if (!Src0.isReg() && 3433*0b57cec5SDimitry Andric !isInlineConstant(Src0, Desc.OpInfo[Src0Idx].OperandType)) 3434*0b57cec5SDimitry Andric Immediates++; 3435*0b57cec5SDimitry Andric if (!Src1.isReg() && 3436*0b57cec5SDimitry Andric !isInlineConstant(Src1, Desc.OpInfo[Src1Idx].OperandType)) 3437*0b57cec5SDimitry Andric Immediates++; 3438*0b57cec5SDimitry Andric 3439*0b57cec5SDimitry Andric if (Immediates > 1) { 3440*0b57cec5SDimitry Andric ErrInfo = "SOP2/SOPC instruction requires too many immediate constants"; 3441*0b57cec5SDimitry Andric return false; 3442*0b57cec5SDimitry Andric } 3443*0b57cec5SDimitry Andric } 3444*0b57cec5SDimitry Andric 3445*0b57cec5SDimitry Andric if (isSOPK(MI)) { 3446*0b57cec5SDimitry Andric auto Op = getNamedOperand(MI, AMDGPU::OpName::simm16); 3447*0b57cec5SDimitry Andric if (Desc.isBranch()) { 3448*0b57cec5SDimitry Andric if (!Op->isMBB()) { 3449*0b57cec5SDimitry Andric ErrInfo = "invalid branch target for SOPK instruction"; 3450*0b57cec5SDimitry Andric return false; 3451*0b57cec5SDimitry Andric } 3452*0b57cec5SDimitry Andric } else { 3453*0b57cec5SDimitry Andric uint64_t Imm = Op->getImm(); 3454*0b57cec5SDimitry Andric if (sopkIsZext(MI)) { 3455*0b57cec5SDimitry Andric if (!isUInt<16>(Imm)) { 3456*0b57cec5SDimitry Andric ErrInfo = "invalid immediate for SOPK instruction"; 3457*0b57cec5SDimitry Andric return false; 3458*0b57cec5SDimitry Andric } 3459*0b57cec5SDimitry Andric } else { 3460*0b57cec5SDimitry Andric if (!isInt<16>(Imm)) { 3461*0b57cec5SDimitry Andric ErrInfo = "invalid immediate for SOPK instruction"; 3462*0b57cec5SDimitry Andric return false; 3463*0b57cec5SDimitry Andric } 3464*0b57cec5SDimitry Andric } 3465*0b57cec5SDimitry Andric } 3466*0b57cec5SDimitry Andric } 3467*0b57cec5SDimitry Andric 3468*0b57cec5SDimitry Andric if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 || 3469*0b57cec5SDimitry Andric Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 || 3470*0b57cec5SDimitry Andric Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 || 3471*0b57cec5SDimitry Andric Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) { 3472*0b57cec5SDimitry Andric const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 || 3473*0b57cec5SDimitry Andric Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64; 3474*0b57cec5SDimitry Andric 3475*0b57cec5SDimitry Andric const unsigned StaticNumOps = Desc.getNumOperands() + 3476*0b57cec5SDimitry Andric Desc.getNumImplicitUses(); 3477*0b57cec5SDimitry Andric const unsigned NumImplicitOps = IsDst ? 2 : 1; 3478*0b57cec5SDimitry Andric 3479*0b57cec5SDimitry Andric // Allow additional implicit operands. This allows a fixup done by the post 3480*0b57cec5SDimitry Andric // RA scheduler where the main implicit operand is killed and implicit-defs 3481*0b57cec5SDimitry Andric // are added for sub-registers that remain live after this instruction. 3482*0b57cec5SDimitry Andric if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) { 3483*0b57cec5SDimitry Andric ErrInfo = "missing implicit register operands"; 3484*0b57cec5SDimitry Andric return false; 3485*0b57cec5SDimitry Andric } 3486*0b57cec5SDimitry Andric 3487*0b57cec5SDimitry Andric const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst); 3488*0b57cec5SDimitry Andric if (IsDst) { 3489*0b57cec5SDimitry Andric if (!Dst->isUse()) { 3490*0b57cec5SDimitry Andric ErrInfo = "v_movreld_b32 vdst should be a use operand"; 3491*0b57cec5SDimitry Andric return false; 3492*0b57cec5SDimitry Andric } 3493*0b57cec5SDimitry Andric 3494*0b57cec5SDimitry Andric unsigned UseOpIdx; 3495*0b57cec5SDimitry Andric if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) || 3496*0b57cec5SDimitry Andric UseOpIdx != StaticNumOps + 1) { 3497*0b57cec5SDimitry Andric ErrInfo = "movrel implicit operands should be tied"; 3498*0b57cec5SDimitry Andric return false; 3499*0b57cec5SDimitry Andric } 3500*0b57cec5SDimitry Andric } 3501*0b57cec5SDimitry Andric 3502*0b57cec5SDimitry Andric const MachineOperand &Src0 = MI.getOperand(Src0Idx); 3503*0b57cec5SDimitry Andric const MachineOperand &ImpUse 3504*0b57cec5SDimitry Andric = MI.getOperand(StaticNumOps + NumImplicitOps - 1); 3505*0b57cec5SDimitry Andric if (!ImpUse.isReg() || !ImpUse.isUse() || 3506*0b57cec5SDimitry Andric !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) { 3507*0b57cec5SDimitry Andric ErrInfo = "src0 should be subreg of implicit vector use"; 3508*0b57cec5SDimitry Andric return false; 3509*0b57cec5SDimitry Andric } 3510*0b57cec5SDimitry Andric } 3511*0b57cec5SDimitry Andric 3512*0b57cec5SDimitry Andric // Make sure we aren't losing exec uses in the td files. This mostly requires 3513*0b57cec5SDimitry Andric // being careful when using let Uses to try to add other use registers. 3514*0b57cec5SDimitry Andric if (shouldReadExec(MI)) { 3515*0b57cec5SDimitry Andric if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) { 3516*0b57cec5SDimitry Andric ErrInfo = "VALU instruction does not implicitly read exec mask"; 3517*0b57cec5SDimitry Andric return false; 3518*0b57cec5SDimitry Andric } 3519*0b57cec5SDimitry Andric } 3520*0b57cec5SDimitry Andric 3521*0b57cec5SDimitry Andric if (isSMRD(MI)) { 3522*0b57cec5SDimitry Andric if (MI.mayStore()) { 3523*0b57cec5SDimitry Andric // The register offset form of scalar stores may only use m0 as the 3524*0b57cec5SDimitry Andric // soffset register. 3525*0b57cec5SDimitry Andric const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soff); 3526*0b57cec5SDimitry Andric if (Soff && Soff->getReg() != AMDGPU::M0) { 3527*0b57cec5SDimitry Andric ErrInfo = "scalar stores must use m0 as offset register"; 3528*0b57cec5SDimitry Andric return false; 3529*0b57cec5SDimitry Andric } 3530*0b57cec5SDimitry Andric } 3531*0b57cec5SDimitry Andric } 3532*0b57cec5SDimitry Andric 3533*0b57cec5SDimitry Andric if (isFLAT(MI) && !MF->getSubtarget<GCNSubtarget>().hasFlatInstOffsets()) { 3534*0b57cec5SDimitry Andric const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset); 3535*0b57cec5SDimitry Andric if (Offset->getImm() != 0) { 3536*0b57cec5SDimitry Andric ErrInfo = "subtarget does not support offsets in flat instructions"; 3537*0b57cec5SDimitry Andric return false; 3538*0b57cec5SDimitry Andric } 3539*0b57cec5SDimitry Andric } 3540*0b57cec5SDimitry Andric 3541*0b57cec5SDimitry Andric if (isMIMG(MI)) { 3542*0b57cec5SDimitry Andric const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim); 3543*0b57cec5SDimitry Andric if (DimOp) { 3544*0b57cec5SDimitry Andric int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode, 3545*0b57cec5SDimitry Andric AMDGPU::OpName::vaddr0); 3546*0b57cec5SDimitry Andric int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::srsrc); 3547*0b57cec5SDimitry Andric const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode); 3548*0b57cec5SDimitry Andric const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 3549*0b57cec5SDimitry Andric AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 3550*0b57cec5SDimitry Andric const AMDGPU::MIMGDimInfo *Dim = 3551*0b57cec5SDimitry Andric AMDGPU::getMIMGDimInfoByEncoding(DimOp->getImm()); 3552*0b57cec5SDimitry Andric 3553*0b57cec5SDimitry Andric if (!Dim) { 3554*0b57cec5SDimitry Andric ErrInfo = "dim is out of range"; 3555*0b57cec5SDimitry Andric return false; 3556*0b57cec5SDimitry Andric } 3557*0b57cec5SDimitry Andric 3558*0b57cec5SDimitry Andric bool IsNSA = SRsrcIdx - VAddr0Idx > 1; 3559*0b57cec5SDimitry Andric unsigned AddrWords = BaseOpcode->NumExtraArgs + 3560*0b57cec5SDimitry Andric (BaseOpcode->Gradients ? Dim->NumGradients : 0) + 3561*0b57cec5SDimitry Andric (BaseOpcode->Coordinates ? Dim->NumCoords : 0) + 3562*0b57cec5SDimitry Andric (BaseOpcode->LodOrClampOrMip ? 1 : 0); 3563*0b57cec5SDimitry Andric 3564*0b57cec5SDimitry Andric unsigned VAddrWords; 3565*0b57cec5SDimitry Andric if (IsNSA) { 3566*0b57cec5SDimitry Andric VAddrWords = SRsrcIdx - VAddr0Idx; 3567*0b57cec5SDimitry Andric } else { 3568*0b57cec5SDimitry Andric const TargetRegisterClass *RC = getOpRegClass(MI, VAddr0Idx); 3569*0b57cec5SDimitry Andric VAddrWords = MRI.getTargetRegisterInfo()->getRegSizeInBits(*RC) / 32; 3570*0b57cec5SDimitry Andric if (AddrWords > 8) 3571*0b57cec5SDimitry Andric AddrWords = 16; 3572*0b57cec5SDimitry Andric else if (AddrWords > 4) 3573*0b57cec5SDimitry Andric AddrWords = 8; 3574*0b57cec5SDimitry Andric else if (AddrWords == 3 && VAddrWords == 4) { 3575*0b57cec5SDimitry Andric // CodeGen uses the V4 variant of instructions for three addresses, 3576*0b57cec5SDimitry Andric // because the selection DAG does not support non-power-of-two types. 3577*0b57cec5SDimitry Andric AddrWords = 4; 3578*0b57cec5SDimitry Andric } 3579*0b57cec5SDimitry Andric } 3580*0b57cec5SDimitry Andric 3581*0b57cec5SDimitry Andric if (VAddrWords != AddrWords) { 3582*0b57cec5SDimitry Andric ErrInfo = "bad vaddr size"; 3583*0b57cec5SDimitry Andric return false; 3584*0b57cec5SDimitry Andric } 3585*0b57cec5SDimitry Andric } 3586*0b57cec5SDimitry Andric } 3587*0b57cec5SDimitry Andric 3588*0b57cec5SDimitry Andric const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl); 3589*0b57cec5SDimitry Andric if (DppCt) { 3590*0b57cec5SDimitry Andric using namespace AMDGPU::DPP; 3591*0b57cec5SDimitry Andric 3592*0b57cec5SDimitry Andric unsigned DC = DppCt->getImm(); 3593*0b57cec5SDimitry Andric if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 || 3594*0b57cec5SDimitry Andric DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST || 3595*0b57cec5SDimitry Andric (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) || 3596*0b57cec5SDimitry Andric (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) || 3597*0b57cec5SDimitry Andric (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) || 3598*0b57cec5SDimitry Andric (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) || 3599*0b57cec5SDimitry Andric (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) { 3600*0b57cec5SDimitry Andric ErrInfo = "Invalid dpp_ctrl value"; 3601*0b57cec5SDimitry Andric return false; 3602*0b57cec5SDimitry Andric } 3603*0b57cec5SDimitry Andric if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 && 3604*0b57cec5SDimitry Andric ST.getGeneration() >= AMDGPUSubtarget::GFX10) { 3605*0b57cec5SDimitry Andric ErrInfo = "Invalid dpp_ctrl value: " 3606*0b57cec5SDimitry Andric "wavefront shifts are not supported on GFX10+"; 3607*0b57cec5SDimitry Andric return false; 3608*0b57cec5SDimitry Andric } 3609*0b57cec5SDimitry Andric if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 && 3610*0b57cec5SDimitry Andric ST.getGeneration() >= AMDGPUSubtarget::GFX10) { 3611*0b57cec5SDimitry Andric ErrInfo = "Invalid dpp_ctrl value: " 3612*0b57cec5SDimitry Andric "broadcats are not supported on GFX10+"; 3613*0b57cec5SDimitry Andric return false; 3614*0b57cec5SDimitry Andric } 3615*0b57cec5SDimitry Andric if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST && 3616*0b57cec5SDimitry Andric ST.getGeneration() < AMDGPUSubtarget::GFX10) { 3617*0b57cec5SDimitry Andric ErrInfo = "Invalid dpp_ctrl value: " 3618*0b57cec5SDimitry Andric "row_share and row_xmask are not supported before GFX10"; 3619*0b57cec5SDimitry Andric return false; 3620*0b57cec5SDimitry Andric } 3621*0b57cec5SDimitry Andric } 3622*0b57cec5SDimitry Andric 3623*0b57cec5SDimitry Andric return true; 3624*0b57cec5SDimitry Andric } 3625*0b57cec5SDimitry Andric 3626*0b57cec5SDimitry Andric unsigned SIInstrInfo::getVALUOp(const MachineInstr &MI) const { 3627*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 3628*0b57cec5SDimitry Andric default: return AMDGPU::INSTRUCTION_LIST_END; 3629*0b57cec5SDimitry Andric case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE; 3630*0b57cec5SDimitry Andric case AMDGPU::COPY: return AMDGPU::COPY; 3631*0b57cec5SDimitry Andric case AMDGPU::PHI: return AMDGPU::PHI; 3632*0b57cec5SDimitry Andric case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG; 3633*0b57cec5SDimitry Andric case AMDGPU::WQM: return AMDGPU::WQM; 3634*0b57cec5SDimitry Andric case AMDGPU::WWM: return AMDGPU::WWM; 3635*0b57cec5SDimitry Andric case AMDGPU::S_MOV_B32: { 3636*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 3637*0b57cec5SDimitry Andric return MI.getOperand(1).isReg() || 3638*0b57cec5SDimitry Andric RI.isAGPR(MRI, MI.getOperand(0).getReg()) ? 3639*0b57cec5SDimitry Andric AMDGPU::COPY : AMDGPU::V_MOV_B32_e32; 3640*0b57cec5SDimitry Andric } 3641*0b57cec5SDimitry Andric case AMDGPU::S_ADD_I32: 3642*0b57cec5SDimitry Andric return ST.hasAddNoCarry() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_I32_e32; 3643*0b57cec5SDimitry Andric case AMDGPU::S_ADDC_U32: 3644*0b57cec5SDimitry Andric return AMDGPU::V_ADDC_U32_e32; 3645*0b57cec5SDimitry Andric case AMDGPU::S_SUB_I32: 3646*0b57cec5SDimitry Andric return ST.hasAddNoCarry() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_I32_e32; 3647*0b57cec5SDimitry Andric // FIXME: These are not consistently handled, and selected when the carry is 3648*0b57cec5SDimitry Andric // used. 3649*0b57cec5SDimitry Andric case AMDGPU::S_ADD_U32: 3650*0b57cec5SDimitry Andric return AMDGPU::V_ADD_I32_e32; 3651*0b57cec5SDimitry Andric case AMDGPU::S_SUB_U32: 3652*0b57cec5SDimitry Andric return AMDGPU::V_SUB_I32_e32; 3653*0b57cec5SDimitry Andric case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32; 3654*0b57cec5SDimitry Andric case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32; 3655*0b57cec5SDimitry Andric case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32; 3656*0b57cec5SDimitry Andric case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32; 3657*0b57cec5SDimitry Andric case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64; 3658*0b57cec5SDimitry Andric case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64; 3659*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64; 3660*0b57cec5SDimitry Andric case AMDGPU::S_XNOR_B32: 3661*0b57cec5SDimitry Andric return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END; 3662*0b57cec5SDimitry Andric case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64; 3663*0b57cec5SDimitry Andric case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64; 3664*0b57cec5SDimitry Andric case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64; 3665*0b57cec5SDimitry Andric case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64; 3666*0b57cec5SDimitry Andric case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32; 3667*0b57cec5SDimitry Andric case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64; 3668*0b57cec5SDimitry Andric case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32; 3669*0b57cec5SDimitry Andric case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64; 3670*0b57cec5SDimitry Andric case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32; 3671*0b57cec5SDimitry Andric case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64; 3672*0b57cec5SDimitry Andric case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32; 3673*0b57cec5SDimitry Andric case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32; 3674*0b57cec5SDimitry Andric case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32; 3675*0b57cec5SDimitry Andric case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32; 3676*0b57cec5SDimitry Andric case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64; 3677*0b57cec5SDimitry Andric case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32; 3678*0b57cec5SDimitry Andric case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32; 3679*0b57cec5SDimitry Andric case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32; 3680*0b57cec5SDimitry Andric case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e32; 3681*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e32; 3682*0b57cec5SDimitry Andric case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e32; 3683*0b57cec5SDimitry Andric case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e32; 3684*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e32; 3685*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e32; 3686*0b57cec5SDimitry Andric case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e32; 3687*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e32; 3688*0b57cec5SDimitry Andric case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e32; 3689*0b57cec5SDimitry Andric case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e32; 3690*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e32; 3691*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e32; 3692*0b57cec5SDimitry Andric case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e32; 3693*0b57cec5SDimitry Andric case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e32; 3694*0b57cec5SDimitry Andric case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64; 3695*0b57cec5SDimitry Andric case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32; 3696*0b57cec5SDimitry Andric case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32; 3697*0b57cec5SDimitry Andric case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64; 3698*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ; 3699*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ; 3700*0b57cec5SDimitry Andric } 3701*0b57cec5SDimitry Andric llvm_unreachable( 3702*0b57cec5SDimitry Andric "Unexpected scalar opcode without corresponding vector one!"); 3703*0b57cec5SDimitry Andric } 3704*0b57cec5SDimitry Andric 3705*0b57cec5SDimitry Andric const TargetRegisterClass *SIInstrInfo::getOpRegClass(const MachineInstr &MI, 3706*0b57cec5SDimitry Andric unsigned OpNo) const { 3707*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 3708*0b57cec5SDimitry Andric const MCInstrDesc &Desc = get(MI.getOpcode()); 3709*0b57cec5SDimitry Andric if (MI.isVariadic() || OpNo >= Desc.getNumOperands() || 3710*0b57cec5SDimitry Andric Desc.OpInfo[OpNo].RegClass == -1) { 3711*0b57cec5SDimitry Andric unsigned Reg = MI.getOperand(OpNo).getReg(); 3712*0b57cec5SDimitry Andric 3713*0b57cec5SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(Reg)) 3714*0b57cec5SDimitry Andric return MRI.getRegClass(Reg); 3715*0b57cec5SDimitry Andric return RI.getPhysRegClass(Reg); 3716*0b57cec5SDimitry Andric } 3717*0b57cec5SDimitry Andric 3718*0b57cec5SDimitry Andric unsigned RCID = Desc.OpInfo[OpNo].RegClass; 3719*0b57cec5SDimitry Andric return RI.getRegClass(RCID); 3720*0b57cec5SDimitry Andric } 3721*0b57cec5SDimitry Andric 3722*0b57cec5SDimitry Andric void SIInstrInfo::legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const { 3723*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = MI; 3724*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent(); 3725*0b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(OpIdx); 3726*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); 3727*0b57cec5SDimitry Andric const SIRegisterInfo *TRI = 3728*0b57cec5SDimitry Andric static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 3729*0b57cec5SDimitry Andric unsigned RCID = get(MI.getOpcode()).OpInfo[OpIdx].RegClass; 3730*0b57cec5SDimitry Andric const TargetRegisterClass *RC = RI.getRegClass(RCID); 3731*0b57cec5SDimitry Andric unsigned Size = TRI->getRegSizeInBits(*RC); 3732*0b57cec5SDimitry Andric unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO : AMDGPU::V_MOV_B32_e32; 3733*0b57cec5SDimitry Andric if (MO.isReg()) 3734*0b57cec5SDimitry Andric Opcode = AMDGPU::COPY; 3735*0b57cec5SDimitry Andric else if (RI.isSGPRClass(RC)) 3736*0b57cec5SDimitry Andric Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32; 3737*0b57cec5SDimitry Andric 3738*0b57cec5SDimitry Andric const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC); 3739*0b57cec5SDimitry Andric if (RI.getCommonSubClass(&AMDGPU::VReg_64RegClass, VRC)) 3740*0b57cec5SDimitry Andric VRC = &AMDGPU::VReg_64RegClass; 3741*0b57cec5SDimitry Andric else 3742*0b57cec5SDimitry Andric VRC = &AMDGPU::VGPR_32RegClass; 3743*0b57cec5SDimitry Andric 3744*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(VRC); 3745*0b57cec5SDimitry Andric DebugLoc DL = MBB->findDebugLoc(I); 3746*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), I, DL, get(Opcode), Reg).add(MO); 3747*0b57cec5SDimitry Andric MO.ChangeToRegister(Reg, false); 3748*0b57cec5SDimitry Andric } 3749*0b57cec5SDimitry Andric 3750*0b57cec5SDimitry Andric unsigned SIInstrInfo::buildExtractSubReg(MachineBasicBlock::iterator MI, 3751*0b57cec5SDimitry Andric MachineRegisterInfo &MRI, 3752*0b57cec5SDimitry Andric MachineOperand &SuperReg, 3753*0b57cec5SDimitry Andric const TargetRegisterClass *SuperRC, 3754*0b57cec5SDimitry Andric unsigned SubIdx, 3755*0b57cec5SDimitry Andric const TargetRegisterClass *SubRC) 3756*0b57cec5SDimitry Andric const { 3757*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI->getParent(); 3758*0b57cec5SDimitry Andric DebugLoc DL = MI->getDebugLoc(); 3759*0b57cec5SDimitry Andric unsigned SubReg = MRI.createVirtualRegister(SubRC); 3760*0b57cec5SDimitry Andric 3761*0b57cec5SDimitry Andric if (SuperReg.getSubReg() == AMDGPU::NoSubRegister) { 3762*0b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg) 3763*0b57cec5SDimitry Andric .addReg(SuperReg.getReg(), 0, SubIdx); 3764*0b57cec5SDimitry Andric return SubReg; 3765*0b57cec5SDimitry Andric } 3766*0b57cec5SDimitry Andric 3767*0b57cec5SDimitry Andric // Just in case the super register is itself a sub-register, copy it to a new 3768*0b57cec5SDimitry Andric // value so we don't need to worry about merging its subreg index with the 3769*0b57cec5SDimitry Andric // SubIdx passed to this function. The register coalescer should be able to 3770*0b57cec5SDimitry Andric // eliminate this extra copy. 3771*0b57cec5SDimitry Andric unsigned NewSuperReg = MRI.createVirtualRegister(SuperRC); 3772*0b57cec5SDimitry Andric 3773*0b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), NewSuperReg) 3774*0b57cec5SDimitry Andric .addReg(SuperReg.getReg(), 0, SuperReg.getSubReg()); 3775*0b57cec5SDimitry Andric 3776*0b57cec5SDimitry Andric BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg) 3777*0b57cec5SDimitry Andric .addReg(NewSuperReg, 0, SubIdx); 3778*0b57cec5SDimitry Andric 3779*0b57cec5SDimitry Andric return SubReg; 3780*0b57cec5SDimitry Andric } 3781*0b57cec5SDimitry Andric 3782*0b57cec5SDimitry Andric MachineOperand SIInstrInfo::buildExtractSubRegOrImm( 3783*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII, 3784*0b57cec5SDimitry Andric MachineRegisterInfo &MRI, 3785*0b57cec5SDimitry Andric MachineOperand &Op, 3786*0b57cec5SDimitry Andric const TargetRegisterClass *SuperRC, 3787*0b57cec5SDimitry Andric unsigned SubIdx, 3788*0b57cec5SDimitry Andric const TargetRegisterClass *SubRC) const { 3789*0b57cec5SDimitry Andric if (Op.isImm()) { 3790*0b57cec5SDimitry Andric if (SubIdx == AMDGPU::sub0) 3791*0b57cec5SDimitry Andric return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm())); 3792*0b57cec5SDimitry Andric if (SubIdx == AMDGPU::sub1) 3793*0b57cec5SDimitry Andric return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32)); 3794*0b57cec5SDimitry Andric 3795*0b57cec5SDimitry Andric llvm_unreachable("Unhandled register index for immediate"); 3796*0b57cec5SDimitry Andric } 3797*0b57cec5SDimitry Andric 3798*0b57cec5SDimitry Andric unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC, 3799*0b57cec5SDimitry Andric SubIdx, SubRC); 3800*0b57cec5SDimitry Andric return MachineOperand::CreateReg(SubReg, false); 3801*0b57cec5SDimitry Andric } 3802*0b57cec5SDimitry Andric 3803*0b57cec5SDimitry Andric // Change the order of operands from (0, 1, 2) to (0, 2, 1) 3804*0b57cec5SDimitry Andric void SIInstrInfo::swapOperands(MachineInstr &Inst) const { 3805*0b57cec5SDimitry Andric assert(Inst.getNumExplicitOperands() == 3); 3806*0b57cec5SDimitry Andric MachineOperand Op1 = Inst.getOperand(1); 3807*0b57cec5SDimitry Andric Inst.RemoveOperand(1); 3808*0b57cec5SDimitry Andric Inst.addOperand(Op1); 3809*0b57cec5SDimitry Andric } 3810*0b57cec5SDimitry Andric 3811*0b57cec5SDimitry Andric bool SIInstrInfo::isLegalRegOperand(const MachineRegisterInfo &MRI, 3812*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo, 3813*0b57cec5SDimitry Andric const MachineOperand &MO) const { 3814*0b57cec5SDimitry Andric if (!MO.isReg()) 3815*0b57cec5SDimitry Andric return false; 3816*0b57cec5SDimitry Andric 3817*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 3818*0b57cec5SDimitry Andric const TargetRegisterClass *RC = 3819*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(Reg) ? 3820*0b57cec5SDimitry Andric MRI.getRegClass(Reg) : 3821*0b57cec5SDimitry Andric RI.getPhysRegClass(Reg); 3822*0b57cec5SDimitry Andric 3823*0b57cec5SDimitry Andric const SIRegisterInfo *TRI = 3824*0b57cec5SDimitry Andric static_cast<const SIRegisterInfo*>(MRI.getTargetRegisterInfo()); 3825*0b57cec5SDimitry Andric RC = TRI->getSubRegClass(RC, MO.getSubReg()); 3826*0b57cec5SDimitry Andric 3827*0b57cec5SDimitry Andric // In order to be legal, the common sub-class must be equal to the 3828*0b57cec5SDimitry Andric // class of the current operand. For example: 3829*0b57cec5SDimitry Andric // 3830*0b57cec5SDimitry Andric // v_mov_b32 s0 ; Operand defined as vsrc_b32 3831*0b57cec5SDimitry Andric // ; RI.getCommonSubClass(s0,vsrc_b32) = sgpr ; LEGAL 3832*0b57cec5SDimitry Andric // 3833*0b57cec5SDimitry Andric // s_sendmsg 0, s0 ; Operand defined as m0reg 3834*0b57cec5SDimitry Andric // ; RI.getCommonSubClass(s0,m0reg) = m0reg ; NOT LEGAL 3835*0b57cec5SDimitry Andric 3836*0b57cec5SDimitry Andric return RI.getCommonSubClass(RC, RI.getRegClass(OpInfo.RegClass)) == RC; 3837*0b57cec5SDimitry Andric } 3838*0b57cec5SDimitry Andric 3839*0b57cec5SDimitry Andric bool SIInstrInfo::isLegalVSrcOperand(const MachineRegisterInfo &MRI, 3840*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo, 3841*0b57cec5SDimitry Andric const MachineOperand &MO) const { 3842*0b57cec5SDimitry Andric if (MO.isReg()) 3843*0b57cec5SDimitry Andric return isLegalRegOperand(MRI, OpInfo, MO); 3844*0b57cec5SDimitry Andric 3845*0b57cec5SDimitry Andric // Handle non-register types that are treated like immediates. 3846*0b57cec5SDimitry Andric assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal()); 3847*0b57cec5SDimitry Andric return true; 3848*0b57cec5SDimitry Andric } 3849*0b57cec5SDimitry Andric 3850*0b57cec5SDimitry Andric bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx, 3851*0b57cec5SDimitry Andric const MachineOperand *MO) const { 3852*0b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 3853*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 3854*0b57cec5SDimitry Andric const MCInstrDesc &InstDesc = MI.getDesc(); 3855*0b57cec5SDimitry Andric const MCOperandInfo &OpInfo = InstDesc.OpInfo[OpIdx]; 3856*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 3857*0b57cec5SDimitry Andric const TargetRegisterClass *DefinedRC = 3858*0b57cec5SDimitry Andric OpInfo.RegClass != -1 ? RI.getRegClass(OpInfo.RegClass) : nullptr; 3859*0b57cec5SDimitry Andric if (!MO) 3860*0b57cec5SDimitry Andric MO = &MI.getOperand(OpIdx); 3861*0b57cec5SDimitry Andric 3862*0b57cec5SDimitry Andric int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode()); 3863*0b57cec5SDimitry Andric int VOP3LiteralLimit = ST.hasVOP3Literal() ? 1 : 0; 3864*0b57cec5SDimitry Andric if (isVALU(MI) && usesConstantBus(MRI, *MO, OpInfo)) { 3865*0b57cec5SDimitry Andric if (isVOP3(MI) && isLiteralConstantLike(*MO, OpInfo) && !VOP3LiteralLimit--) 3866*0b57cec5SDimitry Andric return false; 3867*0b57cec5SDimitry Andric 3868*0b57cec5SDimitry Andric SmallDenseSet<RegSubRegPair> SGPRsUsed; 3869*0b57cec5SDimitry Andric if (MO->isReg()) 3870*0b57cec5SDimitry Andric SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg())); 3871*0b57cec5SDimitry Andric 3872*0b57cec5SDimitry Andric for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 3873*0b57cec5SDimitry Andric if (i == OpIdx) 3874*0b57cec5SDimitry Andric continue; 3875*0b57cec5SDimitry Andric const MachineOperand &Op = MI.getOperand(i); 3876*0b57cec5SDimitry Andric if (Op.isReg()) { 3877*0b57cec5SDimitry Andric RegSubRegPair SGPR(Op.getReg(), Op.getSubReg()); 3878*0b57cec5SDimitry Andric if (!SGPRsUsed.count(SGPR) && 3879*0b57cec5SDimitry Andric usesConstantBus(MRI, Op, InstDesc.OpInfo[i])) { 3880*0b57cec5SDimitry Andric if (--ConstantBusLimit <= 0) 3881*0b57cec5SDimitry Andric return false; 3882*0b57cec5SDimitry Andric SGPRsUsed.insert(SGPR); 3883*0b57cec5SDimitry Andric } 3884*0b57cec5SDimitry Andric } else if (InstDesc.OpInfo[i].OperandType == AMDGPU::OPERAND_KIMM32) { 3885*0b57cec5SDimitry Andric if (--ConstantBusLimit <= 0) 3886*0b57cec5SDimitry Andric return false; 3887*0b57cec5SDimitry Andric } else if (isVOP3(MI) && AMDGPU::isSISrcOperand(InstDesc, i) && 3888*0b57cec5SDimitry Andric isLiteralConstantLike(Op, InstDesc.OpInfo[i])) { 3889*0b57cec5SDimitry Andric if (!VOP3LiteralLimit--) 3890*0b57cec5SDimitry Andric return false; 3891*0b57cec5SDimitry Andric if (--ConstantBusLimit <= 0) 3892*0b57cec5SDimitry Andric return false; 3893*0b57cec5SDimitry Andric } 3894*0b57cec5SDimitry Andric } 3895*0b57cec5SDimitry Andric } 3896*0b57cec5SDimitry Andric 3897*0b57cec5SDimitry Andric if (MO->isReg()) { 3898*0b57cec5SDimitry Andric assert(DefinedRC); 3899*0b57cec5SDimitry Andric return isLegalRegOperand(MRI, OpInfo, *MO); 3900*0b57cec5SDimitry Andric } 3901*0b57cec5SDimitry Andric 3902*0b57cec5SDimitry Andric // Handle non-register types that are treated like immediates. 3903*0b57cec5SDimitry Andric assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal()); 3904*0b57cec5SDimitry Andric 3905*0b57cec5SDimitry Andric if (!DefinedRC) { 3906*0b57cec5SDimitry Andric // This operand expects an immediate. 3907*0b57cec5SDimitry Andric return true; 3908*0b57cec5SDimitry Andric } 3909*0b57cec5SDimitry Andric 3910*0b57cec5SDimitry Andric return isImmOperandLegal(MI, OpIdx, *MO); 3911*0b57cec5SDimitry Andric } 3912*0b57cec5SDimitry Andric 3913*0b57cec5SDimitry Andric void SIInstrInfo::legalizeOperandsVOP2(MachineRegisterInfo &MRI, 3914*0b57cec5SDimitry Andric MachineInstr &MI) const { 3915*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 3916*0b57cec5SDimitry Andric const MCInstrDesc &InstrDesc = get(Opc); 3917*0b57cec5SDimitry Andric 3918*0b57cec5SDimitry Andric int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3919*0b57cec5SDimitry Andric MachineOperand &Src0 = MI.getOperand(Src0Idx); 3920*0b57cec5SDimitry Andric 3921*0b57cec5SDimitry Andric int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1); 3922*0b57cec5SDimitry Andric MachineOperand &Src1 = MI.getOperand(Src1Idx); 3923*0b57cec5SDimitry Andric 3924*0b57cec5SDimitry Andric // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32 3925*0b57cec5SDimitry Andric // we need to only have one constant bus use before GFX10. 3926*0b57cec5SDimitry Andric bool HasImplicitSGPR = findImplicitSGPRRead(MI) != AMDGPU::NoRegister; 3927*0b57cec5SDimitry Andric if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && 3928*0b57cec5SDimitry Andric Src0.isReg() && (RI.isSGPRReg(MRI, Src0.getReg()) || 3929*0b57cec5SDimitry Andric isLiteralConstantLike(Src0, InstrDesc.OpInfo[Src0Idx]))) 3930*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src0Idx); 3931*0b57cec5SDimitry Andric 3932*0b57cec5SDimitry Andric // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for 3933*0b57cec5SDimitry Andric // both the value to write (src0) and lane select (src1). Fix up non-SGPR 3934*0b57cec5SDimitry Andric // src0/src1 with V_READFIRSTLANE. 3935*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_WRITELANE_B32) { 3936*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 3937*0b57cec5SDimitry Andric if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) { 3938*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 3939*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg) 3940*0b57cec5SDimitry Andric .add(Src0); 3941*0b57cec5SDimitry Andric Src0.ChangeToRegister(Reg, false); 3942*0b57cec5SDimitry Andric } 3943*0b57cec5SDimitry Andric if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) { 3944*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 3945*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 3946*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg) 3947*0b57cec5SDimitry Andric .add(Src1); 3948*0b57cec5SDimitry Andric Src1.ChangeToRegister(Reg, false); 3949*0b57cec5SDimitry Andric } 3950*0b57cec5SDimitry Andric return; 3951*0b57cec5SDimitry Andric } 3952*0b57cec5SDimitry Andric 3953*0b57cec5SDimitry Andric // No VOP2 instructions support AGPRs. 3954*0b57cec5SDimitry Andric if (Src0.isReg() && RI.isAGPR(MRI, Src0.getReg())) 3955*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src0Idx); 3956*0b57cec5SDimitry Andric 3957*0b57cec5SDimitry Andric if (Src1.isReg() && RI.isAGPR(MRI, Src1.getReg())) 3958*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src1Idx); 3959*0b57cec5SDimitry Andric 3960*0b57cec5SDimitry Andric // VOP2 src0 instructions support all operand types, so we don't need to check 3961*0b57cec5SDimitry Andric // their legality. If src1 is already legal, we don't need to do anything. 3962*0b57cec5SDimitry Andric if (isLegalRegOperand(MRI, InstrDesc.OpInfo[Src1Idx], Src1)) 3963*0b57cec5SDimitry Andric return; 3964*0b57cec5SDimitry Andric 3965*0b57cec5SDimitry Andric // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for 3966*0b57cec5SDimitry Andric // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane 3967*0b57cec5SDimitry Andric // select is uniform. 3968*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() && 3969*0b57cec5SDimitry Andric RI.isVGPR(MRI, Src1.getReg())) { 3970*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 3971*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 3972*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg) 3973*0b57cec5SDimitry Andric .add(Src1); 3974*0b57cec5SDimitry Andric Src1.ChangeToRegister(Reg, false); 3975*0b57cec5SDimitry Andric return; 3976*0b57cec5SDimitry Andric } 3977*0b57cec5SDimitry Andric 3978*0b57cec5SDimitry Andric // We do not use commuteInstruction here because it is too aggressive and will 3979*0b57cec5SDimitry Andric // commute if it is possible. We only want to commute here if it improves 3980*0b57cec5SDimitry Andric // legality. This can be called a fairly large number of times so don't waste 3981*0b57cec5SDimitry Andric // compile time pointlessly swapping and checking legality again. 3982*0b57cec5SDimitry Andric if (HasImplicitSGPR || !MI.isCommutable()) { 3983*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src1Idx); 3984*0b57cec5SDimitry Andric return; 3985*0b57cec5SDimitry Andric } 3986*0b57cec5SDimitry Andric 3987*0b57cec5SDimitry Andric // If src0 can be used as src1, commuting will make the operands legal. 3988*0b57cec5SDimitry Andric // Otherwise we have to give up and insert a move. 3989*0b57cec5SDimitry Andric // 3990*0b57cec5SDimitry Andric // TODO: Other immediate-like operand kinds could be commuted if there was a 3991*0b57cec5SDimitry Andric // MachineOperand::ChangeTo* for them. 3992*0b57cec5SDimitry Andric if ((!Src1.isImm() && !Src1.isReg()) || 3993*0b57cec5SDimitry Andric !isLegalRegOperand(MRI, InstrDesc.OpInfo[Src1Idx], Src0)) { 3994*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src1Idx); 3995*0b57cec5SDimitry Andric return; 3996*0b57cec5SDimitry Andric } 3997*0b57cec5SDimitry Andric 3998*0b57cec5SDimitry Andric int CommutedOpc = commuteOpcode(MI); 3999*0b57cec5SDimitry Andric if (CommutedOpc == -1) { 4000*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Src1Idx); 4001*0b57cec5SDimitry Andric return; 4002*0b57cec5SDimitry Andric } 4003*0b57cec5SDimitry Andric 4004*0b57cec5SDimitry Andric MI.setDesc(get(CommutedOpc)); 4005*0b57cec5SDimitry Andric 4006*0b57cec5SDimitry Andric unsigned Src0Reg = Src0.getReg(); 4007*0b57cec5SDimitry Andric unsigned Src0SubReg = Src0.getSubReg(); 4008*0b57cec5SDimitry Andric bool Src0Kill = Src0.isKill(); 4009*0b57cec5SDimitry Andric 4010*0b57cec5SDimitry Andric if (Src1.isImm()) 4011*0b57cec5SDimitry Andric Src0.ChangeToImmediate(Src1.getImm()); 4012*0b57cec5SDimitry Andric else if (Src1.isReg()) { 4013*0b57cec5SDimitry Andric Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill()); 4014*0b57cec5SDimitry Andric Src0.setSubReg(Src1.getSubReg()); 4015*0b57cec5SDimitry Andric } else 4016*0b57cec5SDimitry Andric llvm_unreachable("Should only have register or immediate operands"); 4017*0b57cec5SDimitry Andric 4018*0b57cec5SDimitry Andric Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill); 4019*0b57cec5SDimitry Andric Src1.setSubReg(Src0SubReg); 4020*0b57cec5SDimitry Andric fixImplicitOperands(MI); 4021*0b57cec5SDimitry Andric } 4022*0b57cec5SDimitry Andric 4023*0b57cec5SDimitry Andric // Legalize VOP3 operands. All operand types are supported for any operand 4024*0b57cec5SDimitry Andric // but only one literal constant and only starting from GFX10. 4025*0b57cec5SDimitry Andric void SIInstrInfo::legalizeOperandsVOP3(MachineRegisterInfo &MRI, 4026*0b57cec5SDimitry Andric MachineInstr &MI) const { 4027*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 4028*0b57cec5SDimitry Andric 4029*0b57cec5SDimitry Andric int VOP3Idx[3] = { 4030*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0), 4031*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1), 4032*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2) 4033*0b57cec5SDimitry Andric }; 4034*0b57cec5SDimitry Andric 4035*0b57cec5SDimitry Andric if (Opc == AMDGPU::V_PERMLANE16_B32 || 4036*0b57cec5SDimitry Andric Opc == AMDGPU::V_PERMLANEX16_B32) { 4037*0b57cec5SDimitry Andric // src1 and src2 must be scalar 4038*0b57cec5SDimitry Andric MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]); 4039*0b57cec5SDimitry Andric MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]); 4040*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 4041*0b57cec5SDimitry Andric if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) { 4042*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 4043*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg) 4044*0b57cec5SDimitry Andric .add(Src1); 4045*0b57cec5SDimitry Andric Src1.ChangeToRegister(Reg, false); 4046*0b57cec5SDimitry Andric } 4047*0b57cec5SDimitry Andric if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) { 4048*0b57cec5SDimitry Andric unsigned Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 4049*0b57cec5SDimitry Andric BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg) 4050*0b57cec5SDimitry Andric .add(Src2); 4051*0b57cec5SDimitry Andric Src2.ChangeToRegister(Reg, false); 4052*0b57cec5SDimitry Andric } 4053*0b57cec5SDimitry Andric } 4054*0b57cec5SDimitry Andric 4055*0b57cec5SDimitry Andric // Find the one SGPR operand we are allowed to use. 4056*0b57cec5SDimitry Andric int ConstantBusLimit = ST.getConstantBusLimit(Opc); 4057*0b57cec5SDimitry Andric int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0; 4058*0b57cec5SDimitry Andric SmallDenseSet<unsigned> SGPRsUsed; 4059*0b57cec5SDimitry Andric unsigned SGPRReg = findUsedSGPR(MI, VOP3Idx); 4060*0b57cec5SDimitry Andric if (SGPRReg != AMDGPU::NoRegister) { 4061*0b57cec5SDimitry Andric SGPRsUsed.insert(SGPRReg); 4062*0b57cec5SDimitry Andric --ConstantBusLimit; 4063*0b57cec5SDimitry Andric } 4064*0b57cec5SDimitry Andric 4065*0b57cec5SDimitry Andric for (unsigned i = 0; i < 3; ++i) { 4066*0b57cec5SDimitry Andric int Idx = VOP3Idx[i]; 4067*0b57cec5SDimitry Andric if (Idx == -1) 4068*0b57cec5SDimitry Andric break; 4069*0b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(Idx); 4070*0b57cec5SDimitry Andric 4071*0b57cec5SDimitry Andric if (!MO.isReg()) { 4072*0b57cec5SDimitry Andric if (!isLiteralConstantLike(MO, get(Opc).OpInfo[Idx])) 4073*0b57cec5SDimitry Andric continue; 4074*0b57cec5SDimitry Andric 4075*0b57cec5SDimitry Andric if (LiteralLimit > 0 && ConstantBusLimit > 0) { 4076*0b57cec5SDimitry Andric --LiteralLimit; 4077*0b57cec5SDimitry Andric --ConstantBusLimit; 4078*0b57cec5SDimitry Andric continue; 4079*0b57cec5SDimitry Andric } 4080*0b57cec5SDimitry Andric 4081*0b57cec5SDimitry Andric --LiteralLimit; 4082*0b57cec5SDimitry Andric --ConstantBusLimit; 4083*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Idx); 4084*0b57cec5SDimitry Andric continue; 4085*0b57cec5SDimitry Andric } 4086*0b57cec5SDimitry Andric 4087*0b57cec5SDimitry Andric if (RI.hasAGPRs(MRI.getRegClass(MO.getReg())) && 4088*0b57cec5SDimitry Andric !isOperandLegal(MI, Idx, &MO)) { 4089*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Idx); 4090*0b57cec5SDimitry Andric continue; 4091*0b57cec5SDimitry Andric } 4092*0b57cec5SDimitry Andric 4093*0b57cec5SDimitry Andric if (!RI.isSGPRClass(MRI.getRegClass(MO.getReg()))) 4094*0b57cec5SDimitry Andric continue; // VGPRs are legal 4095*0b57cec5SDimitry Andric 4096*0b57cec5SDimitry Andric // We can use one SGPR in each VOP3 instruction prior to GFX10 4097*0b57cec5SDimitry Andric // and two starting from GFX10. 4098*0b57cec5SDimitry Andric if (SGPRsUsed.count(MO.getReg())) 4099*0b57cec5SDimitry Andric continue; 4100*0b57cec5SDimitry Andric if (ConstantBusLimit > 0) { 4101*0b57cec5SDimitry Andric SGPRsUsed.insert(MO.getReg()); 4102*0b57cec5SDimitry Andric --ConstantBusLimit; 4103*0b57cec5SDimitry Andric continue; 4104*0b57cec5SDimitry Andric } 4105*0b57cec5SDimitry Andric 4106*0b57cec5SDimitry Andric // If we make it this far, then the operand is not legal and we must 4107*0b57cec5SDimitry Andric // legalize it. 4108*0b57cec5SDimitry Andric legalizeOpWithMove(MI, Idx); 4109*0b57cec5SDimitry Andric } 4110*0b57cec5SDimitry Andric } 4111*0b57cec5SDimitry Andric 4112*0b57cec5SDimitry Andric unsigned SIInstrInfo::readlaneVGPRToSGPR(unsigned SrcReg, MachineInstr &UseMI, 4113*0b57cec5SDimitry Andric MachineRegisterInfo &MRI) const { 4114*0b57cec5SDimitry Andric const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg); 4115*0b57cec5SDimitry Andric const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC); 4116*0b57cec5SDimitry Andric unsigned DstReg = MRI.createVirtualRegister(SRC); 4117*0b57cec5SDimitry Andric unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32; 4118*0b57cec5SDimitry Andric 4119*0b57cec5SDimitry Andric if (RI.hasAGPRs(VRC)) { 4120*0b57cec5SDimitry Andric VRC = RI.getEquivalentVGPRClass(VRC); 4121*0b57cec5SDimitry Andric unsigned NewSrcReg = MRI.createVirtualRegister(VRC); 4122*0b57cec5SDimitry Andric BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(), 4123*0b57cec5SDimitry Andric get(TargetOpcode::COPY), NewSrcReg) 4124*0b57cec5SDimitry Andric .addReg(SrcReg); 4125*0b57cec5SDimitry Andric SrcReg = NewSrcReg; 4126*0b57cec5SDimitry Andric } 4127*0b57cec5SDimitry Andric 4128*0b57cec5SDimitry Andric if (SubRegs == 1) { 4129*0b57cec5SDimitry Andric BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(), 4130*0b57cec5SDimitry Andric get(AMDGPU::V_READFIRSTLANE_B32), DstReg) 4131*0b57cec5SDimitry Andric .addReg(SrcReg); 4132*0b57cec5SDimitry Andric return DstReg; 4133*0b57cec5SDimitry Andric } 4134*0b57cec5SDimitry Andric 4135*0b57cec5SDimitry Andric SmallVector<unsigned, 8> SRegs; 4136*0b57cec5SDimitry Andric for (unsigned i = 0; i < SubRegs; ++i) { 4137*0b57cec5SDimitry Andric unsigned SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4138*0b57cec5SDimitry Andric BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(), 4139*0b57cec5SDimitry Andric get(AMDGPU::V_READFIRSTLANE_B32), SGPR) 4140*0b57cec5SDimitry Andric .addReg(SrcReg, 0, RI.getSubRegFromChannel(i)); 4141*0b57cec5SDimitry Andric SRegs.push_back(SGPR); 4142*0b57cec5SDimitry Andric } 4143*0b57cec5SDimitry Andric 4144*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 4145*0b57cec5SDimitry Andric BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(), 4146*0b57cec5SDimitry Andric get(AMDGPU::REG_SEQUENCE), DstReg); 4147*0b57cec5SDimitry Andric for (unsigned i = 0; i < SubRegs; ++i) { 4148*0b57cec5SDimitry Andric MIB.addReg(SRegs[i]); 4149*0b57cec5SDimitry Andric MIB.addImm(RI.getSubRegFromChannel(i)); 4150*0b57cec5SDimitry Andric } 4151*0b57cec5SDimitry Andric return DstReg; 4152*0b57cec5SDimitry Andric } 4153*0b57cec5SDimitry Andric 4154*0b57cec5SDimitry Andric void SIInstrInfo::legalizeOperandsSMRD(MachineRegisterInfo &MRI, 4155*0b57cec5SDimitry Andric MachineInstr &MI) const { 4156*0b57cec5SDimitry Andric 4157*0b57cec5SDimitry Andric // If the pointer is store in VGPRs, then we need to move them to 4158*0b57cec5SDimitry Andric // SGPRs using v_readfirstlane. This is safe because we only select 4159*0b57cec5SDimitry Andric // loads with uniform pointers to SMRD instruction so we know the 4160*0b57cec5SDimitry Andric // pointer value is uniform. 4161*0b57cec5SDimitry Andric MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase); 4162*0b57cec5SDimitry Andric if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) { 4163*0b57cec5SDimitry Andric unsigned SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI); 4164*0b57cec5SDimitry Andric SBase->setReg(SGPR); 4165*0b57cec5SDimitry Andric } 4166*0b57cec5SDimitry Andric MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soff); 4167*0b57cec5SDimitry Andric if (SOff && !RI.isSGPRClass(MRI.getRegClass(SOff->getReg()))) { 4168*0b57cec5SDimitry Andric unsigned SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI); 4169*0b57cec5SDimitry Andric SOff->setReg(SGPR); 4170*0b57cec5SDimitry Andric } 4171*0b57cec5SDimitry Andric } 4172*0b57cec5SDimitry Andric 4173*0b57cec5SDimitry Andric void SIInstrInfo::legalizeGenericOperand(MachineBasicBlock &InsertMBB, 4174*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 4175*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 4176*0b57cec5SDimitry Andric MachineOperand &Op, 4177*0b57cec5SDimitry Andric MachineRegisterInfo &MRI, 4178*0b57cec5SDimitry Andric const DebugLoc &DL) const { 4179*0b57cec5SDimitry Andric unsigned OpReg = Op.getReg(); 4180*0b57cec5SDimitry Andric unsigned OpSubReg = Op.getSubReg(); 4181*0b57cec5SDimitry Andric 4182*0b57cec5SDimitry Andric const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg( 4183*0b57cec5SDimitry Andric RI.getRegClassForReg(MRI, OpReg), OpSubReg); 4184*0b57cec5SDimitry Andric 4185*0b57cec5SDimitry Andric // Check if operand is already the correct register class. 4186*0b57cec5SDimitry Andric if (DstRC == OpRC) 4187*0b57cec5SDimitry Andric return; 4188*0b57cec5SDimitry Andric 4189*0b57cec5SDimitry Andric unsigned DstReg = MRI.createVirtualRegister(DstRC); 4190*0b57cec5SDimitry Andric MachineInstr *Copy = 4191*0b57cec5SDimitry Andric BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg).add(Op); 4192*0b57cec5SDimitry Andric 4193*0b57cec5SDimitry Andric Op.setReg(DstReg); 4194*0b57cec5SDimitry Andric Op.setSubReg(0); 4195*0b57cec5SDimitry Andric 4196*0b57cec5SDimitry Andric MachineInstr *Def = MRI.getVRegDef(OpReg); 4197*0b57cec5SDimitry Andric if (!Def) 4198*0b57cec5SDimitry Andric return; 4199*0b57cec5SDimitry Andric 4200*0b57cec5SDimitry Andric // Try to eliminate the copy if it is copying an immediate value. 4201*0b57cec5SDimitry Andric if (Def->isMoveImmediate()) 4202*0b57cec5SDimitry Andric FoldImmediate(*Copy, *Def, OpReg, &MRI); 4203*0b57cec5SDimitry Andric } 4204*0b57cec5SDimitry Andric 4205*0b57cec5SDimitry Andric // Emit the actual waterfall loop, executing the wrapped instruction for each 4206*0b57cec5SDimitry Andric // unique value of \p Rsrc across all lanes. In the best case we execute 1 4207*0b57cec5SDimitry Andric // iteration, in the worst case we execute 64 (once per lane). 4208*0b57cec5SDimitry Andric static void 4209*0b57cec5SDimitry Andric emitLoadSRsrcFromVGPRLoop(const SIInstrInfo &TII, MachineRegisterInfo &MRI, 4210*0b57cec5SDimitry Andric MachineBasicBlock &OrigBB, MachineBasicBlock &LoopBB, 4211*0b57cec5SDimitry Andric const DebugLoc &DL, MachineOperand &Rsrc) { 4212*0b57cec5SDimitry Andric MachineFunction &MF = *OrigBB.getParent(); 4213*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 4214*0b57cec5SDimitry Andric const SIRegisterInfo *TRI = ST.getRegisterInfo(); 4215*0b57cec5SDimitry Andric unsigned Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC; 4216*0b57cec5SDimitry Andric unsigned SaveExecOpc = 4217*0b57cec5SDimitry Andric ST.isWave32() ? AMDGPU::S_AND_SAVEEXEC_B32 : AMDGPU::S_AND_SAVEEXEC_B64; 4218*0b57cec5SDimitry Andric unsigned XorTermOpc = 4219*0b57cec5SDimitry Andric ST.isWave32() ? AMDGPU::S_XOR_B32_term : AMDGPU::S_XOR_B64_term; 4220*0b57cec5SDimitry Andric unsigned AndOpc = 4221*0b57cec5SDimitry Andric ST.isWave32() ? AMDGPU::S_AND_B32 : AMDGPU::S_AND_B64; 4222*0b57cec5SDimitry Andric const auto *BoolXExecRC = TRI->getRegClass(AMDGPU::SReg_1_XEXECRegClassID); 4223*0b57cec5SDimitry Andric 4224*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = LoopBB.begin(); 4225*0b57cec5SDimitry Andric 4226*0b57cec5SDimitry Andric unsigned VRsrc = Rsrc.getReg(); 4227*0b57cec5SDimitry Andric unsigned VRsrcUndef = getUndefRegState(Rsrc.isUndef()); 4228*0b57cec5SDimitry Andric 4229*0b57cec5SDimitry Andric unsigned SaveExec = MRI.createVirtualRegister(BoolXExecRC); 4230*0b57cec5SDimitry Andric unsigned CondReg0 = MRI.createVirtualRegister(BoolXExecRC); 4231*0b57cec5SDimitry Andric unsigned CondReg1 = MRI.createVirtualRegister(BoolXExecRC); 4232*0b57cec5SDimitry Andric unsigned AndCond = MRI.createVirtualRegister(BoolXExecRC); 4233*0b57cec5SDimitry Andric unsigned SRsrcSub0 = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4234*0b57cec5SDimitry Andric unsigned SRsrcSub1 = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4235*0b57cec5SDimitry Andric unsigned SRsrcSub2 = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4236*0b57cec5SDimitry Andric unsigned SRsrcSub3 = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4237*0b57cec5SDimitry Andric unsigned SRsrc = MRI.createVirtualRegister(&AMDGPU::SReg_128RegClass); 4238*0b57cec5SDimitry Andric 4239*0b57cec5SDimitry Andric // Beginning of the loop, read the next Rsrc variant. 4240*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), SRsrcSub0) 4241*0b57cec5SDimitry Andric .addReg(VRsrc, VRsrcUndef, AMDGPU::sub0); 4242*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), SRsrcSub1) 4243*0b57cec5SDimitry Andric .addReg(VRsrc, VRsrcUndef, AMDGPU::sub1); 4244*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), SRsrcSub2) 4245*0b57cec5SDimitry Andric .addReg(VRsrc, VRsrcUndef, AMDGPU::sub2); 4246*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), SRsrcSub3) 4247*0b57cec5SDimitry Andric .addReg(VRsrc, VRsrcUndef, AMDGPU::sub3); 4248*0b57cec5SDimitry Andric 4249*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SRsrc) 4250*0b57cec5SDimitry Andric .addReg(SRsrcSub0) 4251*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 4252*0b57cec5SDimitry Andric .addReg(SRsrcSub1) 4253*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1) 4254*0b57cec5SDimitry Andric .addReg(SRsrcSub2) 4255*0b57cec5SDimitry Andric .addImm(AMDGPU::sub2) 4256*0b57cec5SDimitry Andric .addReg(SRsrcSub3) 4257*0b57cec5SDimitry Andric .addImm(AMDGPU::sub3); 4258*0b57cec5SDimitry Andric 4259*0b57cec5SDimitry Andric // Update Rsrc operand to use the SGPR Rsrc. 4260*0b57cec5SDimitry Andric Rsrc.setReg(SRsrc); 4261*0b57cec5SDimitry Andric Rsrc.setIsKill(true); 4262*0b57cec5SDimitry Andric 4263*0b57cec5SDimitry Andric // Identify all lanes with identical Rsrc operands in their VGPRs. 4264*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), CondReg0) 4265*0b57cec5SDimitry Andric .addReg(SRsrc, 0, AMDGPU::sub0_sub1) 4266*0b57cec5SDimitry Andric .addReg(VRsrc, 0, AMDGPU::sub0_sub1); 4267*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), CondReg1) 4268*0b57cec5SDimitry Andric .addReg(SRsrc, 0, AMDGPU::sub2_sub3) 4269*0b57cec5SDimitry Andric .addReg(VRsrc, 0, AMDGPU::sub2_sub3); 4270*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AndOpc), AndCond) 4271*0b57cec5SDimitry Andric .addReg(CondReg0) 4272*0b57cec5SDimitry Andric .addReg(CondReg1); 4273*0b57cec5SDimitry Andric 4274*0b57cec5SDimitry Andric MRI.setSimpleHint(SaveExec, AndCond); 4275*0b57cec5SDimitry Andric 4276*0b57cec5SDimitry Andric // Update EXEC to matching lanes, saving original to SaveExec. 4277*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(SaveExecOpc), SaveExec) 4278*0b57cec5SDimitry Andric .addReg(AndCond, RegState::Kill); 4279*0b57cec5SDimitry Andric 4280*0b57cec5SDimitry Andric // The original instruction is here; we insert the terminators after it. 4281*0b57cec5SDimitry Andric I = LoopBB.end(); 4282*0b57cec5SDimitry Andric 4283*0b57cec5SDimitry Andric // Update EXEC, switch all done bits to 0 and all todo bits to 1. 4284*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(XorTermOpc), Exec) 4285*0b57cec5SDimitry Andric .addReg(Exec) 4286*0b57cec5SDimitry Andric .addReg(SaveExec); 4287*0b57cec5SDimitry Andric BuildMI(LoopBB, I, DL, TII.get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(&LoopBB); 4288*0b57cec5SDimitry Andric } 4289*0b57cec5SDimitry Andric 4290*0b57cec5SDimitry Andric // Build a waterfall loop around \p MI, replacing the VGPR \p Rsrc register 4291*0b57cec5SDimitry Andric // with SGPRs by iterating over all unique values across all lanes. 4292*0b57cec5SDimitry Andric static void loadSRsrcFromVGPR(const SIInstrInfo &TII, MachineInstr &MI, 4293*0b57cec5SDimitry Andric MachineOperand &Rsrc, MachineDominatorTree *MDT) { 4294*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 4295*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 4296*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); 4297*0b57cec5SDimitry Andric const SIRegisterInfo *TRI = ST.getRegisterInfo(); 4298*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 4299*0b57cec5SDimitry Andric MachineBasicBlock::iterator I(&MI); 4300*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 4301*0b57cec5SDimitry Andric unsigned Exec = ST.isWave32() ? AMDGPU::EXEC_LO : AMDGPU::EXEC; 4302*0b57cec5SDimitry Andric unsigned MovExecOpc = ST.isWave32() ? AMDGPU::S_MOV_B32 : AMDGPU::S_MOV_B64; 4303*0b57cec5SDimitry Andric const auto *BoolXExecRC = TRI->getRegClass(AMDGPU::SReg_1_XEXECRegClassID); 4304*0b57cec5SDimitry Andric 4305*0b57cec5SDimitry Andric unsigned SaveExec = MRI.createVirtualRegister(BoolXExecRC); 4306*0b57cec5SDimitry Andric 4307*0b57cec5SDimitry Andric // Save the EXEC mask 4308*0b57cec5SDimitry Andric BuildMI(MBB, I, DL, TII.get(MovExecOpc), SaveExec).addReg(Exec); 4309*0b57cec5SDimitry Andric 4310*0b57cec5SDimitry Andric // Killed uses in the instruction we are waterfalling around will be 4311*0b57cec5SDimitry Andric // incorrect due to the added control-flow. 4312*0b57cec5SDimitry Andric for (auto &MO : MI.uses()) { 4313*0b57cec5SDimitry Andric if (MO.isReg() && MO.isUse()) { 4314*0b57cec5SDimitry Andric MRI.clearKillFlags(MO.getReg()); 4315*0b57cec5SDimitry Andric } 4316*0b57cec5SDimitry Andric } 4317*0b57cec5SDimitry Andric 4318*0b57cec5SDimitry Andric // To insert the loop we need to split the block. Move everything after this 4319*0b57cec5SDimitry Andric // point to a new block, and insert a new empty block between the two. 4320*0b57cec5SDimitry Andric MachineBasicBlock *LoopBB = MF.CreateMachineBasicBlock(); 4321*0b57cec5SDimitry Andric MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock(); 4322*0b57cec5SDimitry Andric MachineFunction::iterator MBBI(MBB); 4323*0b57cec5SDimitry Andric ++MBBI; 4324*0b57cec5SDimitry Andric 4325*0b57cec5SDimitry Andric MF.insert(MBBI, LoopBB); 4326*0b57cec5SDimitry Andric MF.insert(MBBI, RemainderBB); 4327*0b57cec5SDimitry Andric 4328*0b57cec5SDimitry Andric LoopBB->addSuccessor(LoopBB); 4329*0b57cec5SDimitry Andric LoopBB->addSuccessor(RemainderBB); 4330*0b57cec5SDimitry Andric 4331*0b57cec5SDimitry Andric // Move MI to the LoopBB, and the remainder of the block to RemainderBB. 4332*0b57cec5SDimitry Andric MachineBasicBlock::iterator J = I++; 4333*0b57cec5SDimitry Andric RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB); 4334*0b57cec5SDimitry Andric RemainderBB->splice(RemainderBB->begin(), &MBB, I, MBB.end()); 4335*0b57cec5SDimitry Andric LoopBB->splice(LoopBB->begin(), &MBB, J); 4336*0b57cec5SDimitry Andric 4337*0b57cec5SDimitry Andric MBB.addSuccessor(LoopBB); 4338*0b57cec5SDimitry Andric 4339*0b57cec5SDimitry Andric // Update dominators. We know that MBB immediately dominates LoopBB, that 4340*0b57cec5SDimitry Andric // LoopBB immediately dominates RemainderBB, and that RemainderBB immediately 4341*0b57cec5SDimitry Andric // dominates all of the successors transferred to it from MBB that MBB used 4342*0b57cec5SDimitry Andric // to dominate. 4343*0b57cec5SDimitry Andric if (MDT) { 4344*0b57cec5SDimitry Andric MDT->addNewBlock(LoopBB, &MBB); 4345*0b57cec5SDimitry Andric MDT->addNewBlock(RemainderBB, LoopBB); 4346*0b57cec5SDimitry Andric for (auto &Succ : RemainderBB->successors()) { 4347*0b57cec5SDimitry Andric if (MDT->dominates(&MBB, Succ)) { 4348*0b57cec5SDimitry Andric MDT->changeImmediateDominator(Succ, RemainderBB); 4349*0b57cec5SDimitry Andric } 4350*0b57cec5SDimitry Andric } 4351*0b57cec5SDimitry Andric } 4352*0b57cec5SDimitry Andric 4353*0b57cec5SDimitry Andric emitLoadSRsrcFromVGPRLoop(TII, MRI, MBB, *LoopBB, DL, Rsrc); 4354*0b57cec5SDimitry Andric 4355*0b57cec5SDimitry Andric // Restore the EXEC mask 4356*0b57cec5SDimitry Andric MachineBasicBlock::iterator First = RemainderBB->begin(); 4357*0b57cec5SDimitry Andric BuildMI(*RemainderBB, First, DL, TII.get(MovExecOpc), Exec).addReg(SaveExec); 4358*0b57cec5SDimitry Andric } 4359*0b57cec5SDimitry Andric 4360*0b57cec5SDimitry Andric // Extract pointer from Rsrc and return a zero-value Rsrc replacement. 4361*0b57cec5SDimitry Andric static std::tuple<unsigned, unsigned> 4362*0b57cec5SDimitry Andric extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc) { 4363*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 4364*0b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 4365*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 4366*0b57cec5SDimitry Andric 4367*0b57cec5SDimitry Andric // Extract the ptr from the resource descriptor. 4368*0b57cec5SDimitry Andric unsigned RsrcPtr = 4369*0b57cec5SDimitry Andric TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass, 4370*0b57cec5SDimitry Andric AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass); 4371*0b57cec5SDimitry Andric 4372*0b57cec5SDimitry Andric // Create an empty resource descriptor 4373*0b57cec5SDimitry Andric unsigned Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass); 4374*0b57cec5SDimitry Andric unsigned SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4375*0b57cec5SDimitry Andric unsigned SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); 4376*0b57cec5SDimitry Andric unsigned NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SReg_128RegClass); 4377*0b57cec5SDimitry Andric uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat(); 4378*0b57cec5SDimitry Andric 4379*0b57cec5SDimitry Andric // Zero64 = 0 4380*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64) 4381*0b57cec5SDimitry Andric .addImm(0); 4382*0b57cec5SDimitry Andric 4383*0b57cec5SDimitry Andric // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0} 4384*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo) 4385*0b57cec5SDimitry Andric .addImm(RsrcDataFormat & 0xFFFFFFFF); 4386*0b57cec5SDimitry Andric 4387*0b57cec5SDimitry Andric // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32} 4388*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi) 4389*0b57cec5SDimitry Andric .addImm(RsrcDataFormat >> 32); 4390*0b57cec5SDimitry Andric 4391*0b57cec5SDimitry Andric // NewSRsrc = {Zero64, SRsrcFormat} 4392*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc) 4393*0b57cec5SDimitry Andric .addReg(Zero64) 4394*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0_sub1) 4395*0b57cec5SDimitry Andric .addReg(SRsrcFormatLo) 4396*0b57cec5SDimitry Andric .addImm(AMDGPU::sub2) 4397*0b57cec5SDimitry Andric .addReg(SRsrcFormatHi) 4398*0b57cec5SDimitry Andric .addImm(AMDGPU::sub3); 4399*0b57cec5SDimitry Andric 4400*0b57cec5SDimitry Andric return std::make_tuple(RsrcPtr, NewSRsrc); 4401*0b57cec5SDimitry Andric } 4402*0b57cec5SDimitry Andric 4403*0b57cec5SDimitry Andric void SIInstrInfo::legalizeOperands(MachineInstr &MI, 4404*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 4405*0b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 4406*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF.getRegInfo(); 4407*0b57cec5SDimitry Andric 4408*0b57cec5SDimitry Andric // Legalize VOP2 4409*0b57cec5SDimitry Andric if (isVOP2(MI) || isVOPC(MI)) { 4410*0b57cec5SDimitry Andric legalizeOperandsVOP2(MRI, MI); 4411*0b57cec5SDimitry Andric return; 4412*0b57cec5SDimitry Andric } 4413*0b57cec5SDimitry Andric 4414*0b57cec5SDimitry Andric // Legalize VOP3 4415*0b57cec5SDimitry Andric if (isVOP3(MI)) { 4416*0b57cec5SDimitry Andric legalizeOperandsVOP3(MRI, MI); 4417*0b57cec5SDimitry Andric return; 4418*0b57cec5SDimitry Andric } 4419*0b57cec5SDimitry Andric 4420*0b57cec5SDimitry Andric // Legalize SMRD 4421*0b57cec5SDimitry Andric if (isSMRD(MI)) { 4422*0b57cec5SDimitry Andric legalizeOperandsSMRD(MRI, MI); 4423*0b57cec5SDimitry Andric return; 4424*0b57cec5SDimitry Andric } 4425*0b57cec5SDimitry Andric 4426*0b57cec5SDimitry Andric // Legalize REG_SEQUENCE and PHI 4427*0b57cec5SDimitry Andric // The register class of the operands much be the same type as the register 4428*0b57cec5SDimitry Andric // class of the output. 4429*0b57cec5SDimitry Andric if (MI.getOpcode() == AMDGPU::PHI) { 4430*0b57cec5SDimitry Andric const TargetRegisterClass *RC = nullptr, *SRC = nullptr, *VRC = nullptr; 4431*0b57cec5SDimitry Andric for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) { 4432*0b57cec5SDimitry Andric if (!MI.getOperand(i).isReg() || 4433*0b57cec5SDimitry Andric !TargetRegisterInfo::isVirtualRegister(MI.getOperand(i).getReg())) 4434*0b57cec5SDimitry Andric continue; 4435*0b57cec5SDimitry Andric const TargetRegisterClass *OpRC = 4436*0b57cec5SDimitry Andric MRI.getRegClass(MI.getOperand(i).getReg()); 4437*0b57cec5SDimitry Andric if (RI.hasVectorRegisters(OpRC)) { 4438*0b57cec5SDimitry Andric VRC = OpRC; 4439*0b57cec5SDimitry Andric } else { 4440*0b57cec5SDimitry Andric SRC = OpRC; 4441*0b57cec5SDimitry Andric } 4442*0b57cec5SDimitry Andric } 4443*0b57cec5SDimitry Andric 4444*0b57cec5SDimitry Andric // If any of the operands are VGPR registers, then they all most be 4445*0b57cec5SDimitry Andric // otherwise we will create illegal VGPR->SGPR copies when legalizing 4446*0b57cec5SDimitry Andric // them. 4447*0b57cec5SDimitry Andric if (VRC || !RI.isSGPRClass(getOpRegClass(MI, 0))) { 4448*0b57cec5SDimitry Andric if (!VRC) { 4449*0b57cec5SDimitry Andric assert(SRC); 4450*0b57cec5SDimitry Andric VRC = RI.hasAGPRs(getOpRegClass(MI, 0)) ? RI.getEquivalentAGPRClass(SRC) 4451*0b57cec5SDimitry Andric : RI.getEquivalentVGPRClass(SRC); 4452*0b57cec5SDimitry Andric } 4453*0b57cec5SDimitry Andric RC = VRC; 4454*0b57cec5SDimitry Andric } else { 4455*0b57cec5SDimitry Andric RC = SRC; 4456*0b57cec5SDimitry Andric } 4457*0b57cec5SDimitry Andric 4458*0b57cec5SDimitry Andric // Update all the operands so they have the same type. 4459*0b57cec5SDimitry Andric for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) { 4460*0b57cec5SDimitry Andric MachineOperand &Op = MI.getOperand(I); 4461*0b57cec5SDimitry Andric if (!Op.isReg() || !TargetRegisterInfo::isVirtualRegister(Op.getReg())) 4462*0b57cec5SDimitry Andric continue; 4463*0b57cec5SDimitry Andric 4464*0b57cec5SDimitry Andric // MI is a PHI instruction. 4465*0b57cec5SDimitry Andric MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB(); 4466*0b57cec5SDimitry Andric MachineBasicBlock::iterator Insert = InsertBB->getFirstTerminator(); 4467*0b57cec5SDimitry Andric 4468*0b57cec5SDimitry Andric // Avoid creating no-op copies with the same src and dst reg class. These 4469*0b57cec5SDimitry Andric // confuse some of the machine passes. 4470*0b57cec5SDimitry Andric legalizeGenericOperand(*InsertBB, Insert, RC, Op, MRI, MI.getDebugLoc()); 4471*0b57cec5SDimitry Andric } 4472*0b57cec5SDimitry Andric } 4473*0b57cec5SDimitry Andric 4474*0b57cec5SDimitry Andric // REG_SEQUENCE doesn't really require operand legalization, but if one has a 4475*0b57cec5SDimitry Andric // VGPR dest type and SGPR sources, insert copies so all operands are 4476*0b57cec5SDimitry Andric // VGPRs. This seems to help operand folding / the register coalescer. 4477*0b57cec5SDimitry Andric if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) { 4478*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent(); 4479*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC = getOpRegClass(MI, 0); 4480*0b57cec5SDimitry Andric if (RI.hasVGPRs(DstRC)) { 4481*0b57cec5SDimitry Andric // Update all the operands so they are VGPR register classes. These may 4482*0b57cec5SDimitry Andric // not be the same register class because REG_SEQUENCE supports mixing 4483*0b57cec5SDimitry Andric // subregister index types e.g. sub0_sub1 + sub2 + sub3 4484*0b57cec5SDimitry Andric for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) { 4485*0b57cec5SDimitry Andric MachineOperand &Op = MI.getOperand(I); 4486*0b57cec5SDimitry Andric if (!Op.isReg() || !TargetRegisterInfo::isVirtualRegister(Op.getReg())) 4487*0b57cec5SDimitry Andric continue; 4488*0b57cec5SDimitry Andric 4489*0b57cec5SDimitry Andric const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg()); 4490*0b57cec5SDimitry Andric const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC); 4491*0b57cec5SDimitry Andric if (VRC == OpRC) 4492*0b57cec5SDimitry Andric continue; 4493*0b57cec5SDimitry Andric 4494*0b57cec5SDimitry Andric legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc()); 4495*0b57cec5SDimitry Andric Op.setIsKill(); 4496*0b57cec5SDimitry Andric } 4497*0b57cec5SDimitry Andric } 4498*0b57cec5SDimitry Andric 4499*0b57cec5SDimitry Andric return; 4500*0b57cec5SDimitry Andric } 4501*0b57cec5SDimitry Andric 4502*0b57cec5SDimitry Andric // Legalize INSERT_SUBREG 4503*0b57cec5SDimitry Andric // src0 must have the same register class as dst 4504*0b57cec5SDimitry Andric if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) { 4505*0b57cec5SDimitry Andric unsigned Dst = MI.getOperand(0).getReg(); 4506*0b57cec5SDimitry Andric unsigned Src0 = MI.getOperand(1).getReg(); 4507*0b57cec5SDimitry Andric const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); 4508*0b57cec5SDimitry Andric const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0); 4509*0b57cec5SDimitry Andric if (DstRC != Src0RC) { 4510*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent(); 4511*0b57cec5SDimitry Andric MachineOperand &Op = MI.getOperand(1); 4512*0b57cec5SDimitry Andric legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc()); 4513*0b57cec5SDimitry Andric } 4514*0b57cec5SDimitry Andric return; 4515*0b57cec5SDimitry Andric } 4516*0b57cec5SDimitry Andric 4517*0b57cec5SDimitry Andric // Legalize SI_INIT_M0 4518*0b57cec5SDimitry Andric if (MI.getOpcode() == AMDGPU::SI_INIT_M0) { 4519*0b57cec5SDimitry Andric MachineOperand &Src = MI.getOperand(0); 4520*0b57cec5SDimitry Andric if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg()))) 4521*0b57cec5SDimitry Andric Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI)); 4522*0b57cec5SDimitry Andric return; 4523*0b57cec5SDimitry Andric } 4524*0b57cec5SDimitry Andric 4525*0b57cec5SDimitry Andric // Legalize MIMG and MUBUF/MTBUF for shaders. 4526*0b57cec5SDimitry Andric // 4527*0b57cec5SDimitry Andric // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via 4528*0b57cec5SDimitry Andric // scratch memory access. In both cases, the legalization never involves 4529*0b57cec5SDimitry Andric // conversion to the addr64 form. 4530*0b57cec5SDimitry Andric if (isMIMG(MI) || 4531*0b57cec5SDimitry Andric (AMDGPU::isShader(MF.getFunction().getCallingConv()) && 4532*0b57cec5SDimitry Andric (isMUBUF(MI) || isMTBUF(MI)))) { 4533*0b57cec5SDimitry Andric MachineOperand *SRsrc = getNamedOperand(MI, AMDGPU::OpName::srsrc); 4534*0b57cec5SDimitry Andric if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg()))) { 4535*0b57cec5SDimitry Andric unsigned SGPR = readlaneVGPRToSGPR(SRsrc->getReg(), MI, MRI); 4536*0b57cec5SDimitry Andric SRsrc->setReg(SGPR); 4537*0b57cec5SDimitry Andric } 4538*0b57cec5SDimitry Andric 4539*0b57cec5SDimitry Andric MachineOperand *SSamp = getNamedOperand(MI, AMDGPU::OpName::ssamp); 4540*0b57cec5SDimitry Andric if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg()))) { 4541*0b57cec5SDimitry Andric unsigned SGPR = readlaneVGPRToSGPR(SSamp->getReg(), MI, MRI); 4542*0b57cec5SDimitry Andric SSamp->setReg(SGPR); 4543*0b57cec5SDimitry Andric } 4544*0b57cec5SDimitry Andric return; 4545*0b57cec5SDimitry Andric } 4546*0b57cec5SDimitry Andric 4547*0b57cec5SDimitry Andric // Legalize MUBUF* instructions. 4548*0b57cec5SDimitry Andric int RsrcIdx = 4549*0b57cec5SDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc); 4550*0b57cec5SDimitry Andric if (RsrcIdx != -1) { 4551*0b57cec5SDimitry Andric // We have an MUBUF instruction 4552*0b57cec5SDimitry Andric MachineOperand *Rsrc = &MI.getOperand(RsrcIdx); 4553*0b57cec5SDimitry Andric unsigned RsrcRC = get(MI.getOpcode()).OpInfo[RsrcIdx].RegClass; 4554*0b57cec5SDimitry Andric if (RI.getCommonSubClass(MRI.getRegClass(Rsrc->getReg()), 4555*0b57cec5SDimitry Andric RI.getRegClass(RsrcRC))) { 4556*0b57cec5SDimitry Andric // The operands are legal. 4557*0b57cec5SDimitry Andric // FIXME: We may need to legalize operands besided srsrc. 4558*0b57cec5SDimitry Andric return; 4559*0b57cec5SDimitry Andric } 4560*0b57cec5SDimitry Andric 4561*0b57cec5SDimitry Andric // Legalize a VGPR Rsrc. 4562*0b57cec5SDimitry Andric // 4563*0b57cec5SDimitry Andric // If the instruction is _ADDR64, we can avoid a waterfall by extracting 4564*0b57cec5SDimitry Andric // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using 4565*0b57cec5SDimitry Andric // a zero-value SRsrc. 4566*0b57cec5SDimitry Andric // 4567*0b57cec5SDimitry Andric // If the instruction is _OFFSET (both idxen and offen disabled), and we 4568*0b57cec5SDimitry Andric // support ADDR64 instructions, we can convert to ADDR64 and do the same as 4569*0b57cec5SDimitry Andric // above. 4570*0b57cec5SDimitry Andric // 4571*0b57cec5SDimitry Andric // Otherwise we are on non-ADDR64 hardware, and/or we have 4572*0b57cec5SDimitry Andric // idxen/offen/bothen and we fall back to a waterfall loop. 4573*0b57cec5SDimitry Andric 4574*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *MI.getParent(); 4575*0b57cec5SDimitry Andric 4576*0b57cec5SDimitry Andric MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr); 4577*0b57cec5SDimitry Andric if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) { 4578*0b57cec5SDimitry Andric // This is already an ADDR64 instruction so we need to add the pointer 4579*0b57cec5SDimitry Andric // extracted from the resource descriptor to the current value of VAddr. 4580*0b57cec5SDimitry Andric unsigned NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 4581*0b57cec5SDimitry Andric unsigned NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 4582*0b57cec5SDimitry Andric unsigned NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass); 4583*0b57cec5SDimitry Andric 4584*0b57cec5SDimitry Andric const auto *BoolXExecRC = RI.getRegClass(AMDGPU::SReg_1_XEXECRegClassID); 4585*0b57cec5SDimitry Andric unsigned CondReg0 = MRI.createVirtualRegister(BoolXExecRC); 4586*0b57cec5SDimitry Andric unsigned CondReg1 = MRI.createVirtualRegister(BoolXExecRC); 4587*0b57cec5SDimitry Andric 4588*0b57cec5SDimitry Andric unsigned RsrcPtr, NewSRsrc; 4589*0b57cec5SDimitry Andric std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc); 4590*0b57cec5SDimitry Andric 4591*0b57cec5SDimitry Andric // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0 4592*0b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 4593*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_I32_e64), NewVAddrLo) 4594*0b57cec5SDimitry Andric .addDef(CondReg0) 4595*0b57cec5SDimitry Andric .addReg(RsrcPtr, 0, AMDGPU::sub0) 4596*0b57cec5SDimitry Andric .addReg(VAddr->getReg(), 0, AMDGPU::sub0) 4597*0b57cec5SDimitry Andric .addImm(0); 4598*0b57cec5SDimitry Andric 4599*0b57cec5SDimitry Andric // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1 4600*0b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi) 4601*0b57cec5SDimitry Andric .addDef(CondReg1, RegState::Dead) 4602*0b57cec5SDimitry Andric .addReg(RsrcPtr, 0, AMDGPU::sub1) 4603*0b57cec5SDimitry Andric .addReg(VAddr->getReg(), 0, AMDGPU::sub1) 4604*0b57cec5SDimitry Andric .addReg(CondReg0, RegState::Kill) 4605*0b57cec5SDimitry Andric .addImm(0); 4606*0b57cec5SDimitry Andric 4607*0b57cec5SDimitry Andric // NewVaddr = {NewVaddrHi, NewVaddrLo} 4608*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr) 4609*0b57cec5SDimitry Andric .addReg(NewVAddrLo) 4610*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 4611*0b57cec5SDimitry Andric .addReg(NewVAddrHi) 4612*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 4613*0b57cec5SDimitry Andric 4614*0b57cec5SDimitry Andric VAddr->setReg(NewVAddr); 4615*0b57cec5SDimitry Andric Rsrc->setReg(NewSRsrc); 4616*0b57cec5SDimitry Andric } else if (!VAddr && ST.hasAddr64()) { 4617*0b57cec5SDimitry Andric // This instructions is the _OFFSET variant, so we need to convert it to 4618*0b57cec5SDimitry Andric // ADDR64. 4619*0b57cec5SDimitry Andric assert(MBB.getParent()->getSubtarget<GCNSubtarget>().getGeneration() 4620*0b57cec5SDimitry Andric < AMDGPUSubtarget::VOLCANIC_ISLANDS && 4621*0b57cec5SDimitry Andric "FIXME: Need to emit flat atomics here"); 4622*0b57cec5SDimitry Andric 4623*0b57cec5SDimitry Andric unsigned RsrcPtr, NewSRsrc; 4624*0b57cec5SDimitry Andric std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc); 4625*0b57cec5SDimitry Andric 4626*0b57cec5SDimitry Andric unsigned NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass); 4627*0b57cec5SDimitry Andric MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata); 4628*0b57cec5SDimitry Andric MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset); 4629*0b57cec5SDimitry Andric MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset); 4630*0b57cec5SDimitry Andric unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode()); 4631*0b57cec5SDimitry Andric 4632*0b57cec5SDimitry Andric // Atomics rith return have have an additional tied operand and are 4633*0b57cec5SDimitry Andric // missing some of the special bits. 4634*0b57cec5SDimitry Andric MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in); 4635*0b57cec5SDimitry Andric MachineInstr *Addr64; 4636*0b57cec5SDimitry Andric 4637*0b57cec5SDimitry Andric if (!VDataIn) { 4638*0b57cec5SDimitry Andric // Regular buffer load / store. 4639*0b57cec5SDimitry Andric MachineInstrBuilder MIB = 4640*0b57cec5SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode)) 4641*0b57cec5SDimitry Andric .add(*VData) 4642*0b57cec5SDimitry Andric .addReg(NewVAddr) 4643*0b57cec5SDimitry Andric .addReg(NewSRsrc) 4644*0b57cec5SDimitry Andric .add(*SOffset) 4645*0b57cec5SDimitry Andric .add(*Offset); 4646*0b57cec5SDimitry Andric 4647*0b57cec5SDimitry Andric // Atomics do not have this operand. 4648*0b57cec5SDimitry Andric if (const MachineOperand *GLC = 4649*0b57cec5SDimitry Andric getNamedOperand(MI, AMDGPU::OpName::glc)) { 4650*0b57cec5SDimitry Andric MIB.addImm(GLC->getImm()); 4651*0b57cec5SDimitry Andric } 4652*0b57cec5SDimitry Andric if (const MachineOperand *DLC = 4653*0b57cec5SDimitry Andric getNamedOperand(MI, AMDGPU::OpName::dlc)) { 4654*0b57cec5SDimitry Andric MIB.addImm(DLC->getImm()); 4655*0b57cec5SDimitry Andric } 4656*0b57cec5SDimitry Andric 4657*0b57cec5SDimitry Andric MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::slc)); 4658*0b57cec5SDimitry Andric 4659*0b57cec5SDimitry Andric if (const MachineOperand *TFE = 4660*0b57cec5SDimitry Andric getNamedOperand(MI, AMDGPU::OpName::tfe)) { 4661*0b57cec5SDimitry Andric MIB.addImm(TFE->getImm()); 4662*0b57cec5SDimitry Andric } 4663*0b57cec5SDimitry Andric 4664*0b57cec5SDimitry Andric MIB.cloneMemRefs(MI); 4665*0b57cec5SDimitry Andric Addr64 = MIB; 4666*0b57cec5SDimitry Andric } else { 4667*0b57cec5SDimitry Andric // Atomics with return. 4668*0b57cec5SDimitry Andric Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode)) 4669*0b57cec5SDimitry Andric .add(*VData) 4670*0b57cec5SDimitry Andric .add(*VDataIn) 4671*0b57cec5SDimitry Andric .addReg(NewVAddr) 4672*0b57cec5SDimitry Andric .addReg(NewSRsrc) 4673*0b57cec5SDimitry Andric .add(*SOffset) 4674*0b57cec5SDimitry Andric .add(*Offset) 4675*0b57cec5SDimitry Andric .addImm(getNamedImmOperand(MI, AMDGPU::OpName::slc)) 4676*0b57cec5SDimitry Andric .cloneMemRefs(MI); 4677*0b57cec5SDimitry Andric } 4678*0b57cec5SDimitry Andric 4679*0b57cec5SDimitry Andric MI.removeFromParent(); 4680*0b57cec5SDimitry Andric 4681*0b57cec5SDimitry Andric // NewVaddr = {NewVaddrHi, NewVaddrLo} 4682*0b57cec5SDimitry Andric BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE), 4683*0b57cec5SDimitry Andric NewVAddr) 4684*0b57cec5SDimitry Andric .addReg(RsrcPtr, 0, AMDGPU::sub0) 4685*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 4686*0b57cec5SDimitry Andric .addReg(RsrcPtr, 0, AMDGPU::sub1) 4687*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 4688*0b57cec5SDimitry Andric } else { 4689*0b57cec5SDimitry Andric // This is another variant; legalize Rsrc with waterfall loop from VGPRs 4690*0b57cec5SDimitry Andric // to SGPRs. 4691*0b57cec5SDimitry Andric loadSRsrcFromVGPR(*this, MI, *Rsrc, MDT); 4692*0b57cec5SDimitry Andric } 4693*0b57cec5SDimitry Andric } 4694*0b57cec5SDimitry Andric } 4695*0b57cec5SDimitry Andric 4696*0b57cec5SDimitry Andric void SIInstrInfo::moveToVALU(MachineInstr &TopInst, 4697*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 4698*0b57cec5SDimitry Andric SetVectorType Worklist; 4699*0b57cec5SDimitry Andric Worklist.insert(&TopInst); 4700*0b57cec5SDimitry Andric 4701*0b57cec5SDimitry Andric while (!Worklist.empty()) { 4702*0b57cec5SDimitry Andric MachineInstr &Inst = *Worklist.pop_back_val(); 4703*0b57cec5SDimitry Andric MachineBasicBlock *MBB = Inst.getParent(); 4704*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo(); 4705*0b57cec5SDimitry Andric 4706*0b57cec5SDimitry Andric unsigned Opcode = Inst.getOpcode(); 4707*0b57cec5SDimitry Andric unsigned NewOpcode = getVALUOp(Inst); 4708*0b57cec5SDimitry Andric 4709*0b57cec5SDimitry Andric // Handle some special cases 4710*0b57cec5SDimitry Andric switch (Opcode) { 4711*0b57cec5SDimitry Andric default: 4712*0b57cec5SDimitry Andric break; 4713*0b57cec5SDimitry Andric case AMDGPU::S_ADD_U64_PSEUDO: 4714*0b57cec5SDimitry Andric case AMDGPU::S_SUB_U64_PSEUDO: 4715*0b57cec5SDimitry Andric splitScalar64BitAddSub(Worklist, Inst, MDT); 4716*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4717*0b57cec5SDimitry Andric continue; 4718*0b57cec5SDimitry Andric case AMDGPU::S_ADD_I32: 4719*0b57cec5SDimitry Andric case AMDGPU::S_SUB_I32: 4720*0b57cec5SDimitry Andric // FIXME: The u32 versions currently selected use the carry. 4721*0b57cec5SDimitry Andric if (moveScalarAddSub(Worklist, Inst, MDT)) 4722*0b57cec5SDimitry Andric continue; 4723*0b57cec5SDimitry Andric 4724*0b57cec5SDimitry Andric // Default handling 4725*0b57cec5SDimitry Andric break; 4726*0b57cec5SDimitry Andric case AMDGPU::S_AND_B64: 4727*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT); 4728*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4729*0b57cec5SDimitry Andric continue; 4730*0b57cec5SDimitry Andric 4731*0b57cec5SDimitry Andric case AMDGPU::S_OR_B64: 4732*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT); 4733*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4734*0b57cec5SDimitry Andric continue; 4735*0b57cec5SDimitry Andric 4736*0b57cec5SDimitry Andric case AMDGPU::S_XOR_B64: 4737*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT); 4738*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4739*0b57cec5SDimitry Andric continue; 4740*0b57cec5SDimitry Andric 4741*0b57cec5SDimitry Andric case AMDGPU::S_NAND_B64: 4742*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT); 4743*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4744*0b57cec5SDimitry Andric continue; 4745*0b57cec5SDimitry Andric 4746*0b57cec5SDimitry Andric case AMDGPU::S_NOR_B64: 4747*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT); 4748*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4749*0b57cec5SDimitry Andric continue; 4750*0b57cec5SDimitry Andric 4751*0b57cec5SDimitry Andric case AMDGPU::S_XNOR_B64: 4752*0b57cec5SDimitry Andric if (ST.hasDLInsts()) 4753*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT); 4754*0b57cec5SDimitry Andric else 4755*0b57cec5SDimitry Andric splitScalar64BitXnor(Worklist, Inst, MDT); 4756*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4757*0b57cec5SDimitry Andric continue; 4758*0b57cec5SDimitry Andric 4759*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B64: 4760*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT); 4761*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4762*0b57cec5SDimitry Andric continue; 4763*0b57cec5SDimitry Andric 4764*0b57cec5SDimitry Andric case AMDGPU::S_ORN2_B64: 4765*0b57cec5SDimitry Andric splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT); 4766*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4767*0b57cec5SDimitry Andric continue; 4768*0b57cec5SDimitry Andric 4769*0b57cec5SDimitry Andric case AMDGPU::S_NOT_B64: 4770*0b57cec5SDimitry Andric splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32); 4771*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4772*0b57cec5SDimitry Andric continue; 4773*0b57cec5SDimitry Andric 4774*0b57cec5SDimitry Andric case AMDGPU::S_BCNT1_I32_B64: 4775*0b57cec5SDimitry Andric splitScalar64BitBCNT(Worklist, Inst); 4776*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4777*0b57cec5SDimitry Andric continue; 4778*0b57cec5SDimitry Andric 4779*0b57cec5SDimitry Andric case AMDGPU::S_BFE_I64: 4780*0b57cec5SDimitry Andric splitScalar64BitBFE(Worklist, Inst); 4781*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4782*0b57cec5SDimitry Andric continue; 4783*0b57cec5SDimitry Andric 4784*0b57cec5SDimitry Andric case AMDGPU::S_LSHL_B32: 4785*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4786*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_LSHLREV_B32_e64; 4787*0b57cec5SDimitry Andric swapOperands(Inst); 4788*0b57cec5SDimitry Andric } 4789*0b57cec5SDimitry Andric break; 4790*0b57cec5SDimitry Andric case AMDGPU::S_ASHR_I32: 4791*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4792*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_ASHRREV_I32_e64; 4793*0b57cec5SDimitry Andric swapOperands(Inst); 4794*0b57cec5SDimitry Andric } 4795*0b57cec5SDimitry Andric break; 4796*0b57cec5SDimitry Andric case AMDGPU::S_LSHR_B32: 4797*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4798*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_LSHRREV_B32_e64; 4799*0b57cec5SDimitry Andric swapOperands(Inst); 4800*0b57cec5SDimitry Andric } 4801*0b57cec5SDimitry Andric break; 4802*0b57cec5SDimitry Andric case AMDGPU::S_LSHL_B64: 4803*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4804*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_LSHLREV_B64; 4805*0b57cec5SDimitry Andric swapOperands(Inst); 4806*0b57cec5SDimitry Andric } 4807*0b57cec5SDimitry Andric break; 4808*0b57cec5SDimitry Andric case AMDGPU::S_ASHR_I64: 4809*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4810*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_ASHRREV_I64; 4811*0b57cec5SDimitry Andric swapOperands(Inst); 4812*0b57cec5SDimitry Andric } 4813*0b57cec5SDimitry Andric break; 4814*0b57cec5SDimitry Andric case AMDGPU::S_LSHR_B64: 4815*0b57cec5SDimitry Andric if (ST.hasOnlyRevVALUShifts()) { 4816*0b57cec5SDimitry Andric NewOpcode = AMDGPU::V_LSHRREV_B64; 4817*0b57cec5SDimitry Andric swapOperands(Inst); 4818*0b57cec5SDimitry Andric } 4819*0b57cec5SDimitry Andric break; 4820*0b57cec5SDimitry Andric 4821*0b57cec5SDimitry Andric case AMDGPU::S_ABS_I32: 4822*0b57cec5SDimitry Andric lowerScalarAbs(Worklist, Inst); 4823*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4824*0b57cec5SDimitry Andric continue; 4825*0b57cec5SDimitry Andric 4826*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC0: 4827*0b57cec5SDimitry Andric case AMDGPU::S_CBRANCH_SCC1: 4828*0b57cec5SDimitry Andric // Clear unused bits of vcc 4829*0b57cec5SDimitry Andric if (ST.isWave32()) 4830*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::S_AND_B32), 4831*0b57cec5SDimitry Andric AMDGPU::VCC_LO) 4832*0b57cec5SDimitry Andric .addReg(AMDGPU::EXEC_LO) 4833*0b57cec5SDimitry Andric .addReg(AMDGPU::VCC_LO); 4834*0b57cec5SDimitry Andric else 4835*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::S_AND_B64), 4836*0b57cec5SDimitry Andric AMDGPU::VCC) 4837*0b57cec5SDimitry Andric .addReg(AMDGPU::EXEC) 4838*0b57cec5SDimitry Andric .addReg(AMDGPU::VCC); 4839*0b57cec5SDimitry Andric break; 4840*0b57cec5SDimitry Andric 4841*0b57cec5SDimitry Andric case AMDGPU::S_BFE_U64: 4842*0b57cec5SDimitry Andric case AMDGPU::S_BFM_B64: 4843*0b57cec5SDimitry Andric llvm_unreachable("Moving this op to VALU not implemented"); 4844*0b57cec5SDimitry Andric 4845*0b57cec5SDimitry Andric case AMDGPU::S_PACK_LL_B32_B16: 4846*0b57cec5SDimitry Andric case AMDGPU::S_PACK_LH_B32_B16: 4847*0b57cec5SDimitry Andric case AMDGPU::S_PACK_HH_B32_B16: 4848*0b57cec5SDimitry Andric movePackToVALU(Worklist, MRI, Inst); 4849*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4850*0b57cec5SDimitry Andric continue; 4851*0b57cec5SDimitry Andric 4852*0b57cec5SDimitry Andric case AMDGPU::S_XNOR_B32: 4853*0b57cec5SDimitry Andric lowerScalarXnor(Worklist, Inst); 4854*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4855*0b57cec5SDimitry Andric continue; 4856*0b57cec5SDimitry Andric 4857*0b57cec5SDimitry Andric case AMDGPU::S_NAND_B32: 4858*0b57cec5SDimitry Andric splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32); 4859*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4860*0b57cec5SDimitry Andric continue; 4861*0b57cec5SDimitry Andric 4862*0b57cec5SDimitry Andric case AMDGPU::S_NOR_B32: 4863*0b57cec5SDimitry Andric splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32); 4864*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4865*0b57cec5SDimitry Andric continue; 4866*0b57cec5SDimitry Andric 4867*0b57cec5SDimitry Andric case AMDGPU::S_ANDN2_B32: 4868*0b57cec5SDimitry Andric splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32); 4869*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4870*0b57cec5SDimitry Andric continue; 4871*0b57cec5SDimitry Andric 4872*0b57cec5SDimitry Andric case AMDGPU::S_ORN2_B32: 4873*0b57cec5SDimitry Andric splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32); 4874*0b57cec5SDimitry Andric Inst.eraseFromParent(); 4875*0b57cec5SDimitry Andric continue; 4876*0b57cec5SDimitry Andric } 4877*0b57cec5SDimitry Andric 4878*0b57cec5SDimitry Andric if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) { 4879*0b57cec5SDimitry Andric // We cannot move this instruction to the VALU, so we should try to 4880*0b57cec5SDimitry Andric // legalize its operands instead. 4881*0b57cec5SDimitry Andric legalizeOperands(Inst, MDT); 4882*0b57cec5SDimitry Andric continue; 4883*0b57cec5SDimitry Andric } 4884*0b57cec5SDimitry Andric 4885*0b57cec5SDimitry Andric // Use the new VALU Opcode. 4886*0b57cec5SDimitry Andric const MCInstrDesc &NewDesc = get(NewOpcode); 4887*0b57cec5SDimitry Andric Inst.setDesc(NewDesc); 4888*0b57cec5SDimitry Andric 4889*0b57cec5SDimitry Andric // Remove any references to SCC. Vector instructions can't read from it, and 4890*0b57cec5SDimitry Andric // We're just about to add the implicit use / defs of VCC, and we don't want 4891*0b57cec5SDimitry Andric // both. 4892*0b57cec5SDimitry Andric for (unsigned i = Inst.getNumOperands() - 1; i > 0; --i) { 4893*0b57cec5SDimitry Andric MachineOperand &Op = Inst.getOperand(i); 4894*0b57cec5SDimitry Andric if (Op.isReg() && Op.getReg() == AMDGPU::SCC) { 4895*0b57cec5SDimitry Andric // Only propagate through live-def of SCC. 4896*0b57cec5SDimitry Andric if (Op.isDef() && !Op.isDead()) 4897*0b57cec5SDimitry Andric addSCCDefUsersToVALUWorklist(Op, Inst, Worklist); 4898*0b57cec5SDimitry Andric Inst.RemoveOperand(i); 4899*0b57cec5SDimitry Andric } 4900*0b57cec5SDimitry Andric } 4901*0b57cec5SDimitry Andric 4902*0b57cec5SDimitry Andric if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) { 4903*0b57cec5SDimitry Andric // We are converting these to a BFE, so we need to add the missing 4904*0b57cec5SDimitry Andric // operands for the size and offset. 4905*0b57cec5SDimitry Andric unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16; 4906*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(0)); 4907*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(Size)); 4908*0b57cec5SDimitry Andric 4909*0b57cec5SDimitry Andric } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) { 4910*0b57cec5SDimitry Andric // The VALU version adds the second operand to the result, so insert an 4911*0b57cec5SDimitry Andric // extra 0 operand. 4912*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(0)); 4913*0b57cec5SDimitry Andric } 4914*0b57cec5SDimitry Andric 4915*0b57cec5SDimitry Andric Inst.addImplicitDefUseOperands(*Inst.getParent()->getParent()); 4916*0b57cec5SDimitry Andric fixImplicitOperands(Inst); 4917*0b57cec5SDimitry Andric 4918*0b57cec5SDimitry Andric if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) { 4919*0b57cec5SDimitry Andric const MachineOperand &OffsetWidthOp = Inst.getOperand(2); 4920*0b57cec5SDimitry Andric // If we need to move this to VGPRs, we need to unpack the second operand 4921*0b57cec5SDimitry Andric // back into the 2 separate ones for bit offset and width. 4922*0b57cec5SDimitry Andric assert(OffsetWidthOp.isImm() && 4923*0b57cec5SDimitry Andric "Scalar BFE is only implemented for constant width and offset"); 4924*0b57cec5SDimitry Andric uint32_t Imm = OffsetWidthOp.getImm(); 4925*0b57cec5SDimitry Andric 4926*0b57cec5SDimitry Andric uint32_t Offset = Imm & 0x3f; // Extract bits [5:0]. 4927*0b57cec5SDimitry Andric uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16]. 4928*0b57cec5SDimitry Andric Inst.RemoveOperand(2); // Remove old immediate. 4929*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(Offset)); 4930*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(BitWidth)); 4931*0b57cec5SDimitry Andric } 4932*0b57cec5SDimitry Andric 4933*0b57cec5SDimitry Andric bool HasDst = Inst.getOperand(0).isReg() && Inst.getOperand(0).isDef(); 4934*0b57cec5SDimitry Andric unsigned NewDstReg = AMDGPU::NoRegister; 4935*0b57cec5SDimitry Andric if (HasDst) { 4936*0b57cec5SDimitry Andric unsigned DstReg = Inst.getOperand(0).getReg(); 4937*0b57cec5SDimitry Andric if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 4938*0b57cec5SDimitry Andric continue; 4939*0b57cec5SDimitry Andric 4940*0b57cec5SDimitry Andric // Update the destination register class. 4941*0b57cec5SDimitry Andric const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst); 4942*0b57cec5SDimitry Andric if (!NewDstRC) 4943*0b57cec5SDimitry Andric continue; 4944*0b57cec5SDimitry Andric 4945*0b57cec5SDimitry Andric if (Inst.isCopy() && 4946*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(Inst.getOperand(1).getReg()) && 4947*0b57cec5SDimitry Andric NewDstRC == RI.getRegClassForReg(MRI, Inst.getOperand(1).getReg())) { 4948*0b57cec5SDimitry Andric // Instead of creating a copy where src and dst are the same register 4949*0b57cec5SDimitry Andric // class, we just replace all uses of dst with src. These kinds of 4950*0b57cec5SDimitry Andric // copies interfere with the heuristics MachineSink uses to decide 4951*0b57cec5SDimitry Andric // whether or not to split a critical edge. Since the pass assumes 4952*0b57cec5SDimitry Andric // that copies will end up as machine instructions and not be 4953*0b57cec5SDimitry Andric // eliminated. 4954*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist); 4955*0b57cec5SDimitry Andric MRI.replaceRegWith(DstReg, Inst.getOperand(1).getReg()); 4956*0b57cec5SDimitry Andric MRI.clearKillFlags(Inst.getOperand(1).getReg()); 4957*0b57cec5SDimitry Andric Inst.getOperand(0).setReg(DstReg); 4958*0b57cec5SDimitry Andric 4959*0b57cec5SDimitry Andric // Make sure we don't leave around a dead VGPR->SGPR copy. Normally 4960*0b57cec5SDimitry Andric // these are deleted later, but at -O0 it would leave a suspicious 4961*0b57cec5SDimitry Andric // looking illegal copy of an undef register. 4962*0b57cec5SDimitry Andric for (unsigned I = Inst.getNumOperands() - 1; I != 0; --I) 4963*0b57cec5SDimitry Andric Inst.RemoveOperand(I); 4964*0b57cec5SDimitry Andric Inst.setDesc(get(AMDGPU::IMPLICIT_DEF)); 4965*0b57cec5SDimitry Andric continue; 4966*0b57cec5SDimitry Andric } 4967*0b57cec5SDimitry Andric 4968*0b57cec5SDimitry Andric NewDstReg = MRI.createVirtualRegister(NewDstRC); 4969*0b57cec5SDimitry Andric MRI.replaceRegWith(DstReg, NewDstReg); 4970*0b57cec5SDimitry Andric } 4971*0b57cec5SDimitry Andric 4972*0b57cec5SDimitry Andric // Legalize the operands 4973*0b57cec5SDimitry Andric legalizeOperands(Inst, MDT); 4974*0b57cec5SDimitry Andric 4975*0b57cec5SDimitry Andric if (HasDst) 4976*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist); 4977*0b57cec5SDimitry Andric } 4978*0b57cec5SDimitry Andric } 4979*0b57cec5SDimitry Andric 4980*0b57cec5SDimitry Andric // Add/sub require special handling to deal with carry outs. 4981*0b57cec5SDimitry Andric bool SIInstrInfo::moveScalarAddSub(SetVectorType &Worklist, MachineInstr &Inst, 4982*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 4983*0b57cec5SDimitry Andric if (ST.hasAddNoCarry()) { 4984*0b57cec5SDimitry Andric // Assume there is no user of scc since we don't select this in that case. 4985*0b57cec5SDimitry Andric // Since scc isn't used, it doesn't really matter if the i32 or u32 variant 4986*0b57cec5SDimitry Andric // is used. 4987*0b57cec5SDimitry Andric 4988*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 4989*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 4990*0b57cec5SDimitry Andric 4991*0b57cec5SDimitry Andric unsigned OldDstReg = Inst.getOperand(0).getReg(); 4992*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 4993*0b57cec5SDimitry Andric 4994*0b57cec5SDimitry Andric unsigned Opc = Inst.getOpcode(); 4995*0b57cec5SDimitry Andric assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32); 4996*0b57cec5SDimitry Andric 4997*0b57cec5SDimitry Andric unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ? 4998*0b57cec5SDimitry Andric AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64; 4999*0b57cec5SDimitry Andric 5000*0b57cec5SDimitry Andric assert(Inst.getOperand(3).getReg() == AMDGPU::SCC); 5001*0b57cec5SDimitry Andric Inst.RemoveOperand(3); 5002*0b57cec5SDimitry Andric 5003*0b57cec5SDimitry Andric Inst.setDesc(get(NewOpc)); 5004*0b57cec5SDimitry Andric Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit 5005*0b57cec5SDimitry Andric Inst.addImplicitDefUseOperands(*MBB.getParent()); 5006*0b57cec5SDimitry Andric MRI.replaceRegWith(OldDstReg, ResultReg); 5007*0b57cec5SDimitry Andric legalizeOperands(Inst, MDT); 5008*0b57cec5SDimitry Andric 5009*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5010*0b57cec5SDimitry Andric return true; 5011*0b57cec5SDimitry Andric } 5012*0b57cec5SDimitry Andric 5013*0b57cec5SDimitry Andric return false; 5014*0b57cec5SDimitry Andric } 5015*0b57cec5SDimitry Andric 5016*0b57cec5SDimitry Andric void SIInstrInfo::lowerScalarAbs(SetVectorType &Worklist, 5017*0b57cec5SDimitry Andric MachineInstr &Inst) const { 5018*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5019*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5020*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5021*0b57cec5SDimitry Andric DebugLoc DL = Inst.getDebugLoc(); 5022*0b57cec5SDimitry Andric 5023*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5024*0b57cec5SDimitry Andric MachineOperand &Src = Inst.getOperand(1); 5025*0b57cec5SDimitry Andric unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5026*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5027*0b57cec5SDimitry Andric 5028*0b57cec5SDimitry Andric unsigned SubOp = ST.hasAddNoCarry() ? 5029*0b57cec5SDimitry Andric AMDGPU::V_SUB_U32_e32 : AMDGPU::V_SUB_I32_e32; 5030*0b57cec5SDimitry Andric 5031*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(SubOp), TmpReg) 5032*0b57cec5SDimitry Andric .addImm(0) 5033*0b57cec5SDimitry Andric .addReg(Src.getReg()); 5034*0b57cec5SDimitry Andric 5035*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg) 5036*0b57cec5SDimitry Andric .addReg(Src.getReg()) 5037*0b57cec5SDimitry Andric .addReg(TmpReg); 5038*0b57cec5SDimitry Andric 5039*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), ResultReg); 5040*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5041*0b57cec5SDimitry Andric } 5042*0b57cec5SDimitry Andric 5043*0b57cec5SDimitry Andric void SIInstrInfo::lowerScalarXnor(SetVectorType &Worklist, 5044*0b57cec5SDimitry Andric MachineInstr &Inst) const { 5045*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5046*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5047*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5048*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5049*0b57cec5SDimitry Andric 5050*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5051*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5052*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5053*0b57cec5SDimitry Andric 5054*0b57cec5SDimitry Andric if (ST.hasDLInsts()) { 5055*0b57cec5SDimitry Andric unsigned NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5056*0b57cec5SDimitry Andric legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL); 5057*0b57cec5SDimitry Andric legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL); 5058*0b57cec5SDimitry Andric 5059*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest) 5060*0b57cec5SDimitry Andric .add(Src0) 5061*0b57cec5SDimitry Andric .add(Src1); 5062*0b57cec5SDimitry Andric 5063*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), NewDest); 5064*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist); 5065*0b57cec5SDimitry Andric } else { 5066*0b57cec5SDimitry Andric // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can 5067*0b57cec5SDimitry Andric // invert either source and then perform the XOR. If either source is a 5068*0b57cec5SDimitry Andric // scalar register, then we can leave the inversion on the scalar unit to 5069*0b57cec5SDimitry Andric // acheive a better distrubution of scalar and vector instructions. 5070*0b57cec5SDimitry Andric bool Src0IsSGPR = Src0.isReg() && 5071*0b57cec5SDimitry Andric RI.isSGPRClass(MRI.getRegClass(Src0.getReg())); 5072*0b57cec5SDimitry Andric bool Src1IsSGPR = Src1.isReg() && 5073*0b57cec5SDimitry Andric RI.isSGPRClass(MRI.getRegClass(Src1.getReg())); 5074*0b57cec5SDimitry Andric MachineInstr *Xor; 5075*0b57cec5SDimitry Andric unsigned Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5076*0b57cec5SDimitry Andric unsigned NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5077*0b57cec5SDimitry Andric 5078*0b57cec5SDimitry Andric // Build a pair of scalar instructions and add them to the work list. 5079*0b57cec5SDimitry Andric // The next iteration over the work list will lower these to the vector 5080*0b57cec5SDimitry Andric // unit as necessary. 5081*0b57cec5SDimitry Andric if (Src0IsSGPR) { 5082*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0); 5083*0b57cec5SDimitry Andric Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest) 5084*0b57cec5SDimitry Andric .addReg(Temp) 5085*0b57cec5SDimitry Andric .add(Src1); 5086*0b57cec5SDimitry Andric } else if (Src1IsSGPR) { 5087*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1); 5088*0b57cec5SDimitry Andric Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest) 5089*0b57cec5SDimitry Andric .add(Src0) 5090*0b57cec5SDimitry Andric .addReg(Temp); 5091*0b57cec5SDimitry Andric } else { 5092*0b57cec5SDimitry Andric Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp) 5093*0b57cec5SDimitry Andric .add(Src0) 5094*0b57cec5SDimitry Andric .add(Src1); 5095*0b57cec5SDimitry Andric MachineInstr *Not = 5096*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp); 5097*0b57cec5SDimitry Andric Worklist.insert(Not); 5098*0b57cec5SDimitry Andric } 5099*0b57cec5SDimitry Andric 5100*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), NewDest); 5101*0b57cec5SDimitry Andric 5102*0b57cec5SDimitry Andric Worklist.insert(Xor); 5103*0b57cec5SDimitry Andric 5104*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist); 5105*0b57cec5SDimitry Andric } 5106*0b57cec5SDimitry Andric } 5107*0b57cec5SDimitry Andric 5108*0b57cec5SDimitry Andric void SIInstrInfo::splitScalarNotBinop(SetVectorType &Worklist, 5109*0b57cec5SDimitry Andric MachineInstr &Inst, 5110*0b57cec5SDimitry Andric unsigned Opcode) const { 5111*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5112*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5113*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5114*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5115*0b57cec5SDimitry Andric 5116*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5117*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5118*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5119*0b57cec5SDimitry Andric 5120*0b57cec5SDimitry Andric unsigned NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5121*0b57cec5SDimitry Andric unsigned Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5122*0b57cec5SDimitry Andric 5123*0b57cec5SDimitry Andric MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm) 5124*0b57cec5SDimitry Andric .add(Src0) 5125*0b57cec5SDimitry Andric .add(Src1); 5126*0b57cec5SDimitry Andric 5127*0b57cec5SDimitry Andric MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest) 5128*0b57cec5SDimitry Andric .addReg(Interm); 5129*0b57cec5SDimitry Andric 5130*0b57cec5SDimitry Andric Worklist.insert(&Op); 5131*0b57cec5SDimitry Andric Worklist.insert(&Not); 5132*0b57cec5SDimitry Andric 5133*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), NewDest); 5134*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist); 5135*0b57cec5SDimitry Andric } 5136*0b57cec5SDimitry Andric 5137*0b57cec5SDimitry Andric void SIInstrInfo::splitScalarBinOpN2(SetVectorType& Worklist, 5138*0b57cec5SDimitry Andric MachineInstr &Inst, 5139*0b57cec5SDimitry Andric unsigned Opcode) const { 5140*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5141*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5142*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5143*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5144*0b57cec5SDimitry Andric 5145*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5146*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5147*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5148*0b57cec5SDimitry Andric 5149*0b57cec5SDimitry Andric unsigned NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5150*0b57cec5SDimitry Andric unsigned Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); 5151*0b57cec5SDimitry Andric 5152*0b57cec5SDimitry Andric MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm) 5153*0b57cec5SDimitry Andric .add(Src1); 5154*0b57cec5SDimitry Andric 5155*0b57cec5SDimitry Andric MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest) 5156*0b57cec5SDimitry Andric .add(Src0) 5157*0b57cec5SDimitry Andric .addReg(Interm); 5158*0b57cec5SDimitry Andric 5159*0b57cec5SDimitry Andric Worklist.insert(&Not); 5160*0b57cec5SDimitry Andric Worklist.insert(&Op); 5161*0b57cec5SDimitry Andric 5162*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), NewDest); 5163*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist); 5164*0b57cec5SDimitry Andric } 5165*0b57cec5SDimitry Andric 5166*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitUnaryOp( 5167*0b57cec5SDimitry Andric SetVectorType &Worklist, MachineInstr &Inst, 5168*0b57cec5SDimitry Andric unsigned Opcode) const { 5169*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5170*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5171*0b57cec5SDimitry Andric 5172*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5173*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5174*0b57cec5SDimitry Andric DebugLoc DL = Inst.getDebugLoc(); 5175*0b57cec5SDimitry Andric 5176*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5177*0b57cec5SDimitry Andric 5178*0b57cec5SDimitry Andric const MCInstrDesc &InstDesc = get(Opcode); 5179*0b57cec5SDimitry Andric const TargetRegisterClass *Src0RC = Src0.isReg() ? 5180*0b57cec5SDimitry Andric MRI.getRegClass(Src0.getReg()) : 5181*0b57cec5SDimitry Andric &AMDGPU::SGPR_32RegClass; 5182*0b57cec5SDimitry Andric 5183*0b57cec5SDimitry Andric const TargetRegisterClass *Src0SubRC = RI.getSubRegClass(Src0RC, AMDGPU::sub0); 5184*0b57cec5SDimitry Andric 5185*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5186*0b57cec5SDimitry Andric AMDGPU::sub0, Src0SubRC); 5187*0b57cec5SDimitry Andric 5188*0b57cec5SDimitry Andric const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg()); 5189*0b57cec5SDimitry Andric const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC); 5190*0b57cec5SDimitry Andric const TargetRegisterClass *NewDestSubRC = RI.getSubRegClass(NewDestRC, AMDGPU::sub0); 5191*0b57cec5SDimitry Andric 5192*0b57cec5SDimitry Andric unsigned DestSub0 = MRI.createVirtualRegister(NewDestSubRC); 5193*0b57cec5SDimitry Andric MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0); 5194*0b57cec5SDimitry Andric 5195*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5196*0b57cec5SDimitry Andric AMDGPU::sub1, Src0SubRC); 5197*0b57cec5SDimitry Andric 5198*0b57cec5SDimitry Andric unsigned DestSub1 = MRI.createVirtualRegister(NewDestSubRC); 5199*0b57cec5SDimitry Andric MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1); 5200*0b57cec5SDimitry Andric 5201*0b57cec5SDimitry Andric unsigned FullDestReg = MRI.createVirtualRegister(NewDestRC); 5202*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg) 5203*0b57cec5SDimitry Andric .addReg(DestSub0) 5204*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 5205*0b57cec5SDimitry Andric .addReg(DestSub1) 5206*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 5207*0b57cec5SDimitry Andric 5208*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), FullDestReg); 5209*0b57cec5SDimitry Andric 5210*0b57cec5SDimitry Andric Worklist.insert(&LoHalf); 5211*0b57cec5SDimitry Andric Worklist.insert(&HiHalf); 5212*0b57cec5SDimitry Andric 5213*0b57cec5SDimitry Andric // We don't need to legalizeOperands here because for a single operand, src0 5214*0b57cec5SDimitry Andric // will support any kind of input. 5215*0b57cec5SDimitry Andric 5216*0b57cec5SDimitry Andric // Move all users of this moved value. 5217*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist); 5218*0b57cec5SDimitry Andric } 5219*0b57cec5SDimitry Andric 5220*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitAddSub(SetVectorType &Worklist, 5221*0b57cec5SDimitry Andric MachineInstr &Inst, 5222*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 5223*0b57cec5SDimitry Andric bool IsAdd = (Inst.getOpcode() == AMDGPU::S_ADD_U64_PSEUDO); 5224*0b57cec5SDimitry Andric 5225*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5226*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5227*0b57cec5SDimitry Andric const auto *CarryRC = RI.getRegClass(AMDGPU::SReg_1_XEXECRegClassID); 5228*0b57cec5SDimitry Andric 5229*0b57cec5SDimitry Andric unsigned FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass); 5230*0b57cec5SDimitry Andric unsigned DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5231*0b57cec5SDimitry Andric unsigned DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5232*0b57cec5SDimitry Andric 5233*0b57cec5SDimitry Andric unsigned CarryReg = MRI.createVirtualRegister(CarryRC); 5234*0b57cec5SDimitry Andric unsigned DeadCarryReg = MRI.createVirtualRegister(CarryRC); 5235*0b57cec5SDimitry Andric 5236*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5237*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5238*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5239*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5240*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5241*0b57cec5SDimitry Andric 5242*0b57cec5SDimitry Andric const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg()); 5243*0b57cec5SDimitry Andric const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg()); 5244*0b57cec5SDimitry Andric const TargetRegisterClass *Src0SubRC = RI.getSubRegClass(Src0RC, AMDGPU::sub0); 5245*0b57cec5SDimitry Andric const TargetRegisterClass *Src1SubRC = RI.getSubRegClass(Src1RC, AMDGPU::sub0); 5246*0b57cec5SDimitry Andric 5247*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5248*0b57cec5SDimitry Andric AMDGPU::sub0, Src0SubRC); 5249*0b57cec5SDimitry Andric MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, 5250*0b57cec5SDimitry Andric AMDGPU::sub0, Src1SubRC); 5251*0b57cec5SDimitry Andric 5252*0b57cec5SDimitry Andric 5253*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5254*0b57cec5SDimitry Andric AMDGPU::sub1, Src0SubRC); 5255*0b57cec5SDimitry Andric MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, 5256*0b57cec5SDimitry Andric AMDGPU::sub1, Src1SubRC); 5257*0b57cec5SDimitry Andric 5258*0b57cec5SDimitry Andric unsigned LoOpc = IsAdd ? AMDGPU::V_ADD_I32_e64 : AMDGPU::V_SUB_I32_e64; 5259*0b57cec5SDimitry Andric MachineInstr *LoHalf = 5260*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(LoOpc), DestSub0) 5261*0b57cec5SDimitry Andric .addReg(CarryReg, RegState::Define) 5262*0b57cec5SDimitry Andric .add(SrcReg0Sub0) 5263*0b57cec5SDimitry Andric .add(SrcReg1Sub0) 5264*0b57cec5SDimitry Andric .addImm(0); // clamp bit 5265*0b57cec5SDimitry Andric 5266*0b57cec5SDimitry Andric unsigned HiOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64; 5267*0b57cec5SDimitry Andric MachineInstr *HiHalf = 5268*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(HiOpc), DestSub1) 5269*0b57cec5SDimitry Andric .addReg(DeadCarryReg, RegState::Define | RegState::Dead) 5270*0b57cec5SDimitry Andric .add(SrcReg0Sub1) 5271*0b57cec5SDimitry Andric .add(SrcReg1Sub1) 5272*0b57cec5SDimitry Andric .addReg(CarryReg, RegState::Kill) 5273*0b57cec5SDimitry Andric .addImm(0); // clamp bit 5274*0b57cec5SDimitry Andric 5275*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg) 5276*0b57cec5SDimitry Andric .addReg(DestSub0) 5277*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 5278*0b57cec5SDimitry Andric .addReg(DestSub1) 5279*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 5280*0b57cec5SDimitry Andric 5281*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), FullDestReg); 5282*0b57cec5SDimitry Andric 5283*0b57cec5SDimitry Andric // Try to legalize the operands in case we need to swap the order to keep it 5284*0b57cec5SDimitry Andric // valid. 5285*0b57cec5SDimitry Andric legalizeOperands(*LoHalf, MDT); 5286*0b57cec5SDimitry Andric legalizeOperands(*HiHalf, MDT); 5287*0b57cec5SDimitry Andric 5288*0b57cec5SDimitry Andric // Move all users of this moved vlaue. 5289*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist); 5290*0b57cec5SDimitry Andric } 5291*0b57cec5SDimitry Andric 5292*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitBinaryOp(SetVectorType &Worklist, 5293*0b57cec5SDimitry Andric MachineInstr &Inst, unsigned Opcode, 5294*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 5295*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5296*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5297*0b57cec5SDimitry Andric 5298*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5299*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5300*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5301*0b57cec5SDimitry Andric DebugLoc DL = Inst.getDebugLoc(); 5302*0b57cec5SDimitry Andric 5303*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5304*0b57cec5SDimitry Andric 5305*0b57cec5SDimitry Andric const MCInstrDesc &InstDesc = get(Opcode); 5306*0b57cec5SDimitry Andric const TargetRegisterClass *Src0RC = Src0.isReg() ? 5307*0b57cec5SDimitry Andric MRI.getRegClass(Src0.getReg()) : 5308*0b57cec5SDimitry Andric &AMDGPU::SGPR_32RegClass; 5309*0b57cec5SDimitry Andric 5310*0b57cec5SDimitry Andric const TargetRegisterClass *Src0SubRC = RI.getSubRegClass(Src0RC, AMDGPU::sub0); 5311*0b57cec5SDimitry Andric const TargetRegisterClass *Src1RC = Src1.isReg() ? 5312*0b57cec5SDimitry Andric MRI.getRegClass(Src1.getReg()) : 5313*0b57cec5SDimitry Andric &AMDGPU::SGPR_32RegClass; 5314*0b57cec5SDimitry Andric 5315*0b57cec5SDimitry Andric const TargetRegisterClass *Src1SubRC = RI.getSubRegClass(Src1RC, AMDGPU::sub0); 5316*0b57cec5SDimitry Andric 5317*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5318*0b57cec5SDimitry Andric AMDGPU::sub0, Src0SubRC); 5319*0b57cec5SDimitry Andric MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, 5320*0b57cec5SDimitry Andric AMDGPU::sub0, Src1SubRC); 5321*0b57cec5SDimitry Andric MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, 5322*0b57cec5SDimitry Andric AMDGPU::sub1, Src0SubRC); 5323*0b57cec5SDimitry Andric MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, 5324*0b57cec5SDimitry Andric AMDGPU::sub1, Src1SubRC); 5325*0b57cec5SDimitry Andric 5326*0b57cec5SDimitry Andric const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg()); 5327*0b57cec5SDimitry Andric const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC); 5328*0b57cec5SDimitry Andric const TargetRegisterClass *NewDestSubRC = RI.getSubRegClass(NewDestRC, AMDGPU::sub0); 5329*0b57cec5SDimitry Andric 5330*0b57cec5SDimitry Andric unsigned DestSub0 = MRI.createVirtualRegister(NewDestSubRC); 5331*0b57cec5SDimitry Andric MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0) 5332*0b57cec5SDimitry Andric .add(SrcReg0Sub0) 5333*0b57cec5SDimitry Andric .add(SrcReg1Sub0); 5334*0b57cec5SDimitry Andric 5335*0b57cec5SDimitry Andric unsigned DestSub1 = MRI.createVirtualRegister(NewDestSubRC); 5336*0b57cec5SDimitry Andric MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1) 5337*0b57cec5SDimitry Andric .add(SrcReg0Sub1) 5338*0b57cec5SDimitry Andric .add(SrcReg1Sub1); 5339*0b57cec5SDimitry Andric 5340*0b57cec5SDimitry Andric unsigned FullDestReg = MRI.createVirtualRegister(NewDestRC); 5341*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg) 5342*0b57cec5SDimitry Andric .addReg(DestSub0) 5343*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 5344*0b57cec5SDimitry Andric .addReg(DestSub1) 5345*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 5346*0b57cec5SDimitry Andric 5347*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), FullDestReg); 5348*0b57cec5SDimitry Andric 5349*0b57cec5SDimitry Andric Worklist.insert(&LoHalf); 5350*0b57cec5SDimitry Andric Worklist.insert(&HiHalf); 5351*0b57cec5SDimitry Andric 5352*0b57cec5SDimitry Andric // Move all users of this moved vlaue. 5353*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist); 5354*0b57cec5SDimitry Andric } 5355*0b57cec5SDimitry Andric 5356*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitXnor(SetVectorType &Worklist, 5357*0b57cec5SDimitry Andric MachineInstr &Inst, 5358*0b57cec5SDimitry Andric MachineDominatorTree *MDT) const { 5359*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5360*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5361*0b57cec5SDimitry Andric 5362*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5363*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5364*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5365*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5366*0b57cec5SDimitry Andric 5367*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5368*0b57cec5SDimitry Andric 5369*0b57cec5SDimitry Andric const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg()); 5370*0b57cec5SDimitry Andric 5371*0b57cec5SDimitry Andric unsigned Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass); 5372*0b57cec5SDimitry Andric 5373*0b57cec5SDimitry Andric MachineOperand* Op0; 5374*0b57cec5SDimitry Andric MachineOperand* Op1; 5375*0b57cec5SDimitry Andric 5376*0b57cec5SDimitry Andric if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) { 5377*0b57cec5SDimitry Andric Op0 = &Src0; 5378*0b57cec5SDimitry Andric Op1 = &Src1; 5379*0b57cec5SDimitry Andric } else { 5380*0b57cec5SDimitry Andric Op0 = &Src1; 5381*0b57cec5SDimitry Andric Op1 = &Src0; 5382*0b57cec5SDimitry Andric } 5383*0b57cec5SDimitry Andric 5384*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm) 5385*0b57cec5SDimitry Andric .add(*Op0); 5386*0b57cec5SDimitry Andric 5387*0b57cec5SDimitry Andric unsigned NewDest = MRI.createVirtualRegister(DestRC); 5388*0b57cec5SDimitry Andric 5389*0b57cec5SDimitry Andric MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest) 5390*0b57cec5SDimitry Andric .addReg(Interm) 5391*0b57cec5SDimitry Andric .add(*Op1); 5392*0b57cec5SDimitry Andric 5393*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), NewDest); 5394*0b57cec5SDimitry Andric 5395*0b57cec5SDimitry Andric Worklist.insert(&Xor); 5396*0b57cec5SDimitry Andric } 5397*0b57cec5SDimitry Andric 5398*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitBCNT( 5399*0b57cec5SDimitry Andric SetVectorType &Worklist, MachineInstr &Inst) const { 5400*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5401*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5402*0b57cec5SDimitry Andric 5403*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5404*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5405*0b57cec5SDimitry Andric 5406*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5407*0b57cec5SDimitry Andric MachineOperand &Src = Inst.getOperand(1); 5408*0b57cec5SDimitry Andric 5409*0b57cec5SDimitry Andric const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64); 5410*0b57cec5SDimitry Andric const TargetRegisterClass *SrcRC = Src.isReg() ? 5411*0b57cec5SDimitry Andric MRI.getRegClass(Src.getReg()) : 5412*0b57cec5SDimitry Andric &AMDGPU::SGPR_32RegClass; 5413*0b57cec5SDimitry Andric 5414*0b57cec5SDimitry Andric unsigned MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5415*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5416*0b57cec5SDimitry Andric 5417*0b57cec5SDimitry Andric const TargetRegisterClass *SrcSubRC = RI.getSubRegClass(SrcRC, AMDGPU::sub0); 5418*0b57cec5SDimitry Andric 5419*0b57cec5SDimitry Andric MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, 5420*0b57cec5SDimitry Andric AMDGPU::sub0, SrcSubRC); 5421*0b57cec5SDimitry Andric MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, 5422*0b57cec5SDimitry Andric AMDGPU::sub1, SrcSubRC); 5423*0b57cec5SDimitry Andric 5424*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0); 5425*0b57cec5SDimitry Andric 5426*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg); 5427*0b57cec5SDimitry Andric 5428*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), ResultReg); 5429*0b57cec5SDimitry Andric 5430*0b57cec5SDimitry Andric // We don't need to legalize operands here. src0 for etiher instruction can be 5431*0b57cec5SDimitry Andric // an SGPR, and the second input is unused or determined here. 5432*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5433*0b57cec5SDimitry Andric } 5434*0b57cec5SDimitry Andric 5435*0b57cec5SDimitry Andric void SIInstrInfo::splitScalar64BitBFE(SetVectorType &Worklist, 5436*0b57cec5SDimitry Andric MachineInstr &Inst) const { 5437*0b57cec5SDimitry Andric MachineBasicBlock &MBB = *Inst.getParent(); 5438*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 5439*0b57cec5SDimitry Andric MachineBasicBlock::iterator MII = Inst; 5440*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5441*0b57cec5SDimitry Andric 5442*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5443*0b57cec5SDimitry Andric uint32_t Imm = Inst.getOperand(2).getImm(); 5444*0b57cec5SDimitry Andric uint32_t Offset = Imm & 0x3f; // Extract bits [5:0]. 5445*0b57cec5SDimitry Andric uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16]. 5446*0b57cec5SDimitry Andric 5447*0b57cec5SDimitry Andric (void) Offset; 5448*0b57cec5SDimitry Andric 5449*0b57cec5SDimitry Andric // Only sext_inreg cases handled. 5450*0b57cec5SDimitry Andric assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 && 5451*0b57cec5SDimitry Andric Offset == 0 && "Not implemented"); 5452*0b57cec5SDimitry Andric 5453*0b57cec5SDimitry Andric if (BitWidth < 32) { 5454*0b57cec5SDimitry Andric unsigned MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5455*0b57cec5SDimitry Andric unsigned MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5456*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass); 5457*0b57cec5SDimitry Andric 5458*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32), MidRegLo) 5459*0b57cec5SDimitry Andric .addReg(Inst.getOperand(1).getReg(), 0, AMDGPU::sub0) 5460*0b57cec5SDimitry Andric .addImm(0) 5461*0b57cec5SDimitry Andric .addImm(BitWidth); 5462*0b57cec5SDimitry Andric 5463*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi) 5464*0b57cec5SDimitry Andric .addImm(31) 5465*0b57cec5SDimitry Andric .addReg(MidRegLo); 5466*0b57cec5SDimitry Andric 5467*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg) 5468*0b57cec5SDimitry Andric .addReg(MidRegLo) 5469*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 5470*0b57cec5SDimitry Andric .addReg(MidRegHi) 5471*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 5472*0b57cec5SDimitry Andric 5473*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), ResultReg); 5474*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5475*0b57cec5SDimitry Andric return; 5476*0b57cec5SDimitry Andric } 5477*0b57cec5SDimitry Andric 5478*0b57cec5SDimitry Andric MachineOperand &Src = Inst.getOperand(1); 5479*0b57cec5SDimitry Andric unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5480*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass); 5481*0b57cec5SDimitry Andric 5482*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg) 5483*0b57cec5SDimitry Andric .addImm(31) 5484*0b57cec5SDimitry Andric .addReg(Src.getReg(), 0, AMDGPU::sub0); 5485*0b57cec5SDimitry Andric 5486*0b57cec5SDimitry Andric BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg) 5487*0b57cec5SDimitry Andric .addReg(Src.getReg(), 0, AMDGPU::sub0) 5488*0b57cec5SDimitry Andric .addImm(AMDGPU::sub0) 5489*0b57cec5SDimitry Andric .addReg(TmpReg) 5490*0b57cec5SDimitry Andric .addImm(AMDGPU::sub1); 5491*0b57cec5SDimitry Andric 5492*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), ResultReg); 5493*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5494*0b57cec5SDimitry Andric } 5495*0b57cec5SDimitry Andric 5496*0b57cec5SDimitry Andric void SIInstrInfo::addUsersToMoveToVALUWorklist( 5497*0b57cec5SDimitry Andric unsigned DstReg, 5498*0b57cec5SDimitry Andric MachineRegisterInfo &MRI, 5499*0b57cec5SDimitry Andric SetVectorType &Worklist) const { 5500*0b57cec5SDimitry Andric for (MachineRegisterInfo::use_iterator I = MRI.use_begin(DstReg), 5501*0b57cec5SDimitry Andric E = MRI.use_end(); I != E;) { 5502*0b57cec5SDimitry Andric MachineInstr &UseMI = *I->getParent(); 5503*0b57cec5SDimitry Andric 5504*0b57cec5SDimitry Andric unsigned OpNo = 0; 5505*0b57cec5SDimitry Andric 5506*0b57cec5SDimitry Andric switch (UseMI.getOpcode()) { 5507*0b57cec5SDimitry Andric case AMDGPU::COPY: 5508*0b57cec5SDimitry Andric case AMDGPU::WQM: 5509*0b57cec5SDimitry Andric case AMDGPU::WWM: 5510*0b57cec5SDimitry Andric case AMDGPU::REG_SEQUENCE: 5511*0b57cec5SDimitry Andric case AMDGPU::PHI: 5512*0b57cec5SDimitry Andric case AMDGPU::INSERT_SUBREG: 5513*0b57cec5SDimitry Andric break; 5514*0b57cec5SDimitry Andric default: 5515*0b57cec5SDimitry Andric OpNo = I.getOperandNo(); 5516*0b57cec5SDimitry Andric break; 5517*0b57cec5SDimitry Andric } 5518*0b57cec5SDimitry Andric 5519*0b57cec5SDimitry Andric if (!RI.hasVectorRegisters(getOpRegClass(UseMI, OpNo))) { 5520*0b57cec5SDimitry Andric Worklist.insert(&UseMI); 5521*0b57cec5SDimitry Andric 5522*0b57cec5SDimitry Andric do { 5523*0b57cec5SDimitry Andric ++I; 5524*0b57cec5SDimitry Andric } while (I != E && I->getParent() == &UseMI); 5525*0b57cec5SDimitry Andric } else { 5526*0b57cec5SDimitry Andric ++I; 5527*0b57cec5SDimitry Andric } 5528*0b57cec5SDimitry Andric } 5529*0b57cec5SDimitry Andric } 5530*0b57cec5SDimitry Andric 5531*0b57cec5SDimitry Andric void SIInstrInfo::movePackToVALU(SetVectorType &Worklist, 5532*0b57cec5SDimitry Andric MachineRegisterInfo &MRI, 5533*0b57cec5SDimitry Andric MachineInstr &Inst) const { 5534*0b57cec5SDimitry Andric unsigned ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5535*0b57cec5SDimitry Andric MachineBasicBlock *MBB = Inst.getParent(); 5536*0b57cec5SDimitry Andric MachineOperand &Src0 = Inst.getOperand(1); 5537*0b57cec5SDimitry Andric MachineOperand &Src1 = Inst.getOperand(2); 5538*0b57cec5SDimitry Andric const DebugLoc &DL = Inst.getDebugLoc(); 5539*0b57cec5SDimitry Andric 5540*0b57cec5SDimitry Andric switch (Inst.getOpcode()) { 5541*0b57cec5SDimitry Andric case AMDGPU::S_PACK_LL_B32_B16: { 5542*0b57cec5SDimitry Andric unsigned ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5543*0b57cec5SDimitry Andric unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5544*0b57cec5SDimitry Andric 5545*0b57cec5SDimitry Andric // FIXME: Can do a lot better if we know the high bits of src0 or src1 are 5546*0b57cec5SDimitry Andric // 0. 5547*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg) 5548*0b57cec5SDimitry Andric .addImm(0xffff); 5549*0b57cec5SDimitry Andric 5550*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg) 5551*0b57cec5SDimitry Andric .addReg(ImmReg, RegState::Kill) 5552*0b57cec5SDimitry Andric .add(Src0); 5553*0b57cec5SDimitry Andric 5554*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32), ResultReg) 5555*0b57cec5SDimitry Andric .add(Src1) 5556*0b57cec5SDimitry Andric .addImm(16) 5557*0b57cec5SDimitry Andric .addReg(TmpReg, RegState::Kill); 5558*0b57cec5SDimitry Andric break; 5559*0b57cec5SDimitry Andric } 5560*0b57cec5SDimitry Andric case AMDGPU::S_PACK_LH_B32_B16: { 5561*0b57cec5SDimitry Andric unsigned ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5562*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg) 5563*0b57cec5SDimitry Andric .addImm(0xffff); 5564*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32), ResultReg) 5565*0b57cec5SDimitry Andric .addReg(ImmReg, RegState::Kill) 5566*0b57cec5SDimitry Andric .add(Src0) 5567*0b57cec5SDimitry Andric .add(Src1); 5568*0b57cec5SDimitry Andric break; 5569*0b57cec5SDimitry Andric } 5570*0b57cec5SDimitry Andric case AMDGPU::S_PACK_HH_B32_B16: { 5571*0b57cec5SDimitry Andric unsigned ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5572*0b57cec5SDimitry Andric unsigned TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); 5573*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg) 5574*0b57cec5SDimitry Andric .addImm(16) 5575*0b57cec5SDimitry Andric .add(Src0); 5576*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg) 5577*0b57cec5SDimitry Andric .addImm(0xffff0000); 5578*0b57cec5SDimitry Andric BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32), ResultReg) 5579*0b57cec5SDimitry Andric .add(Src1) 5580*0b57cec5SDimitry Andric .addReg(ImmReg, RegState::Kill) 5581*0b57cec5SDimitry Andric .addReg(TmpReg, RegState::Kill); 5582*0b57cec5SDimitry Andric break; 5583*0b57cec5SDimitry Andric } 5584*0b57cec5SDimitry Andric default: 5585*0b57cec5SDimitry Andric llvm_unreachable("unhandled s_pack_* instruction"); 5586*0b57cec5SDimitry Andric } 5587*0b57cec5SDimitry Andric 5588*0b57cec5SDimitry Andric MachineOperand &Dest = Inst.getOperand(0); 5589*0b57cec5SDimitry Andric MRI.replaceRegWith(Dest.getReg(), ResultReg); 5590*0b57cec5SDimitry Andric addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist); 5591*0b57cec5SDimitry Andric } 5592*0b57cec5SDimitry Andric 5593*0b57cec5SDimitry Andric void SIInstrInfo::addSCCDefUsersToVALUWorklist(MachineOperand &Op, 5594*0b57cec5SDimitry Andric MachineInstr &SCCDefInst, 5595*0b57cec5SDimitry Andric SetVectorType &Worklist) const { 5596*0b57cec5SDimitry Andric // Ensure that def inst defines SCC, which is still live. 5597*0b57cec5SDimitry Andric assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() && 5598*0b57cec5SDimitry Andric !Op.isDead() && Op.getParent() == &SCCDefInst); 5599*0b57cec5SDimitry Andric // This assumes that all the users of SCC are in the same block 5600*0b57cec5SDimitry Andric // as the SCC def. 5601*0b57cec5SDimitry Andric for (MachineInstr &MI : // Skip the def inst itself. 5602*0b57cec5SDimitry Andric make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)), 5603*0b57cec5SDimitry Andric SCCDefInst.getParent()->end())) { 5604*0b57cec5SDimitry Andric // Check if SCC is used first. 5605*0b57cec5SDimitry Andric if (MI.findRegisterUseOperandIdx(AMDGPU::SCC, false, &RI) != -1) 5606*0b57cec5SDimitry Andric Worklist.insert(&MI); 5607*0b57cec5SDimitry Andric // Exit if we find another SCC def. 5608*0b57cec5SDimitry Andric if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, false, false, &RI) != -1) 5609*0b57cec5SDimitry Andric return; 5610*0b57cec5SDimitry Andric } 5611*0b57cec5SDimitry Andric } 5612*0b57cec5SDimitry Andric 5613*0b57cec5SDimitry Andric const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass( 5614*0b57cec5SDimitry Andric const MachineInstr &Inst) const { 5615*0b57cec5SDimitry Andric const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0); 5616*0b57cec5SDimitry Andric 5617*0b57cec5SDimitry Andric switch (Inst.getOpcode()) { 5618*0b57cec5SDimitry Andric // For target instructions, getOpRegClass just returns the virtual register 5619*0b57cec5SDimitry Andric // class associated with the operand, so we need to find an equivalent VGPR 5620*0b57cec5SDimitry Andric // register class in order to move the instruction to the VALU. 5621*0b57cec5SDimitry Andric case AMDGPU::COPY: 5622*0b57cec5SDimitry Andric case AMDGPU::PHI: 5623*0b57cec5SDimitry Andric case AMDGPU::REG_SEQUENCE: 5624*0b57cec5SDimitry Andric case AMDGPU::INSERT_SUBREG: 5625*0b57cec5SDimitry Andric case AMDGPU::WQM: 5626*0b57cec5SDimitry Andric case AMDGPU::WWM: { 5627*0b57cec5SDimitry Andric const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1); 5628*0b57cec5SDimitry Andric if (RI.hasAGPRs(SrcRC)) { 5629*0b57cec5SDimitry Andric if (RI.hasAGPRs(NewDstRC)) 5630*0b57cec5SDimitry Andric return nullptr; 5631*0b57cec5SDimitry Andric 5632*0b57cec5SDimitry Andric NewDstRC = RI.getEquivalentAGPRClass(NewDstRC); 5633*0b57cec5SDimitry Andric if (!NewDstRC) 5634*0b57cec5SDimitry Andric return nullptr; 5635*0b57cec5SDimitry Andric } else { 5636*0b57cec5SDimitry Andric if (RI.hasVGPRs(NewDstRC)) 5637*0b57cec5SDimitry Andric return nullptr; 5638*0b57cec5SDimitry Andric 5639*0b57cec5SDimitry Andric NewDstRC = RI.getEquivalentVGPRClass(NewDstRC); 5640*0b57cec5SDimitry Andric if (!NewDstRC) 5641*0b57cec5SDimitry Andric return nullptr; 5642*0b57cec5SDimitry Andric } 5643*0b57cec5SDimitry Andric 5644*0b57cec5SDimitry Andric return NewDstRC; 5645*0b57cec5SDimitry Andric } 5646*0b57cec5SDimitry Andric default: 5647*0b57cec5SDimitry Andric return NewDstRC; 5648*0b57cec5SDimitry Andric } 5649*0b57cec5SDimitry Andric } 5650*0b57cec5SDimitry Andric 5651*0b57cec5SDimitry Andric // Find the one SGPR operand we are allowed to use. 5652*0b57cec5SDimitry Andric unsigned SIInstrInfo::findUsedSGPR(const MachineInstr &MI, 5653*0b57cec5SDimitry Andric int OpIndices[3]) const { 5654*0b57cec5SDimitry Andric const MCInstrDesc &Desc = MI.getDesc(); 5655*0b57cec5SDimitry Andric 5656*0b57cec5SDimitry Andric // Find the one SGPR operand we are allowed to use. 5657*0b57cec5SDimitry Andric // 5658*0b57cec5SDimitry Andric // First we need to consider the instruction's operand requirements before 5659*0b57cec5SDimitry Andric // legalizing. Some operands are required to be SGPRs, such as implicit uses 5660*0b57cec5SDimitry Andric // of VCC, but we are still bound by the constant bus requirement to only use 5661*0b57cec5SDimitry Andric // one. 5662*0b57cec5SDimitry Andric // 5663*0b57cec5SDimitry Andric // If the operand's class is an SGPR, we can never move it. 5664*0b57cec5SDimitry Andric 5665*0b57cec5SDimitry Andric unsigned SGPRReg = findImplicitSGPRRead(MI); 5666*0b57cec5SDimitry Andric if (SGPRReg != AMDGPU::NoRegister) 5667*0b57cec5SDimitry Andric return SGPRReg; 5668*0b57cec5SDimitry Andric 5669*0b57cec5SDimitry Andric unsigned UsedSGPRs[3] = { AMDGPU::NoRegister }; 5670*0b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 5671*0b57cec5SDimitry Andric 5672*0b57cec5SDimitry Andric for (unsigned i = 0; i < 3; ++i) { 5673*0b57cec5SDimitry Andric int Idx = OpIndices[i]; 5674*0b57cec5SDimitry Andric if (Idx == -1) 5675*0b57cec5SDimitry Andric break; 5676*0b57cec5SDimitry Andric 5677*0b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(Idx); 5678*0b57cec5SDimitry Andric if (!MO.isReg()) 5679*0b57cec5SDimitry Andric continue; 5680*0b57cec5SDimitry Andric 5681*0b57cec5SDimitry Andric // Is this operand statically required to be an SGPR based on the operand 5682*0b57cec5SDimitry Andric // constraints? 5683*0b57cec5SDimitry Andric const TargetRegisterClass *OpRC = RI.getRegClass(Desc.OpInfo[Idx].RegClass); 5684*0b57cec5SDimitry Andric bool IsRequiredSGPR = RI.isSGPRClass(OpRC); 5685*0b57cec5SDimitry Andric if (IsRequiredSGPR) 5686*0b57cec5SDimitry Andric return MO.getReg(); 5687*0b57cec5SDimitry Andric 5688*0b57cec5SDimitry Andric // If this could be a VGPR or an SGPR, Check the dynamic register class. 5689*0b57cec5SDimitry Andric unsigned Reg = MO.getReg(); 5690*0b57cec5SDimitry Andric const TargetRegisterClass *RegRC = MRI.getRegClass(Reg); 5691*0b57cec5SDimitry Andric if (RI.isSGPRClass(RegRC)) 5692*0b57cec5SDimitry Andric UsedSGPRs[i] = Reg; 5693*0b57cec5SDimitry Andric } 5694*0b57cec5SDimitry Andric 5695*0b57cec5SDimitry Andric // We don't have a required SGPR operand, so we have a bit more freedom in 5696*0b57cec5SDimitry Andric // selecting operands to move. 5697*0b57cec5SDimitry Andric 5698*0b57cec5SDimitry Andric // Try to select the most used SGPR. If an SGPR is equal to one of the 5699*0b57cec5SDimitry Andric // others, we choose that. 5700*0b57cec5SDimitry Andric // 5701*0b57cec5SDimitry Andric // e.g. 5702*0b57cec5SDimitry Andric // V_FMA_F32 v0, s0, s0, s0 -> No moves 5703*0b57cec5SDimitry Andric // V_FMA_F32 v0, s0, s1, s0 -> Move s1 5704*0b57cec5SDimitry Andric 5705*0b57cec5SDimitry Andric // TODO: If some of the operands are 64-bit SGPRs and some 32, we should 5706*0b57cec5SDimitry Andric // prefer those. 5707*0b57cec5SDimitry Andric 5708*0b57cec5SDimitry Andric if (UsedSGPRs[0] != AMDGPU::NoRegister) { 5709*0b57cec5SDimitry Andric if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2]) 5710*0b57cec5SDimitry Andric SGPRReg = UsedSGPRs[0]; 5711*0b57cec5SDimitry Andric } 5712*0b57cec5SDimitry Andric 5713*0b57cec5SDimitry Andric if (SGPRReg == AMDGPU::NoRegister && UsedSGPRs[1] != AMDGPU::NoRegister) { 5714*0b57cec5SDimitry Andric if (UsedSGPRs[1] == UsedSGPRs[2]) 5715*0b57cec5SDimitry Andric SGPRReg = UsedSGPRs[1]; 5716*0b57cec5SDimitry Andric } 5717*0b57cec5SDimitry Andric 5718*0b57cec5SDimitry Andric return SGPRReg; 5719*0b57cec5SDimitry Andric } 5720*0b57cec5SDimitry Andric 5721*0b57cec5SDimitry Andric MachineOperand *SIInstrInfo::getNamedOperand(MachineInstr &MI, 5722*0b57cec5SDimitry Andric unsigned OperandName) const { 5723*0b57cec5SDimitry Andric int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName); 5724*0b57cec5SDimitry Andric if (Idx == -1) 5725*0b57cec5SDimitry Andric return nullptr; 5726*0b57cec5SDimitry Andric 5727*0b57cec5SDimitry Andric return &MI.getOperand(Idx); 5728*0b57cec5SDimitry Andric } 5729*0b57cec5SDimitry Andric 5730*0b57cec5SDimitry Andric uint64_t SIInstrInfo::getDefaultRsrcDataFormat() const { 5731*0b57cec5SDimitry Andric if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) { 5732*0b57cec5SDimitry Andric return (22ULL << 44) | // IMG_FORMAT_32_FLOAT 5733*0b57cec5SDimitry Andric (1ULL << 56) | // RESOURCE_LEVEL = 1 5734*0b57cec5SDimitry Andric (3ULL << 60); // OOB_SELECT = 3 5735*0b57cec5SDimitry Andric } 5736*0b57cec5SDimitry Andric 5737*0b57cec5SDimitry Andric uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT; 5738*0b57cec5SDimitry Andric if (ST.isAmdHsaOS()) { 5739*0b57cec5SDimitry Andric // Set ATC = 1. GFX9 doesn't have this bit. 5740*0b57cec5SDimitry Andric if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) 5741*0b57cec5SDimitry Andric RsrcDataFormat |= (1ULL << 56); 5742*0b57cec5SDimitry Andric 5743*0b57cec5SDimitry Andric // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this. 5744*0b57cec5SDimitry Andric // BTW, it disables TC L2 and therefore decreases performance. 5745*0b57cec5SDimitry Andric if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) 5746*0b57cec5SDimitry Andric RsrcDataFormat |= (2ULL << 59); 5747*0b57cec5SDimitry Andric } 5748*0b57cec5SDimitry Andric 5749*0b57cec5SDimitry Andric return RsrcDataFormat; 5750*0b57cec5SDimitry Andric } 5751*0b57cec5SDimitry Andric 5752*0b57cec5SDimitry Andric uint64_t SIInstrInfo::getScratchRsrcWords23() const { 5753*0b57cec5SDimitry Andric uint64_t Rsrc23 = getDefaultRsrcDataFormat() | 5754*0b57cec5SDimitry Andric AMDGPU::RSRC_TID_ENABLE | 5755*0b57cec5SDimitry Andric 0xffffffff; // Size; 5756*0b57cec5SDimitry Andric 5757*0b57cec5SDimitry Andric // GFX9 doesn't have ELEMENT_SIZE. 5758*0b57cec5SDimitry Andric if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) { 5759*0b57cec5SDimitry Andric uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize()) - 1; 5760*0b57cec5SDimitry Andric Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT; 5761*0b57cec5SDimitry Andric } 5762*0b57cec5SDimitry Andric 5763*0b57cec5SDimitry Andric // IndexStride = 64 / 32. 5764*0b57cec5SDimitry Andric uint64_t IndexStride = ST.getWavefrontSize() == 64 ? 3 : 2; 5765*0b57cec5SDimitry Andric Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT; 5766*0b57cec5SDimitry Andric 5767*0b57cec5SDimitry Andric // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17]. 5768*0b57cec5SDimitry Andric // Clear them unless we want a huge stride. 5769*0b57cec5SDimitry Andric if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS && 5770*0b57cec5SDimitry Andric ST.getGeneration() <= AMDGPUSubtarget::GFX9) 5771*0b57cec5SDimitry Andric Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT; 5772*0b57cec5SDimitry Andric 5773*0b57cec5SDimitry Andric return Rsrc23; 5774*0b57cec5SDimitry Andric } 5775*0b57cec5SDimitry Andric 5776*0b57cec5SDimitry Andric bool SIInstrInfo::isLowLatencyInstruction(const MachineInstr &MI) const { 5777*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 5778*0b57cec5SDimitry Andric 5779*0b57cec5SDimitry Andric return isSMRD(Opc); 5780*0b57cec5SDimitry Andric } 5781*0b57cec5SDimitry Andric 5782*0b57cec5SDimitry Andric bool SIInstrInfo::isHighLatencyInstruction(const MachineInstr &MI) const { 5783*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 5784*0b57cec5SDimitry Andric 5785*0b57cec5SDimitry Andric return isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc); 5786*0b57cec5SDimitry Andric } 5787*0b57cec5SDimitry Andric 5788*0b57cec5SDimitry Andric unsigned SIInstrInfo::isStackAccess(const MachineInstr &MI, 5789*0b57cec5SDimitry Andric int &FrameIndex) const { 5790*0b57cec5SDimitry Andric const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr); 5791*0b57cec5SDimitry Andric if (!Addr || !Addr->isFI()) 5792*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 5793*0b57cec5SDimitry Andric 5794*0b57cec5SDimitry Andric assert(!MI.memoperands_empty() && 5795*0b57cec5SDimitry Andric (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS); 5796*0b57cec5SDimitry Andric 5797*0b57cec5SDimitry Andric FrameIndex = Addr->getIndex(); 5798*0b57cec5SDimitry Andric return getNamedOperand(MI, AMDGPU::OpName::vdata)->getReg(); 5799*0b57cec5SDimitry Andric } 5800*0b57cec5SDimitry Andric 5801*0b57cec5SDimitry Andric unsigned SIInstrInfo::isSGPRStackAccess(const MachineInstr &MI, 5802*0b57cec5SDimitry Andric int &FrameIndex) const { 5803*0b57cec5SDimitry Andric const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr); 5804*0b57cec5SDimitry Andric assert(Addr && Addr->isFI()); 5805*0b57cec5SDimitry Andric FrameIndex = Addr->getIndex(); 5806*0b57cec5SDimitry Andric return getNamedOperand(MI, AMDGPU::OpName::data)->getReg(); 5807*0b57cec5SDimitry Andric } 5808*0b57cec5SDimitry Andric 5809*0b57cec5SDimitry Andric unsigned SIInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 5810*0b57cec5SDimitry Andric int &FrameIndex) const { 5811*0b57cec5SDimitry Andric if (!MI.mayLoad()) 5812*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 5813*0b57cec5SDimitry Andric 5814*0b57cec5SDimitry Andric if (isMUBUF(MI) || isVGPRSpill(MI)) 5815*0b57cec5SDimitry Andric return isStackAccess(MI, FrameIndex); 5816*0b57cec5SDimitry Andric 5817*0b57cec5SDimitry Andric if (isSGPRSpill(MI)) 5818*0b57cec5SDimitry Andric return isSGPRStackAccess(MI, FrameIndex); 5819*0b57cec5SDimitry Andric 5820*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 5821*0b57cec5SDimitry Andric } 5822*0b57cec5SDimitry Andric 5823*0b57cec5SDimitry Andric unsigned SIInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 5824*0b57cec5SDimitry Andric int &FrameIndex) const { 5825*0b57cec5SDimitry Andric if (!MI.mayStore()) 5826*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 5827*0b57cec5SDimitry Andric 5828*0b57cec5SDimitry Andric if (isMUBUF(MI) || isVGPRSpill(MI)) 5829*0b57cec5SDimitry Andric return isStackAccess(MI, FrameIndex); 5830*0b57cec5SDimitry Andric 5831*0b57cec5SDimitry Andric if (isSGPRSpill(MI)) 5832*0b57cec5SDimitry Andric return isSGPRStackAccess(MI, FrameIndex); 5833*0b57cec5SDimitry Andric 5834*0b57cec5SDimitry Andric return AMDGPU::NoRegister; 5835*0b57cec5SDimitry Andric } 5836*0b57cec5SDimitry Andric 5837*0b57cec5SDimitry Andric unsigned SIInstrInfo::getInstBundleSize(const MachineInstr &MI) const { 5838*0b57cec5SDimitry Andric unsigned Size = 0; 5839*0b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator I = MI.getIterator(); 5840*0b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator E = MI.getParent()->instr_end(); 5841*0b57cec5SDimitry Andric while (++I != E && I->isInsideBundle()) { 5842*0b57cec5SDimitry Andric assert(!I->isBundle() && "No nested bundle!"); 5843*0b57cec5SDimitry Andric Size += getInstSizeInBytes(*I); 5844*0b57cec5SDimitry Andric } 5845*0b57cec5SDimitry Andric 5846*0b57cec5SDimitry Andric return Size; 5847*0b57cec5SDimitry Andric } 5848*0b57cec5SDimitry Andric 5849*0b57cec5SDimitry Andric unsigned SIInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 5850*0b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 5851*0b57cec5SDimitry Andric const MCInstrDesc &Desc = getMCOpcodeFromPseudo(Opc); 5852*0b57cec5SDimitry Andric unsigned DescSize = Desc.getSize(); 5853*0b57cec5SDimitry Andric 5854*0b57cec5SDimitry Andric // If we have a definitive size, we can use it. Otherwise we need to inspect 5855*0b57cec5SDimitry Andric // the operands to know the size. 5856*0b57cec5SDimitry Andric if (isFixedSize(MI)) 5857*0b57cec5SDimitry Andric return DescSize; 5858*0b57cec5SDimitry Andric 5859*0b57cec5SDimitry Andric // 4-byte instructions may have a 32-bit literal encoded after them. Check 5860*0b57cec5SDimitry Andric // operands that coud ever be literals. 5861*0b57cec5SDimitry Andric if (isVALU(MI) || isSALU(MI)) { 5862*0b57cec5SDimitry Andric int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 5863*0b57cec5SDimitry Andric if (Src0Idx == -1) 5864*0b57cec5SDimitry Andric return DescSize; // No operands. 5865*0b57cec5SDimitry Andric 5866*0b57cec5SDimitry Andric if (isLiteralConstantLike(MI.getOperand(Src0Idx), Desc.OpInfo[Src0Idx])) 5867*0b57cec5SDimitry Andric return isVOP3(MI) ? 12 : (DescSize + 4); 5868*0b57cec5SDimitry Andric 5869*0b57cec5SDimitry Andric int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1); 5870*0b57cec5SDimitry Andric if (Src1Idx == -1) 5871*0b57cec5SDimitry Andric return DescSize; 5872*0b57cec5SDimitry Andric 5873*0b57cec5SDimitry Andric if (isLiteralConstantLike(MI.getOperand(Src1Idx), Desc.OpInfo[Src1Idx])) 5874*0b57cec5SDimitry Andric return isVOP3(MI) ? 12 : (DescSize + 4); 5875*0b57cec5SDimitry Andric 5876*0b57cec5SDimitry Andric int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2); 5877*0b57cec5SDimitry Andric if (Src2Idx == -1) 5878*0b57cec5SDimitry Andric return DescSize; 5879*0b57cec5SDimitry Andric 5880*0b57cec5SDimitry Andric if (isLiteralConstantLike(MI.getOperand(Src2Idx), Desc.OpInfo[Src2Idx])) 5881*0b57cec5SDimitry Andric return isVOP3(MI) ? 12 : (DescSize + 4); 5882*0b57cec5SDimitry Andric 5883*0b57cec5SDimitry Andric return DescSize; 5884*0b57cec5SDimitry Andric } 5885*0b57cec5SDimitry Andric 5886*0b57cec5SDimitry Andric // Check whether we have extra NSA words. 5887*0b57cec5SDimitry Andric if (isMIMG(MI)) { 5888*0b57cec5SDimitry Andric int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0); 5889*0b57cec5SDimitry Andric if (VAddr0Idx < 0) 5890*0b57cec5SDimitry Andric return 8; 5891*0b57cec5SDimitry Andric 5892*0b57cec5SDimitry Andric int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc); 5893*0b57cec5SDimitry Andric return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4); 5894*0b57cec5SDimitry Andric } 5895*0b57cec5SDimitry Andric 5896*0b57cec5SDimitry Andric switch (Opc) { 5897*0b57cec5SDimitry Andric case TargetOpcode::IMPLICIT_DEF: 5898*0b57cec5SDimitry Andric case TargetOpcode::KILL: 5899*0b57cec5SDimitry Andric case TargetOpcode::DBG_VALUE: 5900*0b57cec5SDimitry Andric case TargetOpcode::EH_LABEL: 5901*0b57cec5SDimitry Andric return 0; 5902*0b57cec5SDimitry Andric case TargetOpcode::BUNDLE: 5903*0b57cec5SDimitry Andric return getInstBundleSize(MI); 5904*0b57cec5SDimitry Andric case TargetOpcode::INLINEASM: 5905*0b57cec5SDimitry Andric case TargetOpcode::INLINEASM_BR: { 5906*0b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent(); 5907*0b57cec5SDimitry Andric const char *AsmStr = MI.getOperand(0).getSymbolName(); 5908*0b57cec5SDimitry Andric return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo(), 5909*0b57cec5SDimitry Andric &MF->getSubtarget()); 5910*0b57cec5SDimitry Andric } 5911*0b57cec5SDimitry Andric default: 5912*0b57cec5SDimitry Andric return DescSize; 5913*0b57cec5SDimitry Andric } 5914*0b57cec5SDimitry Andric } 5915*0b57cec5SDimitry Andric 5916*0b57cec5SDimitry Andric bool SIInstrInfo::mayAccessFlatAddressSpace(const MachineInstr &MI) const { 5917*0b57cec5SDimitry Andric if (!isFLAT(MI)) 5918*0b57cec5SDimitry Andric return false; 5919*0b57cec5SDimitry Andric 5920*0b57cec5SDimitry Andric if (MI.memoperands_empty()) 5921*0b57cec5SDimitry Andric return true; 5922*0b57cec5SDimitry Andric 5923*0b57cec5SDimitry Andric for (const MachineMemOperand *MMO : MI.memoperands()) { 5924*0b57cec5SDimitry Andric if (MMO->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS) 5925*0b57cec5SDimitry Andric return true; 5926*0b57cec5SDimitry Andric } 5927*0b57cec5SDimitry Andric return false; 5928*0b57cec5SDimitry Andric } 5929*0b57cec5SDimitry Andric 5930*0b57cec5SDimitry Andric bool SIInstrInfo::isNonUniformBranchInstr(MachineInstr &Branch) const { 5931*0b57cec5SDimitry Andric return Branch.getOpcode() == AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO; 5932*0b57cec5SDimitry Andric } 5933*0b57cec5SDimitry Andric 5934*0b57cec5SDimitry Andric void SIInstrInfo::convertNonUniformIfRegion(MachineBasicBlock *IfEntry, 5935*0b57cec5SDimitry Andric MachineBasicBlock *IfEnd) const { 5936*0b57cec5SDimitry Andric MachineBasicBlock::iterator TI = IfEntry->getFirstTerminator(); 5937*0b57cec5SDimitry Andric assert(TI != IfEntry->end()); 5938*0b57cec5SDimitry Andric 5939*0b57cec5SDimitry Andric MachineInstr *Branch = &(*TI); 5940*0b57cec5SDimitry Andric MachineFunction *MF = IfEntry->getParent(); 5941*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = IfEntry->getParent()->getRegInfo(); 5942*0b57cec5SDimitry Andric 5943*0b57cec5SDimitry Andric if (Branch->getOpcode() == AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO) { 5944*0b57cec5SDimitry Andric unsigned DstReg = MRI.createVirtualRegister(RI.getBoolRC()); 5945*0b57cec5SDimitry Andric MachineInstr *SIIF = 5946*0b57cec5SDimitry Andric BuildMI(*MF, Branch->getDebugLoc(), get(AMDGPU::SI_IF), DstReg) 5947*0b57cec5SDimitry Andric .add(Branch->getOperand(0)) 5948*0b57cec5SDimitry Andric .add(Branch->getOperand(1)); 5949*0b57cec5SDimitry Andric MachineInstr *SIEND = 5950*0b57cec5SDimitry Andric BuildMI(*MF, Branch->getDebugLoc(), get(AMDGPU::SI_END_CF)) 5951*0b57cec5SDimitry Andric .addReg(DstReg); 5952*0b57cec5SDimitry Andric 5953*0b57cec5SDimitry Andric IfEntry->erase(TI); 5954*0b57cec5SDimitry Andric IfEntry->insert(IfEntry->end(), SIIF); 5955*0b57cec5SDimitry Andric IfEnd->insert(IfEnd->getFirstNonPHI(), SIEND); 5956*0b57cec5SDimitry Andric } 5957*0b57cec5SDimitry Andric } 5958*0b57cec5SDimitry Andric 5959*0b57cec5SDimitry Andric void SIInstrInfo::convertNonUniformLoopRegion( 5960*0b57cec5SDimitry Andric MachineBasicBlock *LoopEntry, MachineBasicBlock *LoopEnd) const { 5961*0b57cec5SDimitry Andric MachineBasicBlock::iterator TI = LoopEnd->getFirstTerminator(); 5962*0b57cec5SDimitry Andric // We expect 2 terminators, one conditional and one unconditional. 5963*0b57cec5SDimitry Andric assert(TI != LoopEnd->end()); 5964*0b57cec5SDimitry Andric 5965*0b57cec5SDimitry Andric MachineInstr *Branch = &(*TI); 5966*0b57cec5SDimitry Andric MachineFunction *MF = LoopEnd->getParent(); 5967*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = LoopEnd->getParent()->getRegInfo(); 5968*0b57cec5SDimitry Andric 5969*0b57cec5SDimitry Andric if (Branch->getOpcode() == AMDGPU::SI_NON_UNIFORM_BRCOND_PSEUDO) { 5970*0b57cec5SDimitry Andric 5971*0b57cec5SDimitry Andric unsigned DstReg = MRI.createVirtualRegister(RI.getBoolRC()); 5972*0b57cec5SDimitry Andric unsigned BackEdgeReg = MRI.createVirtualRegister(RI.getBoolRC()); 5973*0b57cec5SDimitry Andric MachineInstrBuilder HeaderPHIBuilder = 5974*0b57cec5SDimitry Andric BuildMI(*(MF), Branch->getDebugLoc(), get(TargetOpcode::PHI), DstReg); 5975*0b57cec5SDimitry Andric for (MachineBasicBlock::pred_iterator PI = LoopEntry->pred_begin(), 5976*0b57cec5SDimitry Andric E = LoopEntry->pred_end(); 5977*0b57cec5SDimitry Andric PI != E; ++PI) { 5978*0b57cec5SDimitry Andric if (*PI == LoopEnd) { 5979*0b57cec5SDimitry Andric HeaderPHIBuilder.addReg(BackEdgeReg); 5980*0b57cec5SDimitry Andric } else { 5981*0b57cec5SDimitry Andric MachineBasicBlock *PMBB = *PI; 5982*0b57cec5SDimitry Andric unsigned ZeroReg = MRI.createVirtualRegister(RI.getBoolRC()); 5983*0b57cec5SDimitry Andric materializeImmediate(*PMBB, PMBB->getFirstTerminator(), DebugLoc(), 5984*0b57cec5SDimitry Andric ZeroReg, 0); 5985*0b57cec5SDimitry Andric HeaderPHIBuilder.addReg(ZeroReg); 5986*0b57cec5SDimitry Andric } 5987*0b57cec5SDimitry Andric HeaderPHIBuilder.addMBB(*PI); 5988*0b57cec5SDimitry Andric } 5989*0b57cec5SDimitry Andric MachineInstr *HeaderPhi = HeaderPHIBuilder; 5990*0b57cec5SDimitry Andric MachineInstr *SIIFBREAK = BuildMI(*(MF), Branch->getDebugLoc(), 5991*0b57cec5SDimitry Andric get(AMDGPU::SI_IF_BREAK), BackEdgeReg) 5992*0b57cec5SDimitry Andric .addReg(DstReg) 5993*0b57cec5SDimitry Andric .add(Branch->getOperand(0)); 5994*0b57cec5SDimitry Andric MachineInstr *SILOOP = 5995*0b57cec5SDimitry Andric BuildMI(*(MF), Branch->getDebugLoc(), get(AMDGPU::SI_LOOP)) 5996*0b57cec5SDimitry Andric .addReg(BackEdgeReg) 5997*0b57cec5SDimitry Andric .addMBB(LoopEntry); 5998*0b57cec5SDimitry Andric 5999*0b57cec5SDimitry Andric LoopEntry->insert(LoopEntry->begin(), HeaderPhi); 6000*0b57cec5SDimitry Andric LoopEnd->erase(TI); 6001*0b57cec5SDimitry Andric LoopEnd->insert(LoopEnd->end(), SIIFBREAK); 6002*0b57cec5SDimitry Andric LoopEnd->insert(LoopEnd->end(), SILOOP); 6003*0b57cec5SDimitry Andric } 6004*0b57cec5SDimitry Andric } 6005*0b57cec5SDimitry Andric 6006*0b57cec5SDimitry Andric ArrayRef<std::pair<int, const char *>> 6007*0b57cec5SDimitry Andric SIInstrInfo::getSerializableTargetIndices() const { 6008*0b57cec5SDimitry Andric static const std::pair<int, const char *> TargetIndices[] = { 6009*0b57cec5SDimitry Andric {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"}, 6010*0b57cec5SDimitry Andric {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"}, 6011*0b57cec5SDimitry Andric {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"}, 6012*0b57cec5SDimitry Andric {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"}, 6013*0b57cec5SDimitry Andric {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}}; 6014*0b57cec5SDimitry Andric return makeArrayRef(TargetIndices); 6015*0b57cec5SDimitry Andric } 6016*0b57cec5SDimitry Andric 6017*0b57cec5SDimitry Andric /// This is used by the post-RA scheduler (SchedulePostRAList.cpp). The 6018*0b57cec5SDimitry Andric /// post-RA version of misched uses CreateTargetMIHazardRecognizer. 6019*0b57cec5SDimitry Andric ScheduleHazardRecognizer * 6020*0b57cec5SDimitry Andric SIInstrInfo::CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, 6021*0b57cec5SDimitry Andric const ScheduleDAG *DAG) const { 6022*0b57cec5SDimitry Andric return new GCNHazardRecognizer(DAG->MF); 6023*0b57cec5SDimitry Andric } 6024*0b57cec5SDimitry Andric 6025*0b57cec5SDimitry Andric /// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer 6026*0b57cec5SDimitry Andric /// pass. 6027*0b57cec5SDimitry Andric ScheduleHazardRecognizer * 6028*0b57cec5SDimitry Andric SIInstrInfo::CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const { 6029*0b57cec5SDimitry Andric return new GCNHazardRecognizer(MF); 6030*0b57cec5SDimitry Andric } 6031*0b57cec5SDimitry Andric 6032*0b57cec5SDimitry Andric std::pair<unsigned, unsigned> 6033*0b57cec5SDimitry Andric SIInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 6034*0b57cec5SDimitry Andric return std::make_pair(TF & MO_MASK, TF & ~MO_MASK); 6035*0b57cec5SDimitry Andric } 6036*0b57cec5SDimitry Andric 6037*0b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 6038*0b57cec5SDimitry Andric SIInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 6039*0b57cec5SDimitry Andric static const std::pair<unsigned, const char *> TargetFlags[] = { 6040*0b57cec5SDimitry Andric { MO_GOTPCREL, "amdgpu-gotprel" }, 6041*0b57cec5SDimitry Andric { MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo" }, 6042*0b57cec5SDimitry Andric { MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi" }, 6043*0b57cec5SDimitry Andric { MO_REL32_LO, "amdgpu-rel32-lo" }, 6044*0b57cec5SDimitry Andric { MO_REL32_HI, "amdgpu-rel32-hi" }, 6045*0b57cec5SDimitry Andric { MO_ABS32_LO, "amdgpu-abs32-lo" }, 6046*0b57cec5SDimitry Andric { MO_ABS32_HI, "amdgpu-abs32-hi" }, 6047*0b57cec5SDimitry Andric }; 6048*0b57cec5SDimitry Andric 6049*0b57cec5SDimitry Andric return makeArrayRef(TargetFlags); 6050*0b57cec5SDimitry Andric } 6051*0b57cec5SDimitry Andric 6052*0b57cec5SDimitry Andric bool SIInstrInfo::isBasicBlockPrologue(const MachineInstr &MI) const { 6053*0b57cec5SDimitry Andric return !MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY && 6054*0b57cec5SDimitry Andric MI.modifiesRegister(AMDGPU::EXEC, &RI); 6055*0b57cec5SDimitry Andric } 6056*0b57cec5SDimitry Andric 6057*0b57cec5SDimitry Andric MachineInstrBuilder 6058*0b57cec5SDimitry Andric SIInstrInfo::getAddNoCarry(MachineBasicBlock &MBB, 6059*0b57cec5SDimitry Andric MachineBasicBlock::iterator I, 6060*0b57cec5SDimitry Andric const DebugLoc &DL, 6061*0b57cec5SDimitry Andric unsigned DestReg) const { 6062*0b57cec5SDimitry Andric if (ST.hasAddNoCarry()) 6063*0b57cec5SDimitry Andric return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg); 6064*0b57cec5SDimitry Andric 6065*0b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 6066*0b57cec5SDimitry Andric unsigned UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC()); 6067*0b57cec5SDimitry Andric MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC()); 6068*0b57cec5SDimitry Andric 6069*0b57cec5SDimitry Andric return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_I32_e64), DestReg) 6070*0b57cec5SDimitry Andric .addReg(UnusedCarry, RegState::Define | RegState::Dead); 6071*0b57cec5SDimitry Andric } 6072*0b57cec5SDimitry Andric 6073*0b57cec5SDimitry Andric bool SIInstrInfo::isKillTerminator(unsigned Opcode) { 6074*0b57cec5SDimitry Andric switch (Opcode) { 6075*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR: 6076*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_I1_TERMINATOR: 6077*0b57cec5SDimitry Andric return true; 6078*0b57cec5SDimitry Andric default: 6079*0b57cec5SDimitry Andric return false; 6080*0b57cec5SDimitry Andric } 6081*0b57cec5SDimitry Andric } 6082*0b57cec5SDimitry Andric 6083*0b57cec5SDimitry Andric const MCInstrDesc &SIInstrInfo::getKillTerminatorFromPseudo(unsigned Opcode) const { 6084*0b57cec5SDimitry Andric switch (Opcode) { 6085*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO: 6086*0b57cec5SDimitry Andric return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR); 6087*0b57cec5SDimitry Andric case AMDGPU::SI_KILL_I1_PSEUDO: 6088*0b57cec5SDimitry Andric return get(AMDGPU::SI_KILL_I1_TERMINATOR); 6089*0b57cec5SDimitry Andric default: 6090*0b57cec5SDimitry Andric llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO"); 6091*0b57cec5SDimitry Andric } 6092*0b57cec5SDimitry Andric } 6093*0b57cec5SDimitry Andric 6094*0b57cec5SDimitry Andric void SIInstrInfo::fixImplicitOperands(MachineInstr &MI) const { 6095*0b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getParent(); 6096*0b57cec5SDimitry Andric MachineFunction *MF = MBB->getParent(); 6097*0b57cec5SDimitry Andric const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>(); 6098*0b57cec5SDimitry Andric 6099*0b57cec5SDimitry Andric if (!ST.isWave32()) 6100*0b57cec5SDimitry Andric return; 6101*0b57cec5SDimitry Andric 6102*0b57cec5SDimitry Andric for (auto &Op : MI.implicit_operands()) { 6103*0b57cec5SDimitry Andric if (Op.isReg() && Op.getReg() == AMDGPU::VCC) 6104*0b57cec5SDimitry Andric Op.setReg(AMDGPU::VCC_LO); 6105*0b57cec5SDimitry Andric } 6106*0b57cec5SDimitry Andric } 6107*0b57cec5SDimitry Andric 6108*0b57cec5SDimitry Andric bool SIInstrInfo::isBufferSMRD(const MachineInstr &MI) const { 6109*0b57cec5SDimitry Andric if (!isSMRD(MI)) 6110*0b57cec5SDimitry Andric return false; 6111*0b57cec5SDimitry Andric 6112*0b57cec5SDimitry Andric // Check that it is using a buffer resource. 6113*0b57cec5SDimitry Andric int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase); 6114*0b57cec5SDimitry Andric if (Idx == -1) // e.g. s_memtime 6115*0b57cec5SDimitry Andric return false; 6116*0b57cec5SDimitry Andric 6117*0b57cec5SDimitry Andric const auto RCID = MI.getDesc().OpInfo[Idx].RegClass; 6118*0b57cec5SDimitry Andric return RCID == AMDGPU::SReg_128RegClassID; 6119*0b57cec5SDimitry Andric } 6120*0b57cec5SDimitry Andric 6121*0b57cec5SDimitry Andric bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, 6122*0b57cec5SDimitry Andric bool Signed) const { 6123*0b57cec5SDimitry Andric // TODO: Should 0 be special cased? 6124*0b57cec5SDimitry Andric if (!ST.hasFlatInstOffsets()) 6125*0b57cec5SDimitry Andric return false; 6126*0b57cec5SDimitry Andric 6127*0b57cec5SDimitry Andric if (ST.hasFlatSegmentOffsetBug() && AddrSpace == AMDGPUAS::FLAT_ADDRESS) 6128*0b57cec5SDimitry Andric return false; 6129*0b57cec5SDimitry Andric 6130*0b57cec5SDimitry Andric if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) { 6131*0b57cec5SDimitry Andric return (Signed && isInt<12>(Offset)) || 6132*0b57cec5SDimitry Andric (!Signed && isUInt<11>(Offset)); 6133*0b57cec5SDimitry Andric } 6134*0b57cec5SDimitry Andric 6135*0b57cec5SDimitry Andric return (Signed && isInt<13>(Offset)) || 6136*0b57cec5SDimitry Andric (!Signed && isUInt<12>(Offset)); 6137*0b57cec5SDimitry Andric } 6138*0b57cec5SDimitry Andric 6139*0b57cec5SDimitry Andric 6140*0b57cec5SDimitry Andric // This must be kept in sync with the SIEncodingFamily class in SIInstrInfo.td 6141*0b57cec5SDimitry Andric enum SIEncodingFamily { 6142*0b57cec5SDimitry Andric SI = 0, 6143*0b57cec5SDimitry Andric VI = 1, 6144*0b57cec5SDimitry Andric SDWA = 2, 6145*0b57cec5SDimitry Andric SDWA9 = 3, 6146*0b57cec5SDimitry Andric GFX80 = 4, 6147*0b57cec5SDimitry Andric GFX9 = 5, 6148*0b57cec5SDimitry Andric GFX10 = 6, 6149*0b57cec5SDimitry Andric SDWA10 = 7 6150*0b57cec5SDimitry Andric }; 6151*0b57cec5SDimitry Andric 6152*0b57cec5SDimitry Andric static SIEncodingFamily subtargetEncodingFamily(const GCNSubtarget &ST) { 6153*0b57cec5SDimitry Andric switch (ST.getGeneration()) { 6154*0b57cec5SDimitry Andric default: 6155*0b57cec5SDimitry Andric break; 6156*0b57cec5SDimitry Andric case AMDGPUSubtarget::SOUTHERN_ISLANDS: 6157*0b57cec5SDimitry Andric case AMDGPUSubtarget::SEA_ISLANDS: 6158*0b57cec5SDimitry Andric return SIEncodingFamily::SI; 6159*0b57cec5SDimitry Andric case AMDGPUSubtarget::VOLCANIC_ISLANDS: 6160*0b57cec5SDimitry Andric case AMDGPUSubtarget::GFX9: 6161*0b57cec5SDimitry Andric return SIEncodingFamily::VI; 6162*0b57cec5SDimitry Andric case AMDGPUSubtarget::GFX10: 6163*0b57cec5SDimitry Andric return SIEncodingFamily::GFX10; 6164*0b57cec5SDimitry Andric } 6165*0b57cec5SDimitry Andric llvm_unreachable("Unknown subtarget generation!"); 6166*0b57cec5SDimitry Andric } 6167*0b57cec5SDimitry Andric 6168*0b57cec5SDimitry Andric int SIInstrInfo::pseudoToMCOpcode(int Opcode) const { 6169*0b57cec5SDimitry Andric SIEncodingFamily Gen = subtargetEncodingFamily(ST); 6170*0b57cec5SDimitry Andric 6171*0b57cec5SDimitry Andric if ((get(Opcode).TSFlags & SIInstrFlags::renamedInGFX9) != 0 && 6172*0b57cec5SDimitry Andric ST.getGeneration() == AMDGPUSubtarget::GFX9) 6173*0b57cec5SDimitry Andric Gen = SIEncodingFamily::GFX9; 6174*0b57cec5SDimitry Andric 6175*0b57cec5SDimitry Andric // Adjust the encoding family to GFX80 for D16 buffer instructions when the 6176*0b57cec5SDimitry Andric // subtarget has UnpackedD16VMem feature. 6177*0b57cec5SDimitry Andric // TODO: remove this when we discard GFX80 encoding. 6178*0b57cec5SDimitry Andric if (ST.hasUnpackedD16VMem() && (get(Opcode).TSFlags & SIInstrFlags::D16Buf)) 6179*0b57cec5SDimitry Andric Gen = SIEncodingFamily::GFX80; 6180*0b57cec5SDimitry Andric 6181*0b57cec5SDimitry Andric if (get(Opcode).TSFlags & SIInstrFlags::SDWA) { 6182*0b57cec5SDimitry Andric switch (ST.getGeneration()) { 6183*0b57cec5SDimitry Andric default: 6184*0b57cec5SDimitry Andric Gen = SIEncodingFamily::SDWA; 6185*0b57cec5SDimitry Andric break; 6186*0b57cec5SDimitry Andric case AMDGPUSubtarget::GFX9: 6187*0b57cec5SDimitry Andric Gen = SIEncodingFamily::SDWA9; 6188*0b57cec5SDimitry Andric break; 6189*0b57cec5SDimitry Andric case AMDGPUSubtarget::GFX10: 6190*0b57cec5SDimitry Andric Gen = SIEncodingFamily::SDWA10; 6191*0b57cec5SDimitry Andric break; 6192*0b57cec5SDimitry Andric } 6193*0b57cec5SDimitry Andric } 6194*0b57cec5SDimitry Andric 6195*0b57cec5SDimitry Andric int MCOp = AMDGPU::getMCOpcode(Opcode, Gen); 6196*0b57cec5SDimitry Andric 6197*0b57cec5SDimitry Andric // -1 means that Opcode is already a native instruction. 6198*0b57cec5SDimitry Andric if (MCOp == -1) 6199*0b57cec5SDimitry Andric return Opcode; 6200*0b57cec5SDimitry Andric 6201*0b57cec5SDimitry Andric // (uint16_t)-1 means that Opcode is a pseudo instruction that has 6202*0b57cec5SDimitry Andric // no encoding in the given subtarget generation. 6203*0b57cec5SDimitry Andric if (MCOp == (uint16_t)-1) 6204*0b57cec5SDimitry Andric return -1; 6205*0b57cec5SDimitry Andric 6206*0b57cec5SDimitry Andric return MCOp; 6207*0b57cec5SDimitry Andric } 6208*0b57cec5SDimitry Andric 6209*0b57cec5SDimitry Andric static 6210*0b57cec5SDimitry Andric TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd) { 6211*0b57cec5SDimitry Andric assert(RegOpnd.isReg()); 6212*0b57cec5SDimitry Andric return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() : 6213*0b57cec5SDimitry Andric getRegSubRegPair(RegOpnd); 6214*0b57cec5SDimitry Andric } 6215*0b57cec5SDimitry Andric 6216*0b57cec5SDimitry Andric TargetInstrInfo::RegSubRegPair 6217*0b57cec5SDimitry Andric llvm::getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg) { 6218*0b57cec5SDimitry Andric assert(MI.isRegSequence()); 6219*0b57cec5SDimitry Andric for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I) 6220*0b57cec5SDimitry Andric if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) { 6221*0b57cec5SDimitry Andric auto &RegOp = MI.getOperand(1 + 2 * I); 6222*0b57cec5SDimitry Andric return getRegOrUndef(RegOp); 6223*0b57cec5SDimitry Andric } 6224*0b57cec5SDimitry Andric return TargetInstrInfo::RegSubRegPair(); 6225*0b57cec5SDimitry Andric } 6226*0b57cec5SDimitry Andric 6227*0b57cec5SDimitry Andric // Try to find the definition of reg:subreg in subreg-manipulation pseudos 6228*0b57cec5SDimitry Andric // Following a subreg of reg:subreg isn't supported 6229*0b57cec5SDimitry Andric static bool followSubRegDef(MachineInstr &MI, 6230*0b57cec5SDimitry Andric TargetInstrInfo::RegSubRegPair &RSR) { 6231*0b57cec5SDimitry Andric if (!RSR.SubReg) 6232*0b57cec5SDimitry Andric return false; 6233*0b57cec5SDimitry Andric switch (MI.getOpcode()) { 6234*0b57cec5SDimitry Andric default: break; 6235*0b57cec5SDimitry Andric case AMDGPU::REG_SEQUENCE: 6236*0b57cec5SDimitry Andric RSR = getRegSequenceSubReg(MI, RSR.SubReg); 6237*0b57cec5SDimitry Andric return true; 6238*0b57cec5SDimitry Andric // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg 6239*0b57cec5SDimitry Andric case AMDGPU::INSERT_SUBREG: 6240*0b57cec5SDimitry Andric if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm()) 6241*0b57cec5SDimitry Andric // inserted the subreg we're looking for 6242*0b57cec5SDimitry Andric RSR = getRegOrUndef(MI.getOperand(2)); 6243*0b57cec5SDimitry Andric else { // the subreg in the rest of the reg 6244*0b57cec5SDimitry Andric auto R1 = getRegOrUndef(MI.getOperand(1)); 6245*0b57cec5SDimitry Andric if (R1.SubReg) // subreg of subreg isn't supported 6246*0b57cec5SDimitry Andric return false; 6247*0b57cec5SDimitry Andric RSR.Reg = R1.Reg; 6248*0b57cec5SDimitry Andric } 6249*0b57cec5SDimitry Andric return true; 6250*0b57cec5SDimitry Andric } 6251*0b57cec5SDimitry Andric return false; 6252*0b57cec5SDimitry Andric } 6253*0b57cec5SDimitry Andric 6254*0b57cec5SDimitry Andric MachineInstr *llvm::getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, 6255*0b57cec5SDimitry Andric MachineRegisterInfo &MRI) { 6256*0b57cec5SDimitry Andric assert(MRI.isSSA()); 6257*0b57cec5SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(P.Reg)) 6258*0b57cec5SDimitry Andric return nullptr; 6259*0b57cec5SDimitry Andric 6260*0b57cec5SDimitry Andric auto RSR = P; 6261*0b57cec5SDimitry Andric auto *DefInst = MRI.getVRegDef(RSR.Reg); 6262*0b57cec5SDimitry Andric while (auto *MI = DefInst) { 6263*0b57cec5SDimitry Andric DefInst = nullptr; 6264*0b57cec5SDimitry Andric switch (MI->getOpcode()) { 6265*0b57cec5SDimitry Andric case AMDGPU::COPY: 6266*0b57cec5SDimitry Andric case AMDGPU::V_MOV_B32_e32: { 6267*0b57cec5SDimitry Andric auto &Op1 = MI->getOperand(1); 6268*0b57cec5SDimitry Andric if (Op1.isReg() && 6269*0b57cec5SDimitry Andric TargetRegisterInfo::isVirtualRegister(Op1.getReg())) { 6270*0b57cec5SDimitry Andric if (Op1.isUndef()) 6271*0b57cec5SDimitry Andric return nullptr; 6272*0b57cec5SDimitry Andric RSR = getRegSubRegPair(Op1); 6273*0b57cec5SDimitry Andric DefInst = MRI.getVRegDef(RSR.Reg); 6274*0b57cec5SDimitry Andric } 6275*0b57cec5SDimitry Andric break; 6276*0b57cec5SDimitry Andric } 6277*0b57cec5SDimitry Andric default: 6278*0b57cec5SDimitry Andric if (followSubRegDef(*MI, RSR)) { 6279*0b57cec5SDimitry Andric if (!RSR.Reg) 6280*0b57cec5SDimitry Andric return nullptr; 6281*0b57cec5SDimitry Andric DefInst = MRI.getVRegDef(RSR.Reg); 6282*0b57cec5SDimitry Andric } 6283*0b57cec5SDimitry Andric } 6284*0b57cec5SDimitry Andric if (!DefInst) 6285*0b57cec5SDimitry Andric return MI; 6286*0b57cec5SDimitry Andric } 6287*0b57cec5SDimitry Andric return nullptr; 6288*0b57cec5SDimitry Andric } 6289*0b57cec5SDimitry Andric 6290*0b57cec5SDimitry Andric bool llvm::execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, 6291*0b57cec5SDimitry Andric Register VReg, 6292*0b57cec5SDimitry Andric const MachineInstr &DefMI, 6293*0b57cec5SDimitry Andric const MachineInstr &UseMI) { 6294*0b57cec5SDimitry Andric assert(MRI.isSSA() && "Must be run on SSA"); 6295*0b57cec5SDimitry Andric 6296*0b57cec5SDimitry Andric auto *TRI = MRI.getTargetRegisterInfo(); 6297*0b57cec5SDimitry Andric auto *DefBB = DefMI.getParent(); 6298*0b57cec5SDimitry Andric 6299*0b57cec5SDimitry Andric // Don't bother searching between blocks, although it is possible this block 6300*0b57cec5SDimitry Andric // doesn't modify exec. 6301*0b57cec5SDimitry Andric if (UseMI.getParent() != DefBB) 6302*0b57cec5SDimitry Andric return true; 6303*0b57cec5SDimitry Andric 6304*0b57cec5SDimitry Andric const int MaxInstScan = 20; 6305*0b57cec5SDimitry Andric int NumInst = 0; 6306*0b57cec5SDimitry Andric 6307*0b57cec5SDimitry Andric // Stop scan at the use. 6308*0b57cec5SDimitry Andric auto E = UseMI.getIterator(); 6309*0b57cec5SDimitry Andric for (auto I = std::next(DefMI.getIterator()); I != E; ++I) { 6310*0b57cec5SDimitry Andric if (I->isDebugInstr()) 6311*0b57cec5SDimitry Andric continue; 6312*0b57cec5SDimitry Andric 6313*0b57cec5SDimitry Andric if (++NumInst > MaxInstScan) 6314*0b57cec5SDimitry Andric return true; 6315*0b57cec5SDimitry Andric 6316*0b57cec5SDimitry Andric if (I->modifiesRegister(AMDGPU::EXEC, TRI)) 6317*0b57cec5SDimitry Andric return true; 6318*0b57cec5SDimitry Andric } 6319*0b57cec5SDimitry Andric 6320*0b57cec5SDimitry Andric return false; 6321*0b57cec5SDimitry Andric } 6322*0b57cec5SDimitry Andric 6323*0b57cec5SDimitry Andric bool llvm::execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, 6324*0b57cec5SDimitry Andric Register VReg, 6325*0b57cec5SDimitry Andric const MachineInstr &DefMI) { 6326*0b57cec5SDimitry Andric assert(MRI.isSSA() && "Must be run on SSA"); 6327*0b57cec5SDimitry Andric 6328*0b57cec5SDimitry Andric auto *TRI = MRI.getTargetRegisterInfo(); 6329*0b57cec5SDimitry Andric auto *DefBB = DefMI.getParent(); 6330*0b57cec5SDimitry Andric 6331*0b57cec5SDimitry Andric const int MaxUseInstScan = 10; 6332*0b57cec5SDimitry Andric int NumUseInst = 0; 6333*0b57cec5SDimitry Andric 6334*0b57cec5SDimitry Andric for (auto &UseInst : MRI.use_nodbg_instructions(VReg)) { 6335*0b57cec5SDimitry Andric // Don't bother searching between blocks, although it is possible this block 6336*0b57cec5SDimitry Andric // doesn't modify exec. 6337*0b57cec5SDimitry Andric if (UseInst.getParent() != DefBB) 6338*0b57cec5SDimitry Andric return true; 6339*0b57cec5SDimitry Andric 6340*0b57cec5SDimitry Andric if (++NumUseInst > MaxUseInstScan) 6341*0b57cec5SDimitry Andric return true; 6342*0b57cec5SDimitry Andric } 6343*0b57cec5SDimitry Andric 6344*0b57cec5SDimitry Andric const int MaxInstScan = 20; 6345*0b57cec5SDimitry Andric int NumInst = 0; 6346*0b57cec5SDimitry Andric 6347*0b57cec5SDimitry Andric // Stop scan when we have seen all the uses. 6348*0b57cec5SDimitry Andric for (auto I = std::next(DefMI.getIterator()); ; ++I) { 6349*0b57cec5SDimitry Andric if (I->isDebugInstr()) 6350*0b57cec5SDimitry Andric continue; 6351*0b57cec5SDimitry Andric 6352*0b57cec5SDimitry Andric if (++NumInst > MaxInstScan) 6353*0b57cec5SDimitry Andric return true; 6354*0b57cec5SDimitry Andric 6355*0b57cec5SDimitry Andric if (I->readsRegister(VReg)) 6356*0b57cec5SDimitry Andric if (--NumUseInst == 0) 6357*0b57cec5SDimitry Andric return false; 6358*0b57cec5SDimitry Andric 6359*0b57cec5SDimitry Andric if (I->modifiesRegister(AMDGPU::EXEC, TRI)) 6360*0b57cec5SDimitry Andric return true; 6361*0b57cec5SDimitry Andric } 6362*0b57cec5SDimitry Andric } 6363