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