1//===- AMDGPUMCExpr.h - AMDGPU specific MC expression classes ---*- C++ -*-===//
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#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H
10#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/MC/MCExpr.h"
14
15namespace llvm {
16
17class Function;
18
19enum class LitModifier { None, Lit, Lit64 };
20
21/// AMDGPU target specific MCExpr operations.
22///
23/// Takes in a minimum of 1 argument to be used with an operation. The supported
24/// operations are:
25/// - (bitwise) or
26/// - max
27/// - min
28///
29/// \note If the 'or'/'max'/'min' operations are provided only a single
30/// argument, the operation will act as a no-op and simply resolve as the
31/// provided argument.
32///
33class AMDGPUMCExpr : public MCTargetExpr {
34public:
35 enum VariantKind {
36 AGVK_None,
37 AGVK_Or,
38 AGVK_Max,
39 AGVK_ExtraSGPRs,
40 AGVK_TotalNumVGPRs,
41 AGVK_AlignTo,
42 AGVK_Occupancy,
43 AGVK_InstPrefSize,
44 AGVK_Lit,
45 AGVK_Lit64,
46 AGVK_Min,
47 };
48
49 // Relocation specifiers.
50 enum Specifier {
51 S_None,
52 S_GOTPCREL, // symbol@gotpcrel
53 S_GOTPCREL32_LO, // symbol@gotpcrel32@lo
54 S_GOTPCREL32_HI, // symbol@gotpcrel32@hi
55 S_REL32_LO, // symbol@rel32@lo
56 S_REL32_HI, // symbol@rel32@hi
57 S_REL64, // symbol@rel64
58 S_ABS32_LO, // symbol@abs32@lo
59 S_ABS32_HI, // symbol@abs32@hi
60 S_ABS64, // symbol@abs64
61 };
62
63private:
64 VariantKind Kind;
65 MCContext &Ctx;
66 const MCExpr **RawArgs;
67 ArrayRef<const MCExpr *> Args;
68
69 AMDGPUMCExpr(VariantKind Kind, ArrayRef<const MCExpr *> Args, MCContext &Ctx);
70 ~AMDGPUMCExpr() override;
71
72 bool evaluateExtraSGPRs(MCValue &Res, const MCAssembler *Asm) const;
73 bool evaluateTotalNumVGPR(MCValue &Res, const MCAssembler *Asm) const;
74 bool evaluateAlignTo(MCValue &Res, const MCAssembler *Asm) const;
75 bool evaluateOccupancy(MCValue &Res, const MCAssembler *Asm) const;
76 bool evaluateInstPrefSize(MCValue &Res, const MCAssembler *Asm) const;
77
78public:
79 static const AMDGPUMCExpr *
80 create(VariantKind Kind, ArrayRef<const MCExpr *> Args, MCContext &Ctx);
81
82 /// \returns the required operand count for \p Kind, or 0 for the variadic
83 /// kinds (or/max/min). Used at parse time and by the create() assert.
84 static unsigned getNumExpectedArgs(VariantKind Kind);
85
86 static const AMDGPUMCExpr *createOr(ArrayRef<const MCExpr *> Args,
87 MCContext &Ctx) {
88 return create(Kind: VariantKind::AGVK_Or, Args, Ctx);
89 }
90
91 static const AMDGPUMCExpr *createMax(ArrayRef<const MCExpr *> Args,
92 MCContext &Ctx) {
93 return create(Kind: VariantKind::AGVK_Max, Args, Ctx);
94 }
95 static const AMDGPUMCExpr *createMin(ArrayRef<const MCExpr *> Args,
96 MCContext &Ctx) {
97 return create(Kind: VariantKind::AGVK_Min, Args, Ctx);
98 }
99
100 static const AMDGPUMCExpr *createExtraSGPRs(const MCExpr *VCCUsed,
101 const MCExpr *FlatScrUsed,
102 bool XNACKUsed, MCContext &Ctx);
103
104 static const AMDGPUMCExpr *createTotalNumVGPR(const MCExpr *NumAGPR,
105 const MCExpr *NumVGPR,
106 MCContext &Ctx);
107
108 static const AMDGPUMCExpr *
109 createAlignTo(const MCExpr *Value, const MCExpr *Align, MCContext &Ctx) {
110 return create(Kind: VariantKind::AGVK_AlignTo, Args: {Value, Align}, Ctx);
111 }
112
113 /// Create an expression for instruction prefetch size computation:
114 /// min(divideCeil(CodeSizeBytes, CacheLineSize), (1 << FieldWidth) - 1)
115 /// FieldWidth and CacheLineSize are derived from the subtarget.
116 static const AMDGPUMCExpr *createInstPrefSize(const MCExpr *CodeSizeBytes,
117 MCContext &Ctx);
118
119 static const AMDGPUMCExpr *createLit(LitModifier Lit, int64_t Value,
120 MCContext &Ctx);
121
122 ArrayRef<const MCExpr *> getArgs() const { return Args; }
123 VariantKind getKind() const { return Kind; }
124 MCContext &getCtx() const { return Ctx; }
125 const MCExpr *getSubExpr(size_t Index) const;
126
127 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
128 bool evaluateAsRelocatableImpl(MCValue &Res,
129 const MCAssembler *Asm) const override;
130 void visitUsedExpr(MCStreamer &Streamer) const override;
131 MCFragment *findAssociatedFragment() const override;
132
133 static bool classof(const MCExpr *E) {
134 return E->getKind() == MCExpr::Target;
135 }
136 static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *E);
137};
138
139namespace AMDGPU {
140// Tries to leverage KnownBits for MCExprs to reduce and limit any composed
141// MCExprs printing. E.g., for an expression such as
142// ((unevaluatable_sym | 1) & 1) won't evaluate due to unevaluatable_sym and
143// would verbosely print the full expression; however, KnownBits should deduce
144// the value to be 1. Particularly useful for AMDGPU metadata MCExprs.
145void printAMDGPUMCExpr(const MCExpr *Expr, raw_ostream &OS,
146 const MCAsmInfo *MAI);
147
148const MCExpr *foldAMDGPUMCExpr(const MCExpr *Expr, MCContext &Ctx);
149
150static inline AMDGPUMCExpr::Specifier getSpecifier(const MCSymbolRefExpr *SRE) {
151 return AMDGPUMCExpr::Specifier(SRE->getKind());
152}
153
154LLVM_READONLY bool isLitExpr(const MCExpr *Expr);
155
156LLVM_READONLY int64_t getLitValue(const MCExpr *Expr);
157
158LLVM_READONLY AMDGPUMCExpr::VariantKind getExprKind(const MCExpr *Expr);
159
160} // end namespace AMDGPU
161} // end namespace llvm
162
163#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H
164