1*0fca6ea1SDimitry Andric //===- AMDGPUMCExpr.cpp - AMDGPU specific MC expression classes -----------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "AMDGPUMCExpr.h" 10*0fca6ea1SDimitry Andric #include "GCNSubtarget.h" 11*0fca6ea1SDimitry Andric #include "Utils/AMDGPUBaseInfo.h" 12*0fca6ea1SDimitry Andric #include "llvm/IR/Function.h" 13*0fca6ea1SDimitry Andric #include "llvm/MC/MCAssembler.h" 14*0fca6ea1SDimitry Andric #include "llvm/MC/MCContext.h" 15*0fca6ea1SDimitry Andric #include "llvm/MC/MCStreamer.h" 16*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbol.h" 17*0fca6ea1SDimitry Andric #include "llvm/MC/MCValue.h" 18*0fca6ea1SDimitry Andric #include "llvm/Support/Allocator.h" 19*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 20*0fca6ea1SDimitry Andric #include <optional> 21*0fca6ea1SDimitry Andric 22*0fca6ea1SDimitry Andric using namespace llvm; 23*0fca6ea1SDimitry Andric using namespace llvm::AMDGPU; 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric AMDGPUMCExpr::AMDGPUMCExpr(VariantKind Kind, ArrayRef<const MCExpr *> Args, 26*0fca6ea1SDimitry Andric MCContext &Ctx) 27*0fca6ea1SDimitry Andric : Kind(Kind), Ctx(Ctx) { 28*0fca6ea1SDimitry Andric assert(Args.size() >= 1 && "Needs a minimum of one expression."); 29*0fca6ea1SDimitry Andric assert(Kind != AGVK_None && "Cannot construct AMDGPUMCExpr of kind none."); 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric // Allocating the variadic arguments through the same allocation mechanism 32*0fca6ea1SDimitry Andric // that the object itself is allocated with so they end up in the same memory. 33*0fca6ea1SDimitry Andric // 34*0fca6ea1SDimitry Andric // Will result in an asan failure if allocated on the heap through standard 35*0fca6ea1SDimitry Andric // allocation (e.g., through SmallVector's grow). 36*0fca6ea1SDimitry Andric RawArgs = static_cast<const MCExpr **>( 37*0fca6ea1SDimitry Andric Ctx.allocate(sizeof(const MCExpr *) * Args.size())); 38*0fca6ea1SDimitry Andric std::uninitialized_copy(Args.begin(), Args.end(), RawArgs); 39*0fca6ea1SDimitry Andric this->Args = ArrayRef<const MCExpr *>(RawArgs, Args.size()); 40*0fca6ea1SDimitry Andric } 41*0fca6ea1SDimitry Andric 42*0fca6ea1SDimitry Andric AMDGPUMCExpr::~AMDGPUMCExpr() { Ctx.deallocate(RawArgs); } 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric const AMDGPUMCExpr *AMDGPUMCExpr::create(VariantKind Kind, 45*0fca6ea1SDimitry Andric ArrayRef<const MCExpr *> Args, 46*0fca6ea1SDimitry Andric MCContext &Ctx) { 47*0fca6ea1SDimitry Andric return new (Ctx) AMDGPUMCExpr(Kind, Args, Ctx); 48*0fca6ea1SDimitry Andric } 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric const MCExpr *AMDGPUMCExpr::getSubExpr(size_t Index) const { 51*0fca6ea1SDimitry Andric assert(Index < Args.size() && "Indexing out of bounds AMDGPUMCExpr sub-expr"); 52*0fca6ea1SDimitry Andric return Args[Index]; 53*0fca6ea1SDimitry Andric } 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric void AMDGPUMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 56*0fca6ea1SDimitry Andric switch (Kind) { 57*0fca6ea1SDimitry Andric default: 58*0fca6ea1SDimitry Andric llvm_unreachable("Unknown AMDGPUMCExpr kind."); 59*0fca6ea1SDimitry Andric case AGVK_Or: 60*0fca6ea1SDimitry Andric OS << "or("; 61*0fca6ea1SDimitry Andric break; 62*0fca6ea1SDimitry Andric case AGVK_Max: 63*0fca6ea1SDimitry Andric OS << "max("; 64*0fca6ea1SDimitry Andric break; 65*0fca6ea1SDimitry Andric case AGVK_ExtraSGPRs: 66*0fca6ea1SDimitry Andric OS << "extrasgprs("; 67*0fca6ea1SDimitry Andric break; 68*0fca6ea1SDimitry Andric case AGVK_TotalNumVGPRs: 69*0fca6ea1SDimitry Andric OS << "totalnumvgprs("; 70*0fca6ea1SDimitry Andric break; 71*0fca6ea1SDimitry Andric case AGVK_AlignTo: 72*0fca6ea1SDimitry Andric OS << "alignto("; 73*0fca6ea1SDimitry Andric break; 74*0fca6ea1SDimitry Andric case AGVK_Occupancy: 75*0fca6ea1SDimitry Andric OS << "occupancy("; 76*0fca6ea1SDimitry Andric break; 77*0fca6ea1SDimitry Andric } 78*0fca6ea1SDimitry Andric for (auto It = Args.begin(); It != Args.end(); ++It) { 79*0fca6ea1SDimitry Andric (*It)->print(OS, MAI, /*InParens=*/false); 80*0fca6ea1SDimitry Andric if ((It + 1) != Args.end()) 81*0fca6ea1SDimitry Andric OS << ", "; 82*0fca6ea1SDimitry Andric } 83*0fca6ea1SDimitry Andric OS << ')'; 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric 86*0fca6ea1SDimitry Andric static int64_t op(AMDGPUMCExpr::VariantKind Kind, int64_t Arg1, int64_t Arg2) { 87*0fca6ea1SDimitry Andric switch (Kind) { 88*0fca6ea1SDimitry Andric default: 89*0fca6ea1SDimitry Andric llvm_unreachable("Unknown AMDGPUMCExpr kind."); 90*0fca6ea1SDimitry Andric case AMDGPUMCExpr::AGVK_Max: 91*0fca6ea1SDimitry Andric return std::max(Arg1, Arg2); 92*0fca6ea1SDimitry Andric case AMDGPUMCExpr::AGVK_Or: 93*0fca6ea1SDimitry Andric return Arg1 | Arg2; 94*0fca6ea1SDimitry Andric } 95*0fca6ea1SDimitry Andric } 96*0fca6ea1SDimitry Andric 97*0fca6ea1SDimitry Andric bool AMDGPUMCExpr::evaluateExtraSGPRs(MCValue &Res, const MCAssembler *Asm, 98*0fca6ea1SDimitry Andric const MCFixup *Fixup) const { 99*0fca6ea1SDimitry Andric auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) { 100*0fca6ea1SDimitry Andric MCValue MCVal; 101*0fca6ea1SDimitry Andric if (!Arg->evaluateAsRelocatable(MCVal, Asm, Fixup) || !MCVal.isAbsolute()) 102*0fca6ea1SDimitry Andric return false; 103*0fca6ea1SDimitry Andric 104*0fca6ea1SDimitry Andric ConstantValue = MCVal.getConstant(); 105*0fca6ea1SDimitry Andric return true; 106*0fca6ea1SDimitry Andric }; 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric assert(Args.size() == 3 && 109*0fca6ea1SDimitry Andric "AMDGPUMCExpr Argument count incorrect for ExtraSGPRs"); 110*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI = Ctx.getSubtargetInfo(); 111*0fca6ea1SDimitry Andric uint64_t VCCUsed = 0, FlatScrUsed = 0, XNACKUsed = 0; 112*0fca6ea1SDimitry Andric 113*0fca6ea1SDimitry Andric bool Success = TryGetMCExprValue(Args[2], XNACKUsed); 114*0fca6ea1SDimitry Andric 115*0fca6ea1SDimitry Andric assert(Success && "Arguments 3 for ExtraSGPRs should be a known constant"); 116*0fca6ea1SDimitry Andric if (!Success || !TryGetMCExprValue(Args[0], VCCUsed) || 117*0fca6ea1SDimitry Andric !TryGetMCExprValue(Args[1], FlatScrUsed)) 118*0fca6ea1SDimitry Andric return false; 119*0fca6ea1SDimitry Andric 120*0fca6ea1SDimitry Andric uint64_t ExtraSGPRs = IsaInfo::getNumExtraSGPRs( 121*0fca6ea1SDimitry Andric STI, (bool)VCCUsed, (bool)FlatScrUsed, (bool)XNACKUsed); 122*0fca6ea1SDimitry Andric Res = MCValue::get(ExtraSGPRs); 123*0fca6ea1SDimitry Andric return true; 124*0fca6ea1SDimitry Andric } 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric bool AMDGPUMCExpr::evaluateTotalNumVGPR(MCValue &Res, const MCAssembler *Asm, 127*0fca6ea1SDimitry Andric const MCFixup *Fixup) const { 128*0fca6ea1SDimitry Andric auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) { 129*0fca6ea1SDimitry Andric MCValue MCVal; 130*0fca6ea1SDimitry Andric if (!Arg->evaluateAsRelocatable(MCVal, Asm, Fixup) || !MCVal.isAbsolute()) 131*0fca6ea1SDimitry Andric return false; 132*0fca6ea1SDimitry Andric 133*0fca6ea1SDimitry Andric ConstantValue = MCVal.getConstant(); 134*0fca6ea1SDimitry Andric return true; 135*0fca6ea1SDimitry Andric }; 136*0fca6ea1SDimitry Andric assert(Args.size() == 2 && 137*0fca6ea1SDimitry Andric "AMDGPUMCExpr Argument count incorrect for TotalNumVGPRs"); 138*0fca6ea1SDimitry Andric const MCSubtargetInfo *STI = Ctx.getSubtargetInfo(); 139*0fca6ea1SDimitry Andric uint64_t NumAGPR = 0, NumVGPR = 0; 140*0fca6ea1SDimitry Andric 141*0fca6ea1SDimitry Andric bool Has90AInsts = AMDGPU::isGFX90A(*STI); 142*0fca6ea1SDimitry Andric 143*0fca6ea1SDimitry Andric if (!TryGetMCExprValue(Args[0], NumAGPR) || 144*0fca6ea1SDimitry Andric !TryGetMCExprValue(Args[1], NumVGPR)) 145*0fca6ea1SDimitry Andric return false; 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric uint64_t TotalNum = Has90AInsts && NumAGPR ? alignTo(NumVGPR, 4) + NumAGPR 148*0fca6ea1SDimitry Andric : std::max(NumVGPR, NumAGPR); 149*0fca6ea1SDimitry Andric Res = MCValue::get(TotalNum); 150*0fca6ea1SDimitry Andric return true; 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric bool AMDGPUMCExpr::evaluateAlignTo(MCValue &Res, const MCAssembler *Asm, 154*0fca6ea1SDimitry Andric const MCFixup *Fixup) const { 155*0fca6ea1SDimitry Andric auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) { 156*0fca6ea1SDimitry Andric MCValue MCVal; 157*0fca6ea1SDimitry Andric if (!Arg->evaluateAsRelocatable(MCVal, Asm, Fixup) || !MCVal.isAbsolute()) 158*0fca6ea1SDimitry Andric return false; 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric ConstantValue = MCVal.getConstant(); 161*0fca6ea1SDimitry Andric return true; 162*0fca6ea1SDimitry Andric }; 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric assert(Args.size() == 2 && 165*0fca6ea1SDimitry Andric "AMDGPUMCExpr Argument count incorrect for AlignTo"); 166*0fca6ea1SDimitry Andric uint64_t Value = 0, Align = 0; 167*0fca6ea1SDimitry Andric if (!TryGetMCExprValue(Args[0], Value) || !TryGetMCExprValue(Args[1], Align)) 168*0fca6ea1SDimitry Andric return false; 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric Res = MCValue::get(alignTo(Value, Align)); 171*0fca6ea1SDimitry Andric return true; 172*0fca6ea1SDimitry Andric } 173*0fca6ea1SDimitry Andric 174*0fca6ea1SDimitry Andric bool AMDGPUMCExpr::evaluateOccupancy(MCValue &Res, const MCAssembler *Asm, 175*0fca6ea1SDimitry Andric const MCFixup *Fixup) const { 176*0fca6ea1SDimitry Andric auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) { 177*0fca6ea1SDimitry Andric MCValue MCVal; 178*0fca6ea1SDimitry Andric if (!Arg->evaluateAsRelocatable(MCVal, Asm, Fixup) || !MCVal.isAbsolute()) 179*0fca6ea1SDimitry Andric return false; 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric ConstantValue = MCVal.getConstant(); 182*0fca6ea1SDimitry Andric return true; 183*0fca6ea1SDimitry Andric }; 184*0fca6ea1SDimitry Andric assert(Args.size() == 7 && 185*0fca6ea1SDimitry Andric "AMDGPUMCExpr Argument count incorrect for Occupancy"); 186*0fca6ea1SDimitry Andric uint64_t InitOccupancy, MaxWaves, Granule, TargetTotalNumVGPRs, Generation, 187*0fca6ea1SDimitry Andric NumSGPRs, NumVGPRs; 188*0fca6ea1SDimitry Andric 189*0fca6ea1SDimitry Andric bool Success = true; 190*0fca6ea1SDimitry Andric Success &= TryGetMCExprValue(Args[0], MaxWaves); 191*0fca6ea1SDimitry Andric Success &= TryGetMCExprValue(Args[1], Granule); 192*0fca6ea1SDimitry Andric Success &= TryGetMCExprValue(Args[2], TargetTotalNumVGPRs); 193*0fca6ea1SDimitry Andric Success &= TryGetMCExprValue(Args[3], Generation); 194*0fca6ea1SDimitry Andric Success &= TryGetMCExprValue(Args[4], InitOccupancy); 195*0fca6ea1SDimitry Andric 196*0fca6ea1SDimitry Andric assert(Success && "Arguments 1 to 5 for Occupancy should be known constants"); 197*0fca6ea1SDimitry Andric 198*0fca6ea1SDimitry Andric if (!Success || !TryGetMCExprValue(Args[5], NumSGPRs) || 199*0fca6ea1SDimitry Andric !TryGetMCExprValue(Args[6], NumVGPRs)) 200*0fca6ea1SDimitry Andric return false; 201*0fca6ea1SDimitry Andric 202*0fca6ea1SDimitry Andric unsigned Occupancy = InitOccupancy; 203*0fca6ea1SDimitry Andric if (NumSGPRs) 204*0fca6ea1SDimitry Andric Occupancy = std::min( 205*0fca6ea1SDimitry Andric Occupancy, IsaInfo::getOccupancyWithNumSGPRs( 206*0fca6ea1SDimitry Andric NumSGPRs, MaxWaves, 207*0fca6ea1SDimitry Andric static_cast<AMDGPUSubtarget::Generation>(Generation))); 208*0fca6ea1SDimitry Andric if (NumVGPRs) 209*0fca6ea1SDimitry Andric Occupancy = std::min(Occupancy, 210*0fca6ea1SDimitry Andric IsaInfo::getNumWavesPerEUWithNumVGPRs( 211*0fca6ea1SDimitry Andric NumVGPRs, Granule, MaxWaves, TargetTotalNumVGPRs)); 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric Res = MCValue::get(Occupancy); 214*0fca6ea1SDimitry Andric return true; 215*0fca6ea1SDimitry Andric } 216*0fca6ea1SDimitry Andric 217*0fca6ea1SDimitry Andric bool AMDGPUMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 218*0fca6ea1SDimitry Andric const MCAssembler *Asm, 219*0fca6ea1SDimitry Andric const MCFixup *Fixup) const { 220*0fca6ea1SDimitry Andric std::optional<int64_t> Total; 221*0fca6ea1SDimitry Andric switch (Kind) { 222*0fca6ea1SDimitry Andric default: 223*0fca6ea1SDimitry Andric break; 224*0fca6ea1SDimitry Andric case AGVK_ExtraSGPRs: 225*0fca6ea1SDimitry Andric return evaluateExtraSGPRs(Res, Asm, Fixup); 226*0fca6ea1SDimitry Andric case AGVK_AlignTo: 227*0fca6ea1SDimitry Andric return evaluateAlignTo(Res, Asm, Fixup); 228*0fca6ea1SDimitry Andric case AGVK_TotalNumVGPRs: 229*0fca6ea1SDimitry Andric return evaluateTotalNumVGPR(Res, Asm, Fixup); 230*0fca6ea1SDimitry Andric case AGVK_Occupancy: 231*0fca6ea1SDimitry Andric return evaluateOccupancy(Res, Asm, Fixup); 232*0fca6ea1SDimitry Andric } 233*0fca6ea1SDimitry Andric 234*0fca6ea1SDimitry Andric for (const MCExpr *Arg : Args) { 235*0fca6ea1SDimitry Andric MCValue ArgRes; 236*0fca6ea1SDimitry Andric if (!Arg->evaluateAsRelocatable(ArgRes, Asm, Fixup) || !ArgRes.isAbsolute()) 237*0fca6ea1SDimitry Andric return false; 238*0fca6ea1SDimitry Andric 239*0fca6ea1SDimitry Andric if (!Total.has_value()) 240*0fca6ea1SDimitry Andric Total = ArgRes.getConstant(); 241*0fca6ea1SDimitry Andric Total = op(Kind, *Total, ArgRes.getConstant()); 242*0fca6ea1SDimitry Andric } 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric Res = MCValue::get(*Total); 245*0fca6ea1SDimitry Andric return true; 246*0fca6ea1SDimitry Andric } 247*0fca6ea1SDimitry Andric 248*0fca6ea1SDimitry Andric void AMDGPUMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 249*0fca6ea1SDimitry Andric for (const MCExpr *Arg : Args) 250*0fca6ea1SDimitry Andric Streamer.visitUsedExpr(*Arg); 251*0fca6ea1SDimitry Andric } 252*0fca6ea1SDimitry Andric 253*0fca6ea1SDimitry Andric MCFragment *AMDGPUMCExpr::findAssociatedFragment() const { 254*0fca6ea1SDimitry Andric for (const MCExpr *Arg : Args) { 255*0fca6ea1SDimitry Andric if (Arg->findAssociatedFragment()) 256*0fca6ea1SDimitry Andric return Arg->findAssociatedFragment(); 257*0fca6ea1SDimitry Andric } 258*0fca6ea1SDimitry Andric return nullptr; 259*0fca6ea1SDimitry Andric } 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric /// Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed 262*0fca6ea1SDimitry Andric /// are unresolvable but needed for further MCExprs). Derived from 263*0fca6ea1SDimitry Andric /// implementation of IsaInfo::getNumExtraSGPRs in AMDGPUBaseInfo.cpp. 264*0fca6ea1SDimitry Andric /// 265*0fca6ea1SDimitry Andric const AMDGPUMCExpr *AMDGPUMCExpr::createExtraSGPRs(const MCExpr *VCCUsed, 266*0fca6ea1SDimitry Andric const MCExpr *FlatScrUsed, 267*0fca6ea1SDimitry Andric bool XNACKUsed, 268*0fca6ea1SDimitry Andric MCContext &Ctx) { 269*0fca6ea1SDimitry Andric 270*0fca6ea1SDimitry Andric return create(AGVK_ExtraSGPRs, 271*0fca6ea1SDimitry Andric {VCCUsed, FlatScrUsed, MCConstantExpr::create(XNACKUsed, Ctx)}, 272*0fca6ea1SDimitry Andric Ctx); 273*0fca6ea1SDimitry Andric } 274*0fca6ea1SDimitry Andric 275*0fca6ea1SDimitry Andric const AMDGPUMCExpr *AMDGPUMCExpr::createTotalNumVGPR(const MCExpr *NumAGPR, 276*0fca6ea1SDimitry Andric const MCExpr *NumVGPR, 277*0fca6ea1SDimitry Andric MCContext &Ctx) { 278*0fca6ea1SDimitry Andric return create(AGVK_TotalNumVGPRs, {NumAGPR, NumVGPR}, Ctx); 279*0fca6ea1SDimitry Andric } 280*0fca6ea1SDimitry Andric 281*0fca6ea1SDimitry Andric /// Mimics GCNSubtarget::computeOccupancy for MCExpr. 282*0fca6ea1SDimitry Andric /// 283*0fca6ea1SDimitry Andric /// Remove dependency on GCNSubtarget and depend only only the necessary values 284*0fca6ea1SDimitry Andric /// for said occupancy computation. Should match computeOccupancy implementation 285*0fca6ea1SDimitry Andric /// without passing \p STM on. 286*0fca6ea1SDimitry Andric const AMDGPUMCExpr *AMDGPUMCExpr::createOccupancy(unsigned InitOcc, 287*0fca6ea1SDimitry Andric const MCExpr *NumSGPRs, 288*0fca6ea1SDimitry Andric const MCExpr *NumVGPRs, 289*0fca6ea1SDimitry Andric const GCNSubtarget &STM, 290*0fca6ea1SDimitry Andric MCContext &Ctx) { 291*0fca6ea1SDimitry Andric unsigned MaxWaves = IsaInfo::getMaxWavesPerEU(&STM); 292*0fca6ea1SDimitry Andric unsigned Granule = IsaInfo::getVGPRAllocGranule(&STM); 293*0fca6ea1SDimitry Andric unsigned TargetTotalNumVGPRs = IsaInfo::getTotalNumVGPRs(&STM); 294*0fca6ea1SDimitry Andric unsigned Generation = STM.getGeneration(); 295*0fca6ea1SDimitry Andric 296*0fca6ea1SDimitry Andric auto CreateExpr = [&Ctx](unsigned Value) { 297*0fca6ea1SDimitry Andric return MCConstantExpr::create(Value, Ctx); 298*0fca6ea1SDimitry Andric }; 299*0fca6ea1SDimitry Andric 300*0fca6ea1SDimitry Andric return create(AGVK_Occupancy, 301*0fca6ea1SDimitry Andric {CreateExpr(MaxWaves), CreateExpr(Granule), 302*0fca6ea1SDimitry Andric CreateExpr(TargetTotalNumVGPRs), CreateExpr(Generation), 303*0fca6ea1SDimitry Andric CreateExpr(InitOcc), NumSGPRs, NumVGPRs}, 304*0fca6ea1SDimitry Andric Ctx); 305*0fca6ea1SDimitry Andric } 306