Skip to content

Commit bec2d10

Browse files
authored
[AMDGPU] Add AMDGPU specific variadic operation MCExprs (#82022)
Adds AMDGPU specific variadic MCExpr operations 'max' and 'or'.
1 parent 012d217 commit bec2d10

File tree

7 files changed

+426
-0
lines changed

7 files changed

+426
-0
lines changed

llvm/docs/AMDGPUUsage.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,6 +1534,25 @@ The AMDGPU backend supports the following calling conventions:
15341534

15351535
=============================== ==========================================================
15361536

1537+
AMDGPU MCExpr
1538+
-------------
1539+
1540+
As part of the AMDGPU MC layer, AMDGPU provides the following target specific
1541+
``MCExpr``\s.
1542+
1543+
.. table:: AMDGPU MCExpr types:
1544+
:name: amdgpu-mcexpr-table
1545+
1546+
=================== ================= ========================================================
1547+
MCExpr Operands Return value
1548+
=================== ================= ========================================================
1549+
``max(arg, ...)`` 1 or more Variadic signed operation that returns the maximum
1550+
value of all its arguments.
1551+
1552+
``or(arg, ...)`` 1 or more Variadic signed operation that returns the bitwise-or
1553+
result of all its arguments.
1554+
1555+
=================== ================= ========================================================
15371556

15381557
.. _amdgpu-elf-code-object:
15391558

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "AMDKernelCodeT.h"
10+
#include "MCTargetDesc/AMDGPUMCExpr.h"
1011
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
1112
#include "MCTargetDesc/AMDGPUTargetStreamer.h"
1213
#include "SIDefines.h"
@@ -1816,6 +1817,7 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
18161817

18171818
public:
18181819
void onBeginOfFile() override;
1820+
bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
18191821

18201822
ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK);
18211823

@@ -8277,6 +8279,59 @@ void AMDGPUAsmParser::onBeginOfFile() {
82778279
getTargetStreamer().EmitDirectiveAMDGCNTarget();
82788280
}
82798281

