Skip to content

Commit e6ce2c0

Browse files
[mlir][LLVM] Add support for operand_attrs to InlineAsmOp
This revision adds enough support to allow InlineAsmOp to work properly with indirect memory constraints "*m". These require an explicit "elementtype" TypeAttr on the operands to pass LLVM verification and need to be provided. Reviewed By: bkramer Differential Revision: https://reviews.llvm.org/D118006
1 parent ff64327 commit e6ce2c0

File tree

4 files changed

+85
-4
lines changed

4 files changed

+85
-4
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1934,17 +1934,25 @@ def LLVM_InlineAsmOp : LLVM_Op<"inline_asm", []> {
19341934
UnitAttr:$has_side_effects,
19351935
UnitAttr:$is_align_stack,
19361936
OptionalAttr<
1937-
DefaultValuedAttr<AsmATTOrIntel, "AsmDialect::AD_ATT">>:$asm_dialect);
1937+
DefaultValuedAttr<AsmATTOrIntel, "AsmDialect::AD_ATT">>:$asm_dialect,
1938+
OptionalAttr<ArrayAttr>:$operand_attrs);
19381939

19391940
let results = (outs Optional<LLVM_Type>:$res);
19401941

19411942
let assemblyFormat = [{
19421943
(`has_side_effects` $has_side_effects^)?
19431944
(`is_align_stack` $is_align_stack^)?
19441945
(`asm_dialect` `=` $asm_dialect^)?
1946+
(`operand_attrs` `=` $operand_attrs^)?
19451947
attr-dict
19461948
$asm_string `,` $constraints
19471949
operands `:` functional-type(operands, results)
19481950
}];
1951+
1952+
let extraClassDeclaration = [{
1953+
static StringRef getElementTypeAttrName() {
1954+
return "elementtype";
1955+
}
1956+
}];
19491957
}
19501958
#endif // LLVMIR_OPS

mlir/lib/Dialect/X86Vector/Transforms/AVXTranspose.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ Value mlir::x86vector::avx2::inline_asm::mm256BlendPsAsm(
3737
SmallVector<Value> asmVals{v1, v2};
3838
auto asmStr = llvm::formatv(asmTp, llvm::format_hex(mask, /*width=*/2)).str();
3939
auto asmOp = b.create<LLVM::InlineAsmOp>(
40-
v1.getType(), asmVals, asmStr, asmCstr, false, false, asmDialectAttr);
40+
v1.getType(), /*operands=*/asmVals, /*asm_string=*/asmStr,
41+
/*constraints=*/asmCstr, /*has_side_effects=*/false,
42+
/*is_align_stack=*/false, /*asm_dialect=*/asmDialectAttr,
43+
/*operand_attrs=*/ArrayAttr());
4144
return asmOp.getResult(0);
4245
}
4346

mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,32 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
330330
inlineAsmOp.getConstraints(),
331331
inlineAsmOp.getHasSideEffects(),
332332
inlineAsmOp.getIsAlignStack());
333-
llvm::Value *result = builder.CreateCall(
333+
llvm::CallInst *inst = builder.CreateCall(
334334
inlineAsmInst,
335335
moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
336+
if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
337+
llvm::AttributeList attrList;
338+
for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
339+
Attribute attr = it.value();
340+
if (!attr)
341+
continue;
342+
DictionaryAttr dAttr = attr.cast<DictionaryAttr>();
343+
TypeAttr tAttr =
344+
dAttr.get(InlineAsmOp::getElementTypeAttrName()).cast<TypeAttr>();
345+
llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
346+
llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
347+
b.addTypeAttr(llvm::Attribute::ElementType, ty);
348+
// shift to account for the returned value (this is always 1 aggregate
349+
// value in LLVM).
350+
int shift = (opInst.getNumResults() > 0) ? 1 : 0;
351+
attrList = attrList.addAttributesAtIndex(
352+
moduleTranslation.getLLVMContext(), it.index() + shift, b);
353+
}
354+
inst->setAttributes(attrList);
355+
}
356+
336357
if (opInst.getNumResults() != 0)
337-
moduleTranslation.mapValue(opInst.getResult(0), result);
358+
moduleTranslation.mapValue(opInst.getResult(0), inst);
338359
return success();
339360
}
340361

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: mlir-opt %s -convert-linalg-to-loops -convert-vector-to-scf='full-unroll=true' -lower-affine -convert-scf-to-std -convert-vector-to-llvm -convert-memref-to-llvm -convert-std-to-llvm='use-bare-ptr-memref-call-conv=1' -convert-arith-to-llvm -reconcile-unrealized-casts |\
2+
// RUN: mlir-translate --mlir-to-llvmir |\
3+
// RUN: %lli --entry-function=entry --mattr="avx512f" | \
4+
// RUN: FileCheck %s
5+
6+
module {
7+
8+
// printf format string "%i\n", char by char: % i \n 0
9+
llvm.mlir.global private @pct_i_newline(dense<[37, 105, 10, 0]> : tensor<4xi8>)
10+
: !llvm.array<4xi8>
11+
// an array of 16 i32 of values [0..15]
12+
llvm.mlir.global private @const16(
13+
dense<[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]> : tensor<16 x i32>)
14+
: !llvm.array<16 x i32>
15+
16+
// declare void @printf(i8*, ...)
17+
llvm.func @printf(!llvm.ptr<i8>, ...)
18+
19+
llvm.func @entry() {
20+
%c0 = llvm.mlir.constant(0 : index) : i64
21+
22+
%1 = llvm.mlir.addressof @const16 : !llvm.ptr<array<16 x i32>>
23+
%ptr = llvm.getelementptr %1[%c0, %c0]
24+
: (!llvm.ptr<array<16 x i32>>, i64, i64) -> !llvm.ptr<i32>
25+
%ptr2 = llvm.bitcast %ptr : !llvm.ptr<i32> to !llvm.ptr<vector<16xi32>>
26+
// operand_attrs of *m operands need to be piped through to LLVM for
27+
// verification to pass.
28+
%v = llvm.inline_asm
29+
asm_dialect = intel
30+
operand_attrs = [{ elementtype = vector<16xi32> }]
31+
"vmovdqu32 $0, $1", "=x,*m" %ptr2
32+
: (!llvm.ptr<vector<16xi32>>) -> vector<16xi32>
33+
34+
%2 = llvm.mlir.addressof @pct_i_newline : !llvm.ptr<array<4xi8>>
35+
%ptrfmt = llvm.getelementptr %2[%c0, %c0]
36+
: (!llvm.ptr<array<4xi8>>, i64, i64) -> !llvm.ptr<i8>
37+
38+
// CHECK: 0
39+
%v0 = vector.extract %v[0]: vector<16xi32>
40+
llvm.call @printf(%ptrfmt, %v0) : (!llvm.ptr<i8>, i32) -> ()
41+
42+
// CHECK: 9
43+
%v9 = vector.extract %v[9]: vector<16xi32>
44+
llvm.call @printf(%ptrfmt, %v9) : (!llvm.ptr<i8>, i32) -> ()
45+
46+
llvm.return
47+
}
48+
}
49+

0 commit comments

Comments
 (0)