LLVM 22.0.0git
AMDGPUMCExpr.cpp
Go to the documentation of this file.
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"
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"
21#include <optional>
22
23using namespace llvm;
24using namespace llvm::AMDGPU;
25
26AMDGPUMCExpr::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 llvm::uninitialized_copy(Args, RawArgs);
40 this->Args = ArrayRef<const MCExpr *>(RawArgs, Args.size());
41}
42
43AMDGPUMCExpr::~AMDGPUMCExpr() { Ctx.deallocate(RawArgs); }
44
45const AMDGPUMCExpr *AMDGPUMCExpr::create(VariantKind Kind,
47 MCContext &Ctx) {
48 return new (Ctx) AMDGPUMCExpr(Kind, Args, Ctx);
49}
50
51const 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
56void 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;
70 OS << "totalnumvgprs(";
71 break;
72 case AGVK_AlignTo:
73 OS << "alignto(";
74 break;
75 case AGVK_Occupancy:
76 OS << "occupancy(";
77 break;
78 case AGVK_Lit:
79 OS << "lit(";
80 break;
81 case AGVK_Lit64:
82 OS << "lit64(";
83 break;
84 }
85 for (const auto *It = Args.begin(); It != Args.end(); ++It) {
86 MAI->printExpr(OS, **It);
87 if ((It + 1) != Args.end())
88 OS << ", ";
89 }
90 OS << ')';
91}
92
93static int64_t op(AMDGPUMCExpr::VariantKind Kind, int64_t Arg1, int64_t Arg2) {
94 switch (Kind) {
95 default:
96 llvm_unreachable("Unknown AMDGPUMCExpr kind.");
98 return std::max(Arg1, Arg2);
100 return Arg1 | Arg2;
101 }
102}
103
104bool AMDGPUMCExpr::evaluateExtraSGPRs(MCValue &Res,
105 const MCAssembler *Asm) const {
106 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {
107 MCValue MCVal;
108 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())
109 return false;
110
111 ConstantValue = MCVal.getConstant();
112 return true;
113 };
114
115 assert(Args.size() == 3 &&
116 "AMDGPUMCExpr Argument count incorrect for ExtraSGPRs");
117 const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();
118 uint64_t VCCUsed = 0, FlatScrUsed = 0, XNACKUsed = 0;
119
120 bool Success = TryGetMCExprValue(Args[2], XNACKUsed);
121
122 assert(Success && "Arguments 3 for ExtraSGPRs should be a known constant");
123 if (!Success || !TryGetMCExprValue(Args[0], VCCUsed) ||
124 !TryGetMCExprValue(Args[1], FlatScrUsed))
125 return false;
126
127 uint64_t ExtraSGPRs = IsaInfo::getNumExtraSGPRs(
128 STI, (bool)VCCUsed, (bool)FlatScrUsed, (bool)XNACKUsed);
129 Res = MCValue::get(ExtraSGPRs);
130 return true;
131}
132
133bool AMDGPUMCExpr::evaluateTotalNumVGPR(MCValue &Res,
134 const MCAssembler *Asm) const {
135 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {
136 MCValue MCVal;
137 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())
138 return false;
139
140 ConstantValue = MCVal.getConstant();
141 return true;
142 };
143 assert(Args.size() == 2 &&
144 "AMDGPUMCExpr Argument count incorrect for TotalNumVGPRs");
145 const MCSubtargetInfo *STI = Ctx.getSubtargetInfo();
146 uint64_t NumAGPR = 0, NumVGPR = 0;
147
148 bool Has90AInsts = AMDGPU::isGFX90A(*STI);
149
150 if (!TryGetMCExprValue(Args[0], NumAGPR) ||
151 !TryGetMCExprValue(Args[1], NumVGPR))
152 return false;
153
154 uint64_t TotalNum = Has90AInsts && NumAGPR ? alignTo(NumVGPR, 4) + NumAGPR
155 : std::max(NumVGPR, NumAGPR);
156 Res = MCValue::get(TotalNum);
157 return true;
158}
159
160bool AMDGPUMCExpr::evaluateAlignTo(MCValue &Res, const MCAssembler *Asm) const {
161 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {
162 MCValue MCVal;
163 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())
164 return false;
165
166 ConstantValue = MCVal.getConstant();
167 return true;
168 };
169
170 assert(Args.size() == 2 &&
171 "AMDGPUMCExpr Argument count incorrect for AlignTo");
172 uint64_t Value = 0, Align = 0;
173 if (!TryGetMCExprValue(Args[0], Value) || !TryGetMCExprValue(Args[1], Align))
174 return false;
175
176 Res = MCValue::get(alignTo(Value, Align));
177 return true;
178}
179
180bool AMDGPUMCExpr::evaluateOccupancy(MCValue &Res,
181 const MCAssembler *Asm) const {
182 auto TryGetMCExprValue = [&](const MCExpr *Arg, uint64_t &ConstantValue) {
183 MCValue MCVal;
184 if (!Arg->evaluateAsRelocatable(MCVal, Asm) || !MCVal.isAbsolute())
185 return false;
186
187 ConstantValue = MCVal.getConstant();
188 return true;
189 };
190 assert(Args.size() == 7 &&
191 "AMDGPUMCExpr Argument count incorrect for Occupancy");
192 uint64_t InitOccupancy, MaxWaves, Granule, TargetTotalNumVGPRs, Generation,
194
195 bool Success = true;
196 Success &= TryGetMCExprValue(Args[0], MaxWaves);
197 Success &= TryGetMCExprValue(Args[1], Granule);
198 Success &= TryGetMCExprValue(Args[2], TargetTotalNumVGPRs);
199 Success &= TryGetMCExprValue(Args[3], Generation);
200 Success &= TryGetMCExprValue(Args[4], InitOccupancy);
201
202 assert(Success && "Arguments 1 to 5 for Occupancy should be known constants");
203
204 if (!Success || !TryGetMCExprValue(Args[5], NumSGPRs) ||
205 !TryGetMCExprValue(Args[6], NumVGPRs))
206 return false;
207
208 unsigned Occupancy = InitOccupancy;
209 if (NumSGPRs)
210 Occupancy = std::min(
212 NumSGPRs, MaxWaves,
213 static_cast<AMDGPUSubtarget::Generation>(Generation)));
214 if (NumVGPRs)
215 Occupancy = std::min(Occupancy,
217 NumVGPRs, Granule, MaxWaves, TargetTotalNumVGPRs));
218
219 Res = MCValue::get(Occupancy);
220 return true;
221}
222
224 const MCExpr *E) {
225 switch (E->getKind()) {
226 case MCExpr::Constant:
227 return false;
228 case MCExpr::Unary:
230 Sym, static_cast<const MCUnaryExpr *>(E)->getSubExpr());
231 case MCExpr::Binary: {
232 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(E);
233 return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
235 }
236 case MCExpr::SymbolRef: {
237 const MCSymbol &S = static_cast<const MCSymbolRefExpr *>(E)->getSymbol();
238 if (S.isVariable())
240 return &S == Sym;
241 }
243 case MCExpr::Target: {
244 auto *TE = static_cast<const AMDGPUMCExpr *>(E);
245 for (const MCExpr *E : TE->getArgs())
246 if (isSymbolUsedInExpression(Sym, E))
247 return true;
248 return false;
249 }
250 }
251 llvm_unreachable("Unknown expr kind!");
252}
253
255 const MCAssembler *Asm) const {
256 std::optional<int64_t> Total;
257 switch (Kind) {
258 default:
259 break;
260 case AGVK_ExtraSGPRs:
261 return evaluateExtraSGPRs(Res, Asm);
262 case AGVK_AlignTo:
263 return evaluateAlignTo(Res, Asm);
265 return evaluateTotalNumVGPR(Res, Asm);
266 case AGVK_Occupancy:
267 return evaluateOccupancy(Res, Asm);
268 case AGVK_Lit:
269 case AGVK_Lit64:
270 return Args[0]->evaluateAsRelocatable(Res, Asm);
271 }
272
273 for (const MCExpr *Arg : Args) {
274 MCValue ArgRes;
275 if (!Arg->evaluateAsRelocatable(ArgRes, Asm) || !ArgRes.isAbsolute())
276 return false;
277
278 if (!Total.has_value())
279 Total = ArgRes.getConstant();
280 Total = op(Kind, *Total, ArgRes.getConstant());
281 }
282
283 Res = MCValue::get(*Total);
284 return true;
285}
286
288 for (const MCExpr *Arg : Args)
289 Streamer.visitUsedExpr(*Arg);
290}
291
293 for (const MCExpr *Arg : Args) {
294 if (Arg->findAssociatedFragment())
295 return Arg->findAssociatedFragment();
296 }
297 return nullptr;
298}
299
300/// Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed
301/// are unresolvable but needed for further MCExprs). Derived from
302/// implementation of IsaInfo::getNumExtraSGPRs in AMDGPUBaseInfo.cpp.
303///
304const AMDGPUMCExpr *AMDGPUMCExpr::createExtraSGPRs(const MCExpr *VCCUsed,
305 const MCExpr *FlatScrUsed,
306 bool XNACKUsed,
307 MCContext &Ctx) {
308
309 return create(AGVK_ExtraSGPRs,
310 {VCCUsed, FlatScrUsed, MCConstantExpr::create(XNACKUsed, Ctx)},
311 Ctx);
312}
313
314const AMDGPUMCExpr *AMDGPUMCExpr::createTotalNumVGPR(const MCExpr *NumAGPR,
315 const MCExpr *NumVGPR,
316 MCContext &Ctx) {
317 return create(AGVK_TotalNumVGPRs, {NumAGPR, NumVGPR}, Ctx);
318}
319
320/// Mimics GCNSubtarget::computeOccupancy for MCExpr.
321///
322/// Remove dependency on GCNSubtarget and depend only only the necessary values
323/// for said occupancy computation. Should match computeOccupancy implementation
324/// without passing \p STM on.
326 unsigned InitOcc, const MCExpr *NumSGPRs, const MCExpr *NumVGPRs,
327 unsigned DynamicVGPRBlockSize, const GCNSubtarget &STM, MCContext &Ctx) {
328 unsigned MaxWaves = IsaInfo::getMaxWavesPerEU(&STM);
329 unsigned Granule = IsaInfo::getVGPRAllocGranule(&STM, DynamicVGPRBlockSize);
330 unsigned TargetTotalNumVGPRs = IsaInfo::getTotalNumVGPRs(&STM);
331 unsigned Generation = STM.getGeneration();
332
333 auto CreateExpr = [&Ctx](unsigned Value) {
334 return MCConstantExpr::create(Value, Ctx);
335 };
336
337 return create(AGVK_Occupancy,
338 {CreateExpr(MaxWaves), CreateExpr(Granule),
339 CreateExpr(TargetTotalNumVGPRs), CreateExpr(Generation),
340 CreateExpr(InitOcc), NumSGPRs, NumVGPRs},
341 Ctx);
342}
343
344const AMDGPUMCExpr *AMDGPUMCExpr::createLit(LitModifier Lit, int64_t Value,
345 MCContext &Ctx) {
349 {MCConstantExpr::create(Value, Ctx, /*PrintInHex=*/true)}, Ctx);
350}
351
352static KnownBits fromOptionalToKnownBits(std::optional<bool> CompareResult) {
353 static constexpr unsigned BitWidth = 64;
354 const APInt True(BitWidth, 1);
355 const APInt False(BitWidth, 0);
356 if (CompareResult) {
357 return *CompareResult ? KnownBits::makeConstant(True)
359 }
360
361 KnownBits UnknownBool(/*BitWidth=*/1);
362 return UnknownBool.zext(BitWidth);
363}
364
366static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
367 unsigned Depth = 0);
368
369static void binaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
370 unsigned Depth) {
371 static constexpr unsigned BitWidth = 64;
372 const MCBinaryExpr *BExpr = cast<MCBinaryExpr>(Expr);
373 const MCExpr *LHS = BExpr->getLHS();
374 const MCExpr *RHS = BExpr->getRHS();
375
376 knownBitsMapHelper(LHS, KBM, Depth + 1);
377 knownBitsMapHelper(RHS, KBM, Depth + 1);
378 KnownBits LHSKnown = KBM[LHS];
379 KnownBits RHSKnown = KBM[RHS];
380
381 switch (BExpr->getOpcode()) {
382 default:
383 KBM[Expr] = KnownBits(BitWidth);
384 return;
386 KBM[Expr] = KnownBits::add(LHSKnown, RHSKnown);
387 return;
389 KBM[Expr] = LHSKnown & RHSKnown;
390 return;
392 KBM[Expr] = KnownBits::sdiv(LHSKnown, RHSKnown);
393 return;
395 std::optional<bool> CompareRes = KnownBits::eq(LHSKnown, RHSKnown);
396 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
397 return;
398 }
400 std::optional<bool> CompareRes = KnownBits::ne(LHSKnown, RHSKnown);
401 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
402 return;
403 }
405 std::optional<bool> CompareRes = KnownBits::sgt(LHSKnown, RHSKnown);
406 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
407 return;
408 }
410 std::optional<bool> CompareRes = KnownBits::sge(LHSKnown, RHSKnown);
411 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
412 return;
413 }
415 std::optional<bool> CompareRes;
416 const APInt False(BitWidth, 0);
417 std::optional<bool> LHSBool =
418 KnownBits::ne(LHSKnown, KnownBits::makeConstant(False));
419 std::optional<bool> RHSBool =
420 KnownBits::ne(RHSKnown, KnownBits::makeConstant(False));
421 if (LHSBool && RHSBool)
422 CompareRes = *LHSBool && *RHSBool;
423 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
424 return;
425 }
427 const APInt False(BitWidth, 0);
428 KnownBits Bits = LHSKnown | RHSKnown;
429 std::optional<bool> CompareRes =
431 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
432 return;
433 }
435 std::optional<bool> CompareRes = KnownBits::slt(LHSKnown, RHSKnown);
436 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
437 return;
438 }
440 std::optional<bool> CompareRes = KnownBits::sle(LHSKnown, RHSKnown);
441 KBM[Expr] = fromOptionalToKnownBits(CompareRes);
442 return;
443 }
445 KBM[Expr] = KnownBits::srem(LHSKnown, RHSKnown);
446 return;
448 KBM[Expr] = KnownBits::mul(LHSKnown, RHSKnown);
449 return;
451 KBM[Expr] = LHSKnown | RHSKnown;
452 return;
454 KBM[Expr] = KnownBits::shl(LHSKnown, RHSKnown);
455 return;
457 KBM[Expr] = KnownBits::ashr(LHSKnown, RHSKnown);
458 return;
460 KBM[Expr] = KnownBits::lshr(LHSKnown, RHSKnown);
461 return;
463 KBM[Expr] = KnownBits::sub(LHSKnown, RHSKnown);
464 return;
466 KBM[Expr] = LHSKnown ^ RHSKnown;
467 return;
468 }
469}
470
471static void unaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
472 unsigned Depth) {
473 static constexpr unsigned BitWidth = 64;
474 const MCUnaryExpr *UExpr = cast<MCUnaryExpr>(Expr);
475 knownBitsMapHelper(UExpr->getSubExpr(), KBM, Depth + 1);
476 KnownBits KB = KBM[UExpr->getSubExpr()];
477
478 switch (UExpr->getOpcode()) {
479 default:
480 KBM[Expr] = KnownBits(BitWidth);
481 return;
483 KB.makeNegative();
484 KBM[Expr] = KB;
485 return;
486 }
489 AllOnes.setAllOnes();
490 KBM[Expr] = KB ^ AllOnes;
491 return;
492 }
494 KB.makeNonNegative();
495 KBM[Expr] = KB;
496 return;
497 }
498 }
499}
500
501static void targetOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
502 unsigned Depth) {
503 static constexpr unsigned BitWidth = 64;
504 const AMDGPUMCExpr *AGVK = cast<AMDGPUMCExpr>(Expr);
505
506 switch (AGVK->getKind()) {
507 default:
508 KBM[Expr] = KnownBits(BitWidth);
509 return;
511 knownBitsMapHelper(AGVK->getSubExpr(0), KBM, Depth + 1);
512 KnownBits KB = KBM[AGVK->getSubExpr(0)];
513 for (const MCExpr *Arg : AGVK->getArgs()) {
514 knownBitsMapHelper(Arg, KBM, Depth + 1);
515 KB |= KBM[Arg];
516 }
517 KBM[Expr] = KB;
518 return;
519 }
521 knownBitsMapHelper(AGVK->getSubExpr(0), KBM, Depth + 1);
522 KnownBits KB = KBM[AGVK->getSubExpr(0)];
523 for (const MCExpr *Arg : AGVK->getArgs()) {
524 knownBitsMapHelper(Arg, KBM, Depth + 1);
525 KB = KnownBits::umax(KB, KBM[Arg]);
526 }
527 KBM[Expr] = KB;
528 return;
529 }
536 int64_t Val;
537 if (AGVK->evaluateAsAbsolute(Val)) {
538 APInt APValue(BitWidth, Val);
539 KBM[Expr] = KnownBits::makeConstant(APValue);
540 return;
541 }
542 KBM[Expr] = KnownBits(BitWidth);
543 return;
544 }
545 }
546}
547
548static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM,
549 unsigned Depth) {
550 static constexpr unsigned BitWidth = 64;
551
552 int64_t Val;
553 if (Expr->evaluateAsAbsolute(Val)) {
554 APInt APValue(BitWidth, Val, /*isSigned=*/true);
555 KBM[Expr] = KnownBits::makeConstant(APValue);
556 return;
557 }
558
559 if (Depth == 16) {
560 KBM[Expr] = KnownBits(BitWidth);
561 return;
562 }
563
564 switch (Expr->getKind()) {
567 return;
568 }
570 const MCConstantExpr *CE = cast<MCConstantExpr>(Expr);
571 APInt APValue(BitWidth, CE->getValue(), /*isSigned=*/true);
572 KBM[Expr] = KnownBits::makeConstant(APValue);
573 return;
574 }
576 const MCSymbolRefExpr *RExpr = cast<MCSymbolRefExpr>(Expr);
577 const MCSymbol &Sym = RExpr->getSymbol();
578 if (!Sym.isVariable()) {
579 KBM[Expr] = KnownBits(BitWidth);
580 return;
581 }
582
583 // Variable value retrieval is not for actual use but only for knownbits
584 // analysis.
585 const MCExpr *SymVal = Sym.getVariableValue();
586 knownBitsMapHelper(SymVal, KBM, Depth + 1);
587
588 // Explicitly copy-construct so that there exists a local KnownBits in case
589 // KBM[SymVal] gets invalidated after a potential growth through KBM[Expr].
590 KBM[Expr] = KnownBits(KBM[SymVal]);
591 return;
592 }
595 return;
596 }
599 return;
601 llvm_unreachable("unused by this backend");
602 }
603 }
604}
605
606static const MCExpr *tryFoldHelper(const MCExpr *Expr, KnownBitsMap &KBM,
607 MCContext &Ctx) {
608 if (!KBM.count(Expr))
609 return Expr;
610
611 auto ValueCheckKnownBits = [](KnownBits &KB, unsigned Value) -> bool {
612 if (!KB.isConstant())
613 return false;
614
615 return Value == KB.getConstant();
616 };
617
618 if (Expr->getKind() == MCExpr::ExprKind::Constant)
619 return Expr;
620
621 // Resolving unary operations to constants may make the value more ambiguous.
622 // For example, `~62` becomes `-63`; however, to me it's more ambiguous if a
623 // bit mask value is represented through a negative number.
624 if (Expr->getKind() != MCExpr::ExprKind::Unary) {
625 if (KBM[Expr].isConstant()) {
626 APInt ConstVal = KBM[Expr].getConstant();
627 return MCConstantExpr::create(ConstVal.getSExtValue(), Ctx);
628 }
629
630 int64_t EvalValue;
631 if (Expr->evaluateAsAbsolute(EvalValue))
632 return MCConstantExpr::create(EvalValue, Ctx);
633 }
634
635 switch (Expr->getKind()) {
636 default:
637 return Expr;
639 const MCBinaryExpr *BExpr = cast<MCBinaryExpr>(Expr);
640 const MCExpr *LHS = BExpr->getLHS();
641 const MCExpr *RHS = BExpr->getRHS();
642
643 switch (BExpr->getOpcode()) {
644 default:
645 return Expr;
647 if (ValueCheckKnownBits(KBM[RHS], 0))
648 return tryFoldHelper(LHS, KBM, Ctx);
649 break;
650 }
653 if (ValueCheckKnownBits(KBM[LHS], 0))
654 return tryFoldHelper(RHS, KBM, Ctx);
655 if (ValueCheckKnownBits(KBM[RHS], 0))
656 return tryFoldHelper(LHS, KBM, Ctx);
657 break;
658 }
660 if (ValueCheckKnownBits(KBM[LHS], 1))
661 return tryFoldHelper(RHS, KBM, Ctx);
662 if (ValueCheckKnownBits(KBM[RHS], 1))
663 return tryFoldHelper(LHS, KBM, Ctx);
664 break;
665 }
669 if (ValueCheckKnownBits(KBM[RHS], 0))
670 return tryFoldHelper(LHS, KBM, Ctx);
671 if (ValueCheckKnownBits(KBM[LHS], 0))
672 return MCConstantExpr::create(0, Ctx);
673 break;
674 }
676 if (ValueCheckKnownBits(KBM[LHS], 0) || ValueCheckKnownBits(KBM[RHS], 0))
677 return MCConstantExpr::create(0, Ctx);
678 break;
679 }
680 }
681 const MCExpr *NewLHS = tryFoldHelper(LHS, KBM, Ctx);
682 const MCExpr *NewRHS = tryFoldHelper(RHS, KBM, Ctx);
683 if (NewLHS != LHS || NewRHS != RHS)
684 return MCBinaryExpr::create(BExpr->getOpcode(), NewLHS, NewRHS, Ctx,
685 BExpr->getLoc());
686 return Expr;
687 }
689 const MCUnaryExpr *UExpr = cast<MCUnaryExpr>(Expr);
690 const MCExpr *SubExpr = UExpr->getSubExpr();
691 const MCExpr *NewSubExpr = tryFoldHelper(SubExpr, KBM, Ctx);
692 if (SubExpr != NewSubExpr)
693 return MCUnaryExpr::create(UExpr->getOpcode(), NewSubExpr, Ctx,
694 UExpr->getLoc());
695 return Expr;
696 }
698 const AMDGPUMCExpr *AGVK = cast<AMDGPUMCExpr>(Expr);
700 bool Changed = false;
701 for (const MCExpr *Arg : AGVK->getArgs()) {
702 const MCExpr *NewArg = tryFoldHelper(Arg, KBM, Ctx);
703 NewArgs.push_back(NewArg);
704 Changed |= Arg != NewArg;
705 }
706 return Changed ? AMDGPUMCExpr::create(AGVK->getKind(), NewArgs, Ctx) : Expr;
707 }
708 }
709 return Expr;
710}
711
713 MCContext &Ctx) {
714 KnownBitsMap KBM;
715 knownBitsMapHelper(Expr, KBM);
716 const MCExpr *NewExpr = tryFoldHelper(Expr, KBM, Ctx);
717
718 return Expr != NewExpr ? NewExpr : Expr;
719}
720
722 const MCAsmInfo *MAI) {
723 int64_t Val;
724 if (Expr->evaluateAsAbsolute(Val)) {
725 OS << Val;
726 return;
727 }
728
729 MAI->printExpr(OS, *Expr);
730}
731
732bool AMDGPU::isLitExpr(const MCExpr *Expr) {
733 const auto *E = dyn_cast<AMDGPUMCExpr>(Expr);
734 return E && (E->getKind() == AMDGPUMCExpr::AGVK_Lit ||
735 E->getKind() == AMDGPUMCExpr::AGVK_Lit64);
736}
737
738int64_t AMDGPU::getLitValue(const MCExpr *Expr) {
739 assert(isLitExpr(Expr));
740 return cast<MCConstantExpr>(cast<AMDGPUMCExpr>(Expr)->getArgs()[0])
741 ->getValue();
742}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
static void targetOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM, unsigned Depth)
static void unaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM, unsigned Depth)
static KnownBits fromOptionalToKnownBits(std::optional< bool > CompareResult)
static void binaryOpKnownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM, unsigned Depth)
static const MCExpr * tryFoldHelper(const MCExpr *Expr, KnownBitsMap &KBM, MCContext &Ctx)
static void knownBitsMapHelper(const MCExpr *Expr, KnownBitsMap &KBM, unsigned Depth=0)
DenseMap< const MCExpr *, KnownBits > KnownBitsMap
AMD GCN specific subclass of TargetSubtarget.
#define op(i)
Value * RHS
Value * LHS
AMDGPU target specific MCExpr operations.
ArrayRef< const MCExpr * > getArgs() const
MCFragment * findAssociatedFragment() const override
void visitUsedExpr(MCStreamer &Streamer) const override
static const AMDGPUMCExpr * createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs, const MCExpr *NumVGPRs, unsigned DynamicVGPRBlockSize, const GCNSubtarget &STM, MCContext &Ctx)
Mimics GCNSubtarget::computeOccupancy for MCExpr.
static const AMDGPUMCExpr * createTotalNumVGPR(const MCExpr *NumAGPR, const MCExpr *NumVGPR, MCContext &Ctx)
static const AMDGPUMCExpr * createLit(LitModifier Lit, int64_t Value, MCContext &Ctx)
static const AMDGPUMCExpr * create(VariantKind Kind, ArrayRef< const MCExpr * > Args, MCContext &Ctx)
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm) const override
static const AMDGPUMCExpr * createExtraSGPRs(const MCExpr *VCCUsed, const MCExpr *FlatScrUsed, bool XNACKUsed, MCContext &Ctx)
Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed are unresolvable but neede...
const MCExpr * getSubExpr(size_t Index) const
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override
VariantKind getKind() const
static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *E)
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1562
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:161
Generation getGeneration() const
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:64
void printExpr(raw_ostream &, const MCExpr &) const
Binary assembler expressions.
Definition MCExpr.h:299
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition MCExpr.h:446
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition MCExpr.h:449
Opcode getOpcode() const
Get the kind of this binary expression.
Definition MCExpr.h:443
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:201
@ Div
Signed division.
Definition MCExpr.h:304
@ Shl
Shift left.
Definition MCExpr.h:321
@ AShr
Arithmetic shift right.
Definition MCExpr.h:322
@ LShr
Logical shift right.
Definition MCExpr.h:323
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:308
@ EQ
Equality comparison.
Definition MCExpr.h:305
@ Sub
Subtraction.
Definition MCExpr.h:324
@ Mul
Multiplication.
Definition MCExpr.h:317
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
Definition MCExpr.h:306
@ Mod
Signed remainder.
Definition MCExpr.h:316
@ And
Bitwise and.
Definition MCExpr.h:303
@ Or
Bitwise or.
Definition MCExpr.h:319
@ Xor
Bitwise exclusive or.
Definition MCExpr.h:325
@ LAnd
Logical and.
Definition MCExpr.h:310
@ LOr
Logical or.
Definition MCExpr.h:311
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:312
@ Add
Addition.
Definition MCExpr.h:302
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
Definition MCExpr.h:314
@ NE
Inequality comparison.
Definition MCExpr.h:318
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData=0)
Definition MCExpr.h:67
@ Unary
Unary expressions.
Definition MCExpr.h:44
@ Constant
Constant expressions.
Definition MCExpr.h:42
@ SymbolRef
References to labels and assigned expressions.
Definition MCExpr.h:43
@ Target
Target specific expression.
Definition MCExpr.h:46
@ Specifier
Expression with a relocation specifier.
Definition MCExpr.h:45
@ Binary
Binary expressions.
Definition MCExpr.h:41
LLVM_ABI bool evaluateAsAbsolute(int64_t &Res) const
Try to evaluate the expression to an absolute value.
Definition MCExpr.cpp:238
LLVM_ABI MCFragment * findAssociatedFragment() const
Find the "associated section" for this expression, which is currently defined as the absolute section...
Definition MCExpr.cpp:692
ExprKind getKind() const
Definition MCExpr.h:85
SMLoc getLoc() const
Definition MCExpr.h:86
Streaming machine code generation interface.
Definition MCStreamer.h:220
void visitUsedExpr(const MCExpr &Expr)
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
const MCSymbol & getSymbol() const
Definition MCExpr.h:227
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
Unary assembler expressions.
Definition MCExpr.h:243
Opcode getOpcode() const
Get the kind of this unary expression.
Definition MCExpr.h:286
static LLVM_ABI const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:207
@ Minus
Unary minus.
Definition MCExpr.h:247
@ Plus
Unary plus.
Definition MCExpr.h:249
@ Not
Bitwise negation.
Definition MCExpr.h:248
const MCExpr * getSubExpr() const
Get the child of this unary expression.
Definition MCExpr.h:289
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
Definition MCValue.h:56
int64_t getConstant() const
Definition MCValue.h:44
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Definition MCValue.h:54
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char NumVGPRs[]
Key for Kernel::CodeProps::Metadata::mNumVGPRs.
constexpr char NumSGPRs[]
Key for Kernel::CodeProps::Metadata::mNumSGPRs.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned getTotalNumVGPRs(const MCSubtargetInfo *STI)
unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo *STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize)
unsigned getMaxWavesPerEU(const MCSubtargetInfo *STI)
unsigned getNumExtraSGPRs(const MCSubtargetInfo *STI, bool VCCUsed, bool FlatScrUsed, bool XNACKUsed)
unsigned getVGPRAllocGranule(const MCSubtargetInfo *STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves, AMDGPUSubtarget::Generation Gen)
LLVM_READONLY bool isLitExpr(const MCExpr *Expr)
void printAMDGPUMCExpr(const MCExpr *Expr, raw_ostream &OS, const MCAsmInfo *MAI)
bool isGFX90A(const MCSubtargetInfo &STI)
LLVM_READONLY int64_t getLitValue(const MCExpr *Expr)
const MCExpr * foldAMDGPUMCExpr(const MCExpr *Expr, MCContext &Ctx)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
auto uninitialized_copy(R &&Src, IterTy Dst)
Definition STLExtras.h:2033
@ Success
The lock was released successfully.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:301
static LLVM_ABI std::optional< bool > eq(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_EQ result.
void makeNonNegative()
Make this value non-negative.
Definition KnownBits.h:124
static LLVM_ABI KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for ashr(LHS, RHS).
static LLVM_ABI std::optional< bool > ne(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_NE result.
void makeNegative()
Make this value negative.
Definition KnownBits.h:119
static LLVM_ABI std::optional< bool > sge(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_SGE result.
static LLVM_ABI KnownBits umax(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for umax(LHS, RHS).
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
Definition KnownBits.h:172
bool isConstant() const
Returns true if we know the value of all bits.
Definition KnownBits.h:54
static LLVM_ABI KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS, bool ShAmtNonZero=false, bool Exact=false)
Compute known bits for lshr(LHS, RHS).
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
Definition KnownBits.h:347
static LLVM_ABI KnownBits srem(const KnownBits &LHS, const KnownBits &RHS)
Compute known bits for srem(LHS, RHS).
static LLVM_ABI std::optional< bool > slt(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_SLT result.
static LLVM_ABI KnownBits sdiv(const KnownBits &LHS, const KnownBits &RHS, bool Exact=false)
Compute known bits for sdiv(LHS, RHS).
static KnownBits sub(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from subtraction of LHS and RHS.
Definition KnownBits.h:353
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
static LLVM_ABI std::optional< bool > sle(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_SLE result.
static LLVM_ABI std::optional< bool > sgt(const KnownBits &LHS, const KnownBits &RHS)
Determine if these known bits always give the same ICMP_SGT result.
static LLVM_ABI KnownBits shl(const KnownBits &LHS, const KnownBits &RHS, bool NUW=false, bool NSW=false, bool ShAmtNonZero=false)
Compute known bits for shl(LHS, RHS).
const APInt & getConstant() const
Returns the value when all bits have a known value.
Definition KnownBits.h:60