717 lines · cpp
1//===- AMDGPUMCExpr.cpp - AMDGPU specific MC expression classes -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "AMDGPUMCExpr.h"10#include "Utils/AMDGPUBaseInfo.h"11#include "llvm/MC/MCAsmInfo.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCStreamer.h"15#include "llvm/MC/MCSymbol.h"16#include "llvm/MC/MCValue.h"17#include "llvm/Support/KnownBits.h"18#include "llvm/Support/raw_ostream.h"19#include <optional>20 21using namespace llvm;22using namespace llvm::AMDGPU;23 24AMDGPUMCExpr::AMDGPUMCExpr(VariantKind Kind, ArrayRef<const MCExpr *> Args,25 MCContext &Ctx)26 : Kind(Kind), Ctx(Ctx) {27 assert(Args.size() >= 1 && "Needs a minimum of one expression.");28 assert(Kind != AGVK_None && "Cannot construct AMDGPUMCExpr of kind none.");29 30 // Allocating the variadic arguments through the same allocation mechanism31 // that the object itself is allocated with so they end up in the same memory.32 //33 // Will result in an asan failure if allocated on the heap through standard34 // allocation (e.g., through SmallVector's grow).35 RawArgs = static_cast<const MCExpr **>(36 Ctx.allocate(sizeof(const MCExpr *) * Args.size()));37 llvm::uninitialized_copy(Args, RawArgs);38 this->Args = ArrayRef<const MCExpr *>(RawArgs, Args.size());39}40 41AMDGPUMCExpr::~AMDGPUMCExpr() { Ctx.deallocate(RawArgs); }42 43const AMDGPUMCExpr *AMDGPUMCExpr::create(VariantKind Kind,44 ArrayRef<const MCExpr *> Args,45 MCContext &Ctx) {46 return new (Ctx) AMDGPUMCExpr(Kind, Args, Ctx);47}48 49const MCExpr *AMDGPUMCExpr::getSubExpr(size_t Index) const {50 assert(Index < Args.size() && "Indexing out of bounds AMDGPUMCExpr sub-expr");51 return Args[Index];52}53 54void AMDGPUMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {55 switch (Kind) {56 default:57 llvm_unreachable("Unknown AMDGPUMCExpr kind.");58 case AGVK_Or:59 OS << "or(";60 break;61 case AGVK_Max:62 OS << "max(";63 break;64 case AGVK_ExtraSGPRs:65 OS << "extrasgprs(";66 break;67 case AGVK_TotalNumVGPRs:68 OS << "totalnumvgprs(";69 break;70 case AGVK_AlignTo:71 OS << "alignto(";72 break;73 case AGVK_Occupancy:74 OS << "occupancy(";75 break;76 case AGVK_Lit:77 OS << "lit(";78 break;79 case AGVK_Lit64:80 OS << "lit64(";81 break;82 }83 for (const auto *It = Args.begin(); It != Args.end(); ++It) {84 MAI->printExpr(OS, **It);85 if ((It + 1) != Args.end())86 OS << ", ";87 }88 OS << ')';89}90 91static int64_t op(AMDGPUMCExpr::VariantKind Kind, int64_t Arg1, int64_t Arg2) {92 switch (Kind) {93 default:94 llvm_unreachable("Unknown AMDGPUMCExpr kind.");95 case AMDGPUMCExpr::AGVK_Max:96 return std::max(Arg1, Arg2);97 case AMDGPUMCExpr::AGVK_Or:98 return Arg1 | Arg2;99 }100}101 102bool AMDGPUMCExpr::evaluateExtraSGPRs(MCValue &Res,103 const MCAssembler *Asm) const {104 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {105 MCValue MCVal;106 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())107 return false;108 109 ConstantValue = MCVal.getConstant();110 return true;111 };112 113 assert(Args.size() == 3 &&114 "AMDGPUMCExpr Argument count incorrect for ExtraSGPRs");115 const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();116 uint64_t VCCUsed = 0, FlatScrUsed = 0, XNACKUsed = 0;117 118 bool Success = TryGetMCExprValue(Args[2], XNACKUsed);119 120 assert(Success && "Arguments 3 for ExtraSGPRs should be a known constant");121 if (!Success || !TryGetMCExprValue(Args[0], VCCUsed) ||122 !TryGetMCExprValue(Args[1], FlatScrUsed))123 return false;124 125 uint64_t ExtraSGPRs = IsaInfo::getNumExtraSGPRs(126 STI, (bool)VCCUsed, (bool)FlatScrUsed, (bool)XNACKUsed);127 Res = MCValue::get(ExtraSGPRs);128 return true;129}130 131bool AMDGPUMCExpr::evaluateTotalNumVGPR(MCValue &Res,132 const MCAssembler *Asm) const {133 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {134 MCValue MCVal;135 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())136 return false;137 138 ConstantValue = MCVal.getConstant();139 return true;140 };141 assert(Args.size() == 2 &&142 "AMDGPUMCExpr Argument count incorrect for TotalNumVGPRs");143 const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();144 uint64_t NumAGPR = 0, NumVGPR = 0;145 146 bool Has90AInsts = AMDGPU::isGFX90A(*STI);147 148 if (!TryGetMCExprValue(Args[0], NumAGPR) ||149 !TryGetMCExprValue(Args[1], NumVGPR))150 return false;151 152 uint64_t TotalNum = Has90AInsts && NumAGPR ? alignTo(NumVGPR, 4) + NumAGPR153 : std::max(NumVGPR, NumAGPR);154 Res = MCValue::get(TotalNum);155 return true;156}157 158bool AMDGPUMCExpr::evaluateAlignTo(MCValue &Res, const MCAssembler *Asm) const {159 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {160 MCValue MCVal;161 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())162 return false;163 164 ConstantValue = MCVal.getConstant();165 return true;166 };167 168 assert(Args.size() == 2 &&169 "AMDGPUMCExpr Argument count incorrect for AlignTo");170 uint64_t Value = 0, Align = 0;171 if (!TryGetMCExprValue(Args[0], Value) || !TryGetMCExprValue(Args[1], Align))172 return false;173 174 Res = MCValue::get(alignTo(Value, Align));175 return true;176}177 178bool AMDGPUMCExpr::evaluateOccupancy(MCValue &Res,179 const MCAssembler *Asm) const {180 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {181 MCValue MCVal;182 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())183 return false;184 185 ConstantValue = MCVal.getConstant();186 return true;187 };188 assert(Args.size() == 7 &&189 "AMDGPUMCExpr Argument count incorrect for Occupancy");190 uint64_t InitOccupancy, MaxWaves, Granule, TargetTotalNumVGPRs, Generation,191 NumSGPRs, NumVGPRs;192 193 bool Success = true;194 Success &= TryGetMCExprValue(Args[0], MaxWaves);195 Success &= TryGetMCExprValue(Args[1], Granule);196 Success &= TryGetMCExprValue(Args[2], TargetTotalNumVGPRs);197 Success &= TryGetMCExprValue(Args[3], Generation);198 Success &= TryGetMCExprValue(Args[4], InitOccupancy);199 200 assert(Success && "Arguments 1 to 5 for Occupancy should be known constants");201 202 if (!Success || !TryGetMCExprValue(Args[5], NumSGPRs) ||203 !TryGetMCExprValue(Args[6], NumVGPRs))204 return false;205 206 unsigned Occupancy = InitOccupancy;207 if (NumSGPRs)208 Occupancy = std::min(209 Occupancy, IsaInfo::getOccupancyWithNumSGPRs(210 NumSGPRs, MaxWaves,211 static_cast<AMDGPUSubtarget::Generation>(Generation)));212 if (NumVGPRs)213 Occupancy = std::min(Occupancy,214 IsaInfo::getNumWavesPerEUWithNumVGPRs(215 NumVGPRs, Granule, MaxWaves, TargetTotalNumVGPRs));216 217 Res = MCValue::get(Occupancy);218 return true;219}220 221bool AMDGPUMCExpr::isSymbolUsedInExpression(const MCSymbol *Sym,222 const MCExpr *E) {223 switch (E->getKind()) {224 case MCExpr::Constant:225 return false;226 case MCExpr::Unary:227 return isSymbolUsedInExpression(228 Sym, static_cast<const MCUnaryExpr *>(E)->getSubExpr());229 case MCExpr::Binary: {230 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(E);231 return isSymbolUsedInExpression(Sym, BE->getLHS()) ||232 isSymbolUsedInExpression(Sym, BE->getRHS());233 }234 case MCExpr::SymbolRef: {235 const MCSymbol &S = static_cast<const MCSymbolRefExpr *>(E)->getSymbol();236 if (S.isVariable())237 return isSymbolUsedInExpression(Sym, S.getVariableValue());238 return &S == Sym;239 }240 case MCExpr::Specifier:241 case MCExpr::Target: {242 auto *TE = static_cast<const AMDGPUMCExpr *>(E);243 for (const MCExpr *E : TE->getArgs())244 if (isSymbolUsedInExpression(Sym, E))245 return true;246 return false;247 }248 }249 llvm_unreachable("Unknown expr kind!");250}251 252bool AMDGPUMCExpr::evaluateAsRelocatableImpl(MCValue &Res,253 const MCAssembler *Asm) const {254 std::optional<int64_t> Total;255 switch (Kind) {256 default:257 break;258 case AGVK_ExtraSGPRs:259 return evaluateExtraSGPRs(Res, Asm);260 case AGVK_AlignTo:261 return evaluateAlignTo(Res, Asm);262 case AGVK_TotalNumVGPRs:263 return evaluateTotalNumVGPR(Res, Asm);264 case AGVK_Occupancy:265 return evaluateOccupancy(Res, Asm);266 case AGVK_Lit:267 case AGVK_Lit64:268 return Args[0]->evaluateAsRelocatable(Res, Asm);269 }270 271 for (const MCExpr *Arg : Args) {272 MCValue ArgRes;273 if (!Arg->evaluateAsRelocatable(ArgRes, Asm) || !ArgRes.isAbsolute())274 return false;275 276 if (!Total.has_value())277 Total = ArgRes.getConstant();278 Total = op(Kind, *Total, ArgRes.getConstant());279 }280 281 Res = MCValue::get(*Total);282 return true;283}284 285void AMDGPUMCExpr::visitUsedExpr(MCStreamer &Streamer) const {286 for (const MCExpr *Arg : Args)287 Streamer.visitUsedExpr(*Arg);288}289 290MCFragment *AMDGPUMCExpr::findAssociatedFragment() const {291 for (const MCExpr *Arg : Args) {292 if (Arg->findAssociatedFragment())293 return Arg->findAssociatedFragment();294 }295 return nullptr;296}297 298/// Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed299/// are unresolvable but needed for further MCExprs). Derived from300/// implementation of IsaInfo::getNumExtraSGPRs in AMDGPUBaseInfo.cpp.301///302const AMDGPUMCExpr *AMDGPUMCExpr::createExtraSGPRs(const MCExpr *VCCUsed,303 const MCExpr *FlatScrUsed,304 bool XNACKUsed,305 MCContext &Ctx) {306 307 return create(AGVK_ExtraSGPRs,308 {VCCUsed, FlatScrUsed, MCConstantExpr::create(XNACKUsed, Ctx)},309 Ctx);310}311 312const AMDGPUMCExpr *AMDGPUMCExpr::createTotalNumVGPR(const MCExpr *NumAGPR,313 const MCExpr *NumVGPR,314 MCContext &Ctx) {315 return create(AGVK_TotalNumVGPRs, {NumAGPR, NumVGPR}, Ctx);316}317 318const AMDGPUMCExpr *AMDGPUMCExpr::createLit(LitModifier Lit, int64_t Value,319 MCContext &Ctx) {320 assert(Lit == LitModifier::Lit || Lit == LitModifier::Lit64);321 return create(Lit == LitModifier::Lit ? VariantKind::AGVK_Lit322 : VariantKind::AGVK_Lit64,323 {MCConstantExpr::create(Value, Ctx, /*PrintInHex=*/true)}, Ctx);324}325 326static KnownBits fromOptionalToKnownBits(std::optional<bool> CompareResult) {327 static constexpr unsigned BitWidth = 64;328 const APInt True(BitWidth, 1);329 const APInt False(BitWidth, 0);330 if (CompareResult) {331 return *CompareResult ? KnownBits::makeConstant(True)332 : KnownBits::makeConstant(False);333 }334 335 KnownBits UnknownBool(/*BitWidth=*/1);336 return UnknownBool.zext(BitWidth);337}338 339using KnownBitsMap = DenseMap<const MCExpr *, KnownBits>;340static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,341 unsigned Depth = 0);342 343static void binaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,344 unsigned Depth) {345 static constexpr unsigned BitWidth = 64;346 const MCBinaryExpr *BExpr = cast<MCBinaryExpr>(Expr);347 const MCExpr *LHS = BExpr->getLHS();348 const MCExpr *RHS = BExpr->getRHS();349 350 knownBitsMapHelper(LHS, KBM, Depth + 1);351 knownBitsMapHelper(RHS, KBM, Depth + 1);352 KnownBits LHSKnown = KBM[LHS];353 KnownBits RHSKnown = KBM[RHS];354 355 switch (BExpr->getOpcode()) {356 default:357 KBM[Expr] = KnownBits(BitWidth);358 return;359 case MCBinaryExpr::Opcode::Add:360 KBM[Expr] = KnownBits::add(LHSKnown, RHSKnown);361 return;362 case MCBinaryExpr::Opcode::And:363 KBM[Expr] = LHSKnown & RHSKnown;364 return;365 case MCBinaryExpr::Opcode::Div:366 KBM[Expr] = KnownBits::sdiv(LHSKnown, RHSKnown);367 return;368 case MCBinaryExpr::Opcode::EQ: {369 std::optional<bool> CompareRes = KnownBits::eq(LHSKnown, RHSKnown);370 KBM[Expr] = fromOptionalToKnownBits(CompareRes);371 return;372 }373 case MCBinaryExpr::Opcode::NE: {374 std::optional<bool> CompareRes = KnownBits::ne(LHSKnown, RHSKnown);375 KBM[Expr] = fromOptionalToKnownBits(CompareRes);376 return;377 }378 case MCBinaryExpr::Opcode::GT: {379 std::optional<bool> CompareRes = KnownBits::sgt(LHSKnown, RHSKnown);380 KBM[Expr] = fromOptionalToKnownBits(CompareRes);381 return;382 }383 case MCBinaryExpr::Opcode::GTE: {384 std::optional<bool> CompareRes = KnownBits::sge(LHSKnown, RHSKnown);385 KBM[Expr] = fromOptionalToKnownBits(CompareRes);386 return;387 }388 case MCBinaryExpr::Opcode::LAnd: {389 std::optional<bool> CompareRes;390 const APInt False(BitWidth, 0);391 std::optional<bool> LHSBool =392 KnownBits::ne(LHSKnown, KnownBits::makeConstant(False));393 std::optional<bool> RHSBool =394 KnownBits::ne(RHSKnown, KnownBits::makeConstant(False));395 if (LHSBool && RHSBool)396 CompareRes = *LHSBool && *RHSBool;397 KBM[Expr] = fromOptionalToKnownBits(CompareRes);398 return;399 }400 case MCBinaryExpr::Opcode::LOr: {401 const APInt False(BitWidth, 0);402 KnownBits Bits = LHSKnown | RHSKnown;403 std::optional<bool> CompareRes =404 KnownBits::ne(Bits, KnownBits::makeConstant(False));405 KBM[Expr] = fromOptionalToKnownBits(CompareRes);406 return;407 }408 case MCBinaryExpr::Opcode::LT: {409 std::optional<bool> CompareRes = KnownBits::slt(LHSKnown, RHSKnown);410 KBM[Expr] = fromOptionalToKnownBits(CompareRes);411 return;412 }413 case MCBinaryExpr::Opcode::LTE: {414 std::optional<bool> CompareRes = KnownBits::sle(LHSKnown, RHSKnown);415 KBM[Expr] = fromOptionalToKnownBits(CompareRes);416 return;417 }418 case MCBinaryExpr::Opcode::Mod:419 KBM[Expr] = KnownBits::srem(LHSKnown, RHSKnown);420 return;421 case MCBinaryExpr::Opcode::Mul:422 KBM[Expr] = KnownBits::mul(LHSKnown, RHSKnown);423 return;424 case MCBinaryExpr::Opcode::Or:425 KBM[Expr] = LHSKnown | RHSKnown;426 return;427 case MCBinaryExpr::Opcode::Shl:428 KBM[Expr] = KnownBits::shl(LHSKnown, RHSKnown);429 return;430 case MCBinaryExpr::Opcode::AShr:431 KBM[Expr] = KnownBits::ashr(LHSKnown, RHSKnown);432 return;433 case MCBinaryExpr::Opcode::LShr:434 KBM[Expr] = KnownBits::lshr(LHSKnown, RHSKnown);435 return;436 case MCBinaryExpr::Opcode::Sub:437 KBM[Expr] = KnownBits::sub(LHSKnown, RHSKnown);438 return;439 case MCBinaryExpr::Opcode::Xor:440 KBM[Expr] = LHSKnown ^ RHSKnown;441 return;442 }443}444 445static void unaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,446 unsigned Depth) {447 static constexpr unsigned BitWidth = 64;448 const MCUnaryExpr *UExpr = cast<MCUnaryExpr>(Expr);449 knownBitsMapHelper(UExpr->getSubExpr(), KBM, Depth + 1);450 KnownBits KB = KBM[UExpr->getSubExpr()];451 452 switch (UExpr->getOpcode()) {453 default:454 KBM[Expr] = KnownBits(BitWidth);455 return;456 case MCUnaryExpr::Opcode::Minus: {457 KB.makeNegative();458 KBM[Expr] = KB;459 return;460 }461 case MCUnaryExpr::Opcode::Not: {462 KnownBits AllOnes(BitWidth);463 AllOnes.setAllOnes();464 KBM[Expr] = KB ^ AllOnes;465 return;466 }467 case MCUnaryExpr::Opcode::Plus: {468 KB.makeNonNegative();469 KBM[Expr] = KB;470 return;471 }472 }473}474 475static void targetOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,476 unsigned Depth) {477 static constexpr unsigned BitWidth = 64;478 const AMDGPUMCExpr *AGVK = cast<AMDGPUMCExpr>(Expr);479 480 switch (AGVK->getKind()) {481 default:482 KBM[Expr] = KnownBits(BitWidth);483 return;484 case AMDGPUMCExpr::VariantKind::AGVK_Or: {485 knownBitsMapHelper(AGVK->getSubExpr(0), KBM, Depth + 1);486 KnownBits KB = KBM[AGVK->getSubExpr(0)];487 for (const MCExpr *Arg : AGVK->getArgs()) {488 knownBitsMapHelper(Arg, KBM, Depth + 1);489 KB |= KBM[Arg];490 }491 KBM[Expr] = KB;492 return;493 }494 case AMDGPUMCExpr::VariantKind::AGVK_Max: {495 knownBitsMapHelper(AGVK->getSubExpr(0), KBM, Depth + 1);496 KnownBits KB = KBM[AGVK->getSubExpr(0)];497 for (const MCExpr *Arg : AGVK->getArgs()) {498 knownBitsMapHelper(Arg, KBM, Depth + 1);499 KB = KnownBits::umax(KB, KBM[Arg]);500 }501 KBM[Expr] = KB;502 return;503 }504 case AMDGPUMCExpr::VariantKind::AGVK_ExtraSGPRs:505 case AMDGPUMCExpr::VariantKind::AGVK_TotalNumVGPRs:506 case AMDGPUMCExpr::VariantKind::AGVK_AlignTo:507 case AMDGPUMCExpr::VariantKind::AGVK_Occupancy:508 case AMDGPUMCExpr::VariantKind::AGVK_Lit:509 case AMDGPUMCExpr::VariantKind::AGVK_Lit64: {510 int64_t Val;511 if (AGVK->evaluateAsAbsolute(Val)) {512 APInt APValue(BitWidth, Val);513 KBM[Expr] = KnownBits::makeConstant(APValue);514 return;515 }516 KBM[Expr] = KnownBits(BitWidth);517 return;518 }519 }520}521 522static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,523 unsigned Depth) {524 static constexpr unsigned BitWidth = 64;525 526 int64_t Val;527 if (Expr->evaluateAsAbsolute(Val)) {528 APInt APValue(BitWidth, Val, /*isSigned=*/true);529 KBM[Expr] = KnownBits::makeConstant(APValue);530 return;531 }532 533 if (Depth == 16) {534 KBM[Expr] = KnownBits(BitWidth);535 return;536 }537 538 switch (Expr->getKind()) {539 case MCExpr::ExprKind::Binary: {540 binaryOpKnownBitsMapHelper(Expr, KBM, Depth);541 return;542 }543 case MCExpr::ExprKind::Constant: {544 const MCConstantExpr *CE = cast<MCConstantExpr>(Expr);545 APInt APValue(BitWidth, CE->getValue(), /*isSigned=*/true);546 KBM[Expr] = KnownBits::makeConstant(APValue);547 return;548 }549 case MCExpr::ExprKind::SymbolRef: {550 const MCSymbolRefExpr *RExpr = cast<MCSymbolRefExpr>(Expr);551 const MCSymbol &Sym = RExpr->getSymbol();552 if (!Sym.isVariable()) {553 KBM[Expr] = KnownBits(BitWidth);554 return;555 }556 557 // Variable value retrieval is not for actual use but only for knownbits558 // analysis.559 const MCExpr *SymVal = Sym.getVariableValue();560 knownBitsMapHelper(SymVal, KBM, Depth + 1);561 562 // Explicitly copy-construct so that there exists a local KnownBits in case563 // KBM[SymVal] gets invalidated after a potential growth through KBM[Expr].564 KBM[Expr] = KnownBits(KBM[SymVal]);565 return;566 }567 case MCExpr::ExprKind::Unary: {568 unaryOpKnownBitsMapHelper(Expr, KBM, Depth);569 return;570 }571 case MCExpr::ExprKind::Target: {572 targetOpKnownBitsMapHelper(Expr, KBM, Depth);573 return;574 case MCExpr::Specifier:575 llvm_unreachable("unused by this backend");576 }577 }578}579 580static const MCExpr *tryFoldHelper(const MCExpr *Expr, KnownBitsMap &KBM,581 MCContext &Ctx) {582 if (!KBM.count(Expr))583 return Expr;584 585 auto ValueCheckKnownBits = [](KnownBits &KB, unsigned Value) -> bool {586 if (!KB.isConstant())587 return false;588 589 return Value == KB.getConstant();590 };591 592 if (Expr->getKind() == MCExpr::ExprKind::Constant)593 return Expr;594 595 // Resolving unary operations to constants may make the value more ambiguous.596 // For example, `~62` becomes `-63`; however, to me it's more ambiguous if a597 // bit mask value is represented through a negative number.598 if (Expr->getKind() != MCExpr::ExprKind::Unary) {599 if (KBM[Expr].isConstant()) {600 APInt ConstVal = KBM[Expr].getConstant();601 return MCConstantExpr::create(ConstVal.getSExtValue(), Ctx);602 }603 604 int64_t EvalValue;605 if (Expr->evaluateAsAbsolute(EvalValue))606 return MCConstantExpr::create(EvalValue, Ctx);607 }608 609 switch (Expr->getKind()) {610 default:611 return Expr;612 case MCExpr::ExprKind::Binary: {613 const MCBinaryExpr *BExpr = cast<MCBinaryExpr>(Expr);614 const MCExpr *LHS = BExpr->getLHS();615 const MCExpr *RHS = BExpr->getRHS();616 617 switch (BExpr->getOpcode()) {618 default:619 return Expr;620 case MCBinaryExpr::Opcode::Sub: {621 if (ValueCheckKnownBits(KBM[RHS], 0))622 return tryFoldHelper(LHS, KBM, Ctx);623 break;624 }625 case MCBinaryExpr::Opcode::Add:626 case MCBinaryExpr::Opcode::Or: {627 if (ValueCheckKnownBits(KBM[LHS], 0))628 return tryFoldHelper(RHS, KBM, Ctx);629 if (ValueCheckKnownBits(KBM[RHS], 0))630 return tryFoldHelper(LHS, KBM, Ctx);631 break;632 }633 case MCBinaryExpr::Opcode::Mul: {634 if (ValueCheckKnownBits(KBM[LHS], 1))635 return tryFoldHelper(RHS, KBM, Ctx);636 if (ValueCheckKnownBits(KBM[RHS], 1))637 return tryFoldHelper(LHS, KBM, Ctx);638 break;639 }640 case MCBinaryExpr::Opcode::Shl:641 case MCBinaryExpr::Opcode::AShr:642 case MCBinaryExpr::Opcode::LShr: {643 if (ValueCheckKnownBits(KBM[RHS], 0))644 return tryFoldHelper(LHS, KBM, Ctx);645 if (ValueCheckKnownBits(KBM[LHS], 0))646 return MCConstantExpr::create(0, Ctx);647 break;648 }649 case MCBinaryExpr::Opcode::And: {650 if (ValueCheckKnownBits(KBM[LHS], 0) || ValueCheckKnownBits(KBM[RHS], 0))651 return MCConstantExpr::create(0, Ctx);652 break;653 }654 }655 const MCExpr *NewLHS = tryFoldHelper(LHS, KBM, Ctx);656 const MCExpr *NewRHS = tryFoldHelper(RHS, KBM, Ctx);657 if (NewLHS != LHS || NewRHS != RHS)658 return MCBinaryExpr::create(BExpr->getOpcode(), NewLHS, NewRHS, Ctx,659 BExpr->getLoc());660 return Expr;661 }662 case MCExpr::ExprKind::Unary: {663 const MCUnaryExpr *UExpr = cast<MCUnaryExpr>(Expr);664 const MCExpr *SubExpr = UExpr->getSubExpr();665 const MCExpr *NewSubExpr = tryFoldHelper(SubExpr, KBM, Ctx);666 if (SubExpr != NewSubExpr)667 return MCUnaryExpr::create(UExpr->getOpcode(), NewSubExpr, Ctx,668 UExpr->getLoc());669 return Expr;670 }671 case MCExpr::ExprKind::Target: {672 const AMDGPUMCExpr *AGVK = cast<AMDGPUMCExpr>(Expr);673 SmallVector<const MCExpr *, 8> NewArgs;674 bool Changed = false;675 for (const MCExpr *Arg : AGVK->getArgs()) {676 const MCExpr *NewArg = tryFoldHelper(Arg, KBM, Ctx);677 NewArgs.push_back(NewArg);678 Changed |= Arg != NewArg;679 }680 return Changed ? AMDGPUMCExpr::create(AGVK->getKind(), NewArgs, Ctx) : Expr;681 }682 }683 return Expr;684}685 686const MCExpr *llvm::AMDGPU::foldAMDGPUMCExpr(const MCExpr *Expr,687 MCContext &Ctx) {688 KnownBitsMap KBM;689 knownBitsMapHelper(Expr, KBM);690 const MCExpr *NewExpr = tryFoldHelper(Expr, KBM, Ctx);691 692 return Expr != NewExpr ? NewExpr : Expr;693}694 695void llvm::AMDGPU::printAMDGPUMCExpr(const MCExpr *Expr, raw_ostream &OS,696 const MCAsmInfo *MAI) {697 int64_t Val;698 if (Expr->evaluateAsAbsolute(Val)) {699 OS << Val;700 return;701 }702 703 MAI->printExpr(OS, *Expr);704}705 706bool AMDGPU::isLitExpr(const MCExpr *Expr) {707 const auto *E = dyn_cast<AMDGPUMCExpr>(Expr);708 return E && (E->getKind() == AMDGPUMCExpr::AGVK_Lit ||709 E->getKind() == AMDGPUMCExpr::AGVK_Lit64);710}711 712int64_t AMDGPU::getLitValue(const MCExpr *Expr) {713 assert(isLitExpr(Expr));714 return cast<MCConstantExpr>(cast<AMDGPUMCExpr>(Expr)->getArgs()[0])715 ->getValue();716}717