8282+
/// Parse AMDGPU specific expressions.
8283+
///
8284+
/// expr ::= or(expr, ...) |
8285+
/// max(expr, ...)
8286+
///
8287+
bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
8288+
using AGVK = AMDGPUVariadicMCExpr::VariadicKind;
8289+
8290+
if (isToken(AsmToken::Identifier)) {
8291+
StringRef TokenId = getTokenStr();
8292+
AGVK VK = StringSwitch<AGVK>(TokenId)
8293+
.Case("max", AGVK::AGVK_Max)
8294+
.Case("or", AGVK::AGVK_Or)
8295+
.Default(AGVK::AGVK_None);
8296+
8297+
if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) {
8298+
SmallVector<const MCExpr *, 4> Exprs;
8299+
uint64_t CommaCount = 0;
8300+
lex(); // Eat 'max'/'or'
8301+
lex(); // Eat '('
8302+
while (true) {
8303+
if (trySkipToken(AsmToken::RParen)) {
8304+
if (Exprs.empty()) {
8305+
Error(getToken().getLoc(),
8306+
"empty " + Twine(TokenId) + " expression");
8307+
return true;
8308+
}
8309+
if (CommaCount + 1 != Exprs.size()) {
8310+
Error(getToken().getLoc(),
8311+
"mismatch of commas in " + Twine(TokenId) + " expression");
8312+
return true;
8313+
}
8314+
Res = AMDGPUVariadicMCExpr::create(VK, Exprs, getContext());
8315+
return false;
8316+
}
8317+
const MCExpr *Expr;
8318+
if (getParser().parseExpression(Expr, EndLoc))
8319+
return true;
8320+
Exprs.push_back(Expr);
8321+
bool LastTokenWasComma = trySkipToken(AsmToken::Comma);
8322+
if (LastTokenWasComma)
8323+
CommaCount++;
8324+
if (!LastTokenWasComma && !isToken(AsmToken::RParen)) {
8325+
Error(getToken().getLoc(),
8326+
"unexpected token in " + Twine(TokenId) + " expression");
8327+
return true;
8328+
}
8329+
}
8330+
}
8331+
}
8332+
return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
8333+
}
8334+
82808335
ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) {
82818336
StringRef Name = getTokenStr();
82828337
if (Name == "mul") {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 "llvm/MC/MCContext.h"
11+
#include "llvm/MC/MCStreamer.h"
12+
#include "llvm/MC/MCSymbol.h"
13+
#include "llvm/MC/MCValue.h"
14+
#include "llvm/Support/Allocator.h"
15+
#include "llvm/Support/raw_ostream.h"
16+
#include <optional>
17+
18+
using namespace llvm;
19+
20+
const AMDGPUVariadicMCExpr *
21+
AMDGPUVariadicMCExpr::create(VariadicKind Kind, ArrayRef<const MCExpr *> Args,
22+
MCContext &Ctx) {
23+
return new (Ctx) AMDGPUVariadicMCExpr(Kind, Args);
24+
}
25+
26+
const MCExpr *AMDGPUVariadicMCExpr::getSubExpr(size_t Index) const {
27+
assert(Index < Args.size() &&
28+
"Indexing out of bounds AMDGPUVariadicMCExpr sub-expr");
29+
return Args[Index];
30+
}
31+
32+
void AMDGPUVariadicMCExpr::printImpl(raw_ostream &OS,
33+
const MCAsmInfo *MAI) const {
34+
switch (Kind) {
35+
default:
36+
llvm_unreachable("Unknown AMDGPUVariadicMCExpr kind.");
37+
case AGVK_Or:
38+
OS << "or(";
39+
break;
40+
case AGVK_Max:
41+
OS << "max(";
42+
break;
43+
}
44+
for (auto It = Args.begin(); It != Args.end(); ++It) {
45+
(*It)->print(OS, MAI, /*InParens=*/false);
46+
if ((It + 1) != Args.end())
47+
OS << ", ";
48+
}
49+
OS << ')';
50+
}
51+
52+
static int64_t op(AMDGPUVariadicMCExpr::VariadicKind Kind, int64_t Arg1,
53+
int64_t Arg2) {
54+
switch (Kind) {
55+
default:
56+
llvm_unreachable("Unknown AMDGPUVariadicMCExpr kind.");
57+
case AMDGPUVariadicMCExpr::AGVK_Max:
58+
return std::max(Arg1, Arg2);
59+
case AMDGPUVariadicMCExpr::AGVK_Or:
60+
return Arg1 | Arg2;
61+
}
62+
}
63+
64+
bool AMDGPUVariadicMCExpr::evaluateAsRelocatableImpl(
65+
MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const {
66+
std::optional<int64_t> Total;
67+
68+
for (const MCExpr *Arg : Args) {
69+
MCValue ArgRes;
70+
if (!Arg->evaluateAsRelocatable(ArgRes, Layout, Fixup) ||
71+
!ArgRes.isAbsolute())
72+
return false;
73+
74+
if (!Total.has_value())
75+
Total = ArgRes.getConstant();
76+
Total = op(Kind, *Total, ArgRes.getConstant());
77+
}
78+
79+
Res = MCValue::get(*Total);
80+
return true;
81+
}
82+
83+
void AMDGPUVariadicMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
84+
for (const MCExpr *Arg : Args)
85+
Streamer.visitUsedExpr(*Arg);
86+
}
87+
88+
MCFragment *AMDGPUVariadicMCExpr::findAssociatedFragment() const {
89+
for (const MCExpr *Arg : Args) {
90+
if (Arg->findAssociatedFragment())
91+
return Arg->findAssociatedFragment();
92+
}
93+
return nullptr;
94+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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/ADT/SmallVector.h"
14+
#include "llvm/MC/MCExpr.h"
15+
16+
namespace llvm {
17+
18+
/// AMDGPU target specific variadic MCExpr operations.
19+
///
20+
/// Takes in a minimum of 1 argument to be used with an operation. The supported
21+
/// operations are:
22+
/// - (bitwise) or
23+
/// - max
24+
///
25+
/// \note If the 'or'/'max' operations are provided only a single argument, the
26+
/// operation will act as a no-op and simply resolve as the provided argument.
27+
///
28+
class AMDGPUVariadicMCExpr : public MCTargetExpr {
29+
public:
30+
enum VariadicKind { AGVK_None, AGVK_Or, AGVK_Max };
31+
32+
private:
33+
VariadicKind Kind;
34+
SmallVector<const MCExpr *, 2> Args;
35+
36+
AMDGPUVariadicMCExpr(VariadicKind Kind, ArrayRef<const MCExpr *> Args)
37+
: Kind(Kind), Args(Args) {
38+
assert(Args.size() >= 1 && "Needs a minimum of one expression.");
39+
assert(Kind != AGVK_None &&
40+
"Cannot construct AMDGPUVariadicMCExpr of kind none.");
41+
}
42+
43+
public:
44+
static const AMDGPUVariadicMCExpr *
45+
create(VariadicKind Kind, ArrayRef<const MCExpr *> Args, MCContext &Ctx);
46+
47+
static const AMDGPUVariadicMCExpr *createOr(ArrayRef<const MCExpr *> Args,
48+
MCContext &Ctx) {
49+
return create(VariadicKind::AGVK_Or, Args, Ctx);
50+
}
51+
52+
static const AMDGPUVariadicMCExpr *createMax(ArrayRef<const MCExpr *> Args,
53+
MCContext &Ctx) {
54+
return create(VariadicKind::AGVK_Max, Args, Ctx);
55+
}
56+
57+
VariadicKind getKind() const { return Kind; }
58+
const MCExpr *getSubExpr(size_t Index) const;
59+
60+
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
61+
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
62+
const MCFixup *Fixup) const override;
63+
void visitUsedExpr(MCStreamer &Streamer) const override;
64+
MCFragment *findAssociatedFragment() const override;
65+
void fixELFSymbolsInTLSFixups(MCAssembler &) const override{};
66+
67+
static bool classof(const MCExpr *E) {
68+
return E->getKind() == MCExpr::Target;
69+
}
70+
};
71+
72+
} // end namespace llvm
73+
74+
#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H

llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMAMDGPUDesc
55
AMDGPUInstPrinter.cpp
66
AMDGPUMCAsmInfo.cpp
77
AMDGPUMCCodeEmitter.cpp
8+
AMDGPUMCExpr.cpp
89
AMDGPUMCTargetDesc.cpp
910
AMDGPUTargetStreamer.cpp
1011
R600InstPrinter.cpp

0 commit comments

Comments
 (0)