LLVM_ScalarOrVectorOf<LLVM_AnyFloat>, "fneg", "FNeg">;
// Memory-related operations.
-def LLVM_AllocaOp : LLVM_Op<"alloca",
+def LLVM_AllocaOp : LLVM_Op<"alloca",
[DeclareOpInterfaceMethods<PromotableAllocationOpInterface>,
DeclareOpInterfaceMethods<DestructurableAllocationOpInterface>]>,
LLVM_MemOpPatterns {
DefaultValuedAttr<
AtomicOrdering, "AtomicOrdering::not_atomic">:$ordering,
OptionalAttr<StrAttr>:$syncscope);
- // Append the aliasing related attributes define in LLVM_MemAccessOpBase.
+ // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
let arguments = !con(args, aliasAttrs);
let results = (outs LLVM_LoadableType:$res);
string llvmInstName = "Load";
DefaultValuedAttr<
AtomicOrdering, "AtomicOrdering::not_atomic">:$ordering,
OptionalAttr<StrAttr>:$syncscope);
- // Append the aliasing related attributes define in LLVM_MemAccessOpBase.
+ // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
let arguments = !con(args, aliasAttrs);
string llvmInstName = "Store";
let description = [{
// FIXME: Add a type attribute that carries the LLVM function type to support
// indirect calls to variadic functions. The type attribute is necessary to
// distinguish normal and variadic arguments.
-def LLVM_CallOp : LLVM_Op<"call",
- [DeclareOpInterfaceMethods<FastmathFlagsInterface>,
- DeclareOpInterfaceMethods<CallOpInterface>,
- DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
+def LLVM_CallOp : LLVM_MemAccessOpBase<"call",
+ [DeclareOpInterfaceMethods<FastmathFlagsInterface>,
+ DeclareOpInterfaceMethods<CallOpInterface>,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = "Call to an LLVM function.";
let description = [{
In LLVM IR, functions may return either 0 or 1 value. LLVM IR dialect
```
}];
- let arguments = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
- Variadic<LLVM_Type>,
- DefaultValuedAttr<LLVM_FastmathFlagsAttr,
- "{}">:$fastmathFlags,
- OptionalAttr<ElementsAttr>:$branch_weights);
+ dag args = (ins OptionalAttr<FlatSymbolRefAttr>:$callee,
+ Variadic<LLVM_Type>,
+ DefaultValuedAttr<LLVM_FastmathFlagsAttr,
+ "{}">:$fastmathFlags,
+ OptionalAttr<ElementsAttr>:$branch_weights);
+ // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
+ let arguments = !con(args, aliasAttrs);
let results = (outs Optional<LLVM_Type>:$result);
-
let builders = [
OpBuilder<(ins "LLVMFuncOp":$func, "ValueRange":$args)>,
OpBuilder<(ins "TypeRange":$results, "StringAttr":$callee,
OpBuilder<(ins "TypeRange":$results, "StringRef":$callee,
CArg<"ValueRange", "{}">:$args)>
];
-
let hasCustomAssemblyFormat = 1;
}
OptionalAttr<StrAttr>:$syncscope,
OptionalAttr<I64Attr>:$alignment,
UnitAttr:$volatile_);
- // Append the aliasing related attributes define in LLVM_MemAccessOpBase.
+ // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
let arguments = !con(args, aliasAttrs);
let results = (outs LLVM_AtomicRMWType:$res);
let assemblyFormat = [{
OptionalAttr<I64Attr>:$alignment,
UnitAttr:$weak,
UnitAttr:$volatile_);
- // Append the aliasing related attributes define in LLVM_MemAccessOpBase.
+ // Append the aliasing related attributes defined in LLVM_MemAccessOpBase.
let arguments = !con(args, aliasAttrs);
let results = (outs LLVM_AnyStruct:$res);
let assemblyFormat = [{
void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
StringAttr callee, ValueRange args) {
- build(builder, state, results, SymbolRefAttr::get(callee), args, nullptr,
- nullptr);
+ build(builder, state, results, SymbolRefAttr::get(callee), args);
}
void CallOp::build(OpBuilder &builder, OperationState &state, TypeRange results,
FlatSymbolRefAttr callee, ValueRange args) {
- build(builder, state, results, callee, args, nullptr, nullptr);
+ build(builder, state, results, callee, args, /*fastmathFlags=*/nullptr,
+ /*branch_weights=*/nullptr,
+ /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
+ /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
}
void CallOp::build(OpBuilder &builder, OperationState &state, LLVMFuncOp func,
Type resultType = func.getFunctionType().getReturnType();
if (!llvm::isa<LLVM::LLVMVoidType>(resultType))
results.push_back(resultType);
- build(builder, state, results, SymbolRefAttr::get(func), args, nullptr,
- nullptr);
+ build(builder, state, results, SymbolRefAttr::get(func), args,
+ /*fastmathFlags=*/nullptr,
+ /*branch_weights=*/nullptr,
+ /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
+ /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr);
}
CallInterfaceCallable CallOp::getCallableForCallee() {
convertBranchWeights(callOp.getBranchWeights(), moduleTranslation);
if (branchWeights)
call->setMetadata(llvm::LLVMContext::MD_prof, branchWeights);
+ moduleTranslation.setAccessGroupsMetadata(callOp, call);
+ moduleTranslation.setAliasScopeMetadata(callOp, call);
+ moduleTranslation.setTBAAMetadata(callOp, call);
// If the called function has a result, remap the corresponding value. Note
// that LLVM IR dialect CallOp has either 0 or 1 result.
if (opInst.getNumResults() != 0) {
call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg1, i32 4, i1 false), !alias.scope !2
; CHECK: "llvm.intr.memset"{{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !alias.scope !2
+ ; CHECK: llvm.call{{.*}}alias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+ call void @foo(ptr %arg1), !alias.scope !2
+ ; CHECK: llvm.call{{.*}}noalias_scopes = [@__llvm_global_metadata::@[[$SCOPE]]]
+ call void @foo(ptr %arg1), !noalias !2
ret void
}
declare void @llvm.experimental.noalias.scope.decl(metadata)
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
+declare void @foo(ptr %arg1)
!0 = distinct !{!0, !"The domain"}
!1 = !{!1, !0}
call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg1, i32 4, i1 false), !llvm.access.group !0
; CHECK: "llvm.intr.memset"{{.*}}access_groups =
call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !llvm.access.group !0
+ ; CHECK: llvm.call{{.*}}access_groups =
+ call void @foo(ptr %arg1), !llvm.access.group !0
ret void
}
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
+declare void @foo(ptr %arg1)
!0 = !{!1, !2}
!1 = distinct !{}
call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg1, i32 4, i1 false), !tbaa !0
; CHECK: "llvm.intr.memset"{{.*}}tbaa =
call void @llvm.memset.p0.i32(ptr %arg1, i8 42, i32 4, i1 false), !tbaa !0
+ ; CHECK: llvm.call{{.*}}tbaa =
+ call void @foo(ptr %arg1), !tbaa !0
ret void
}
declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg)
declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg)
+declare void @foo(ptr %arg1)
!0 = !{!1, !1, i64 0}
!1 = !{!"scalar type", !2, i64 0}
// -----
+llvm.func @foo(%arg0: !llvm.ptr)
+
// CHECK-LABEL: aliasScope
llvm.func @aliasScope(%arg1 : !llvm.ptr) {
%0 = llvm.mlir.constant(0 : i32) : i32
"llvm.intr.memcpy"(%arg1, %arg1, %0, %4) {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr, !llvm.ptr, i32, i1) -> ()
// CHECK: llvm.memset{{.*}}, !noalias ![[SCOPES3]]
"llvm.intr.memset"(%arg1, %5, %0, %4) {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr, i8, i32, i1) -> ()
+ // CHECK: call void @foo({{.*}} !alias.scope ![[SCOPES3]]
+ llvm.call @foo(%arg1) {alias_scopes = [@metadata::@scope3]} : (!llvm.ptr) -> ()
+ // CHECK: call void @foo({{.*}} !noalias ![[SCOPES3]]
+ llvm.call @foo(%arg1) {noalias_scopes = [@metadata::@scope3]} : (!llvm.ptr) -> ()
llvm.return
}
// -----
+llvm.func @foo(%arg0: i32)
+
// CHECK-LABEL: @loopOptions
llvm.func @loopOptions(%arg1 : i32, %arg2 : i32) {
%0 = llvm.mlir.constant(0 : i32) : i32
"llvm.intr.memcpy"(%4, %4, %0, %8) {access_groups = [@metadata::@group1, @metadata::@group2]} : (!llvm.ptr, !llvm.ptr, i32, i1) -> ()
// CHECK: llvm.memset{{.*}} !llvm.access.group ![[ACCESS_GROUPS_NODE]]
"llvm.intr.memset"(%4, %9, %0, %8) {access_groups = [@metadata::@group1, @metadata::@group2]} : (!llvm.ptr, i8, i32, i1) -> ()
+ // CHECK: call void @foo({{.*}} !llvm.access.group ![[ACCESS_GROUPS_NODE]]
+ llvm.call @foo(%arg1) {access_groups = [@metadata::@group1, @metadata::@group2]} : (i32) -> ()
// CHECK: br label {{.*}} !llvm.loop ![[LOOP_NODE]]
llvm.br ^bb3(%3 : i32) {loop_annotation = #llvm.loop_annotation<
licm = <disable = true>,
llvm.tbaa_type_desc @tbaa_type_desc_6 {id = "agg1_t", members = {<@tbaa_type_desc_5, 0>, <@tbaa_type_desc_5, 4>}}
llvm.tbaa_tag @tbaa_tag_7 {access_type = @tbaa_type_desc_5, base_type = @tbaa_type_desc_6, offset = 0 : i64}
}
+ llvm.func @foo(%arg0: !llvm.ptr)
llvm.func @tbaa2(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
%0 = llvm.mlir.constant(0 : i32) : i32
%1 = llvm.mlir.constant(1 : i32) : i32
"llvm.intr.memcpy"(%arg1, %arg1, %0, %8) {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr, !llvm.ptr, i32, i1) -> ()
// CHECK: llvm.memset{{.*}} !tbaa ![[STAG]]
"llvm.intr.memset"(%arg1, %9, %0, %8) {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr, i8, i32, i1) -> ()
+ // CHECK: call void @foo({{.*}} !tbaa ![[STAG]]
+ llvm.call @foo(%arg1) {tbaa = [@__tbaa::@tbaa_tag_7]} : (!llvm.ptr) -> ()
llvm.return
}
}