brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.6 KiB · 093c85e Raw
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