Skip to content

Commit cbf08d0

Browse files
committed
[mlir] Fix LLVM intrinsic convesion generator for overloadable types.
Summary: If an intrinsic has overloadable types like llvm_anyint_ty or llvm_anyfloat_ty then to getDeclaration() we need to pass a list of the types that are "undefined" essentially concretizing them. This patch add support for deriving such types from the MLIR op that has been matched. Reviewers: andydavis1, ftynse, nicolasvasilache, antiagainst Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, arpith-jacob, mgester, lucyrfox, liufengdb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D72974
1 parent 2d77e0b commit cbf08d0

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

mlir/test/mlir-tblgen/llvm-intrinsics.td

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66
// includes from the main file to avoid unnecessary dependencies and decrease
77
// the test cost. The command-line flags further ensure a specific intrinsic is
88
// processed and we only check the ouptut below.
9+
// We also verify emission of type specialization for overloadable intrinsics.
910
//
1011
// RUN: cat %S/../../../llvm/include/llvm/IR/Intrinsics.td \
1112
// RUN: | grep -v "llvm/IR/Intrinsics" \
12-
// RUN: | mlir-tblgen -gen-llvmir-intrinsics -I %S/../../../llvm/include/ --llvmir-intrinsics-filter=vastart \
13+
// RUN: | mlir-tblgen -gen-llvmir-intrinsics -I %S/../../../llvm/include/ --llvmir-intrinsics-filter=is_constant \
1314
// RUN: | FileCheck %s
1415

15-
// CHECK-LABEL: def LLVM_vastart
16+
// CHECK-LABEL: def LLVM_is_constant
1617
// CHECK: LLVM_Op<"intr
1718
// CHECK: Arguments<(ins
1819
// CHECK: Results<(outs
20+
// CHECK: llvm::Function *fn = llvm::Intrinsic::getDeclaration(
21+
// CHECK: module, llvm::Intrinsic::is_constant, {
22+
// CHECK: opInst.getOperand(0).getType().cast<LLVM::LLVMType>().getUnderlyingType(),
23+
// CHECK: });
1924

2025
//---------------------------------------------------------------------------//
2126

mlir/tools/mlir-tblgen/LLVMIRIntrinsicGen.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
#include "mlir/Support/STLExtras.h"
1515
#include "mlir/TableGen/GenInfo.h"
1616

17+
#include "llvm/ADT/SmallBitVector.h"
1718
#include "llvm/Support/CommandLine.h"
19+
#include "llvm/Support/MachineValueType.h"
1820
#include "llvm/Support/PrettyStackTrace.h"
1921
#include "llvm/Support/Signals.h"
2022
#include "llvm/TableGen/Error.h"
@@ -30,6 +32,38 @@ static llvm::cl::opt<std::string>
3032
"substring in their record name"),
3133
llvm::cl::cat(IntrinsicGenCat));
3234

35+
// Used to represent the indices of overloadable operands/results.
36+
using IndicesTy = llvm::SmallBitVector;
37+
38+
/// Return a CodeGen value type entry from a type record.
39+
static llvm::MVT::SimpleValueType getValueType(const llvm::Record *rec) {
40+
return (llvm::MVT::SimpleValueType)rec->getValueAsDef("VT")->getValueAsInt(
41+
"Value");
42+
}
43+
44+
/// Return the indices of the definitions in a list of definitions that
45+
/// represent overloadable types
46+
static IndicesTy getOverloadableTypeIdxs(const llvm::Record &record,
47+
const char *listName) {
48+
auto results = record.getValueAsListOfDefs(listName);
49+
IndicesTy overloadedOps(results.size());
50+
for (auto r : llvm::enumerate(results)) {
51+
llvm::MVT::SimpleValueType vt = getValueType(r.value());
52+
switch (vt) {
53+
case llvm::MVT::iAny:
54+
case llvm::MVT::fAny:
55+
case llvm::MVT::Any:
56+
case llvm::MVT::iPTRAny:
57+
case llvm::MVT::vAny:
58+
overloadedOps.set(r.index());
59+
break;
60+
default:
61+
continue;
62+
}
63+
}
64+
return overloadedOps;
65+
}
66+
3367
namespace {
3468
/// A wrapper for LLVM's Tablegen class `Intrinsic` that provides accessors to
3569
/// the fields of the record.
@@ -108,6 +142,14 @@ class LLVMIntrinsic {
108142
return false;
109143
}
110144

145+
IndicesTy getOverloadableOperandsIdxs() const {
146+
return getOverloadableTypeIdxs(record, fieldOperands);
147+
}
148+
149+
IndicesTy getOverloadableResultsIdxs() const {
150+
return getOverloadableTypeIdxs(record, fieldResults);
151+
}
152+
111153
private:
112154
/// Names of the fields in the Intrinsic LLVM Tablegen class.
113155
const char *fieldName = "LLVMName";
@@ -122,10 +164,23 @@ class LLVMIntrinsic {
122164
/// Emits C++ code constructing an LLVM IR intrinsic given the generated MLIR
123165
/// operation. In LLVM IR, intrinsics are constructed as function calls.
124166
static void emitBuilder(const LLVMIntrinsic &intr, llvm::raw_ostream &os) {
167+
auto overloadedRes = intr.getOverloadableResultsIdxs();
168+
auto overloadedOps = intr.getOverloadableOperandsIdxs();
125169
os << " llvm::Module *module = builder.GetInsertBlock()->getModule();\n";
126170
os << " llvm::Function *fn = llvm::Intrinsic::getDeclaration(\n";
127171
os << " module, llvm::Intrinsic::" << intr.getProperRecordName()
128-
<< ");\n";
172+
<< ", {";
173+
for (unsigned idx : overloadedRes.set_bits()) {
174+
os << "\n opInst.getResult(" << idx << ").getType()"
175+
<< ".cast<LLVM::LLVMType>().getUnderlyingType(),";
176+
}
177+
for (unsigned idx : overloadedOps.set_bits()) {
178+
os << "\n opInst.getOperand(" << idx << ").getType()"
179+
<< ".cast<LLVM::LLVMType>().getUnderlyingType(),";
180+
}
181+
if (overloadedRes.any() || overloadedOps.any())
182+
os << "\n ";
183+
os << "});\n";
129184
os << " auto operands = llvm::to_vector<8, Value *>(\n";
130185
os << " opInst.operand_begin(), opInst.operand_end());\n";
131186
os << " " << (intr.getNumResults() > 0 ? "$res = " : "")

0 commit comments

Comments
 (0)