[flang-commits] [flang] [flang] Added noalias attribute to function arguments. (PR #140803)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Tue May 20 14:13:47 PDT 2025
https://github.com/vzakhari created https://github.com/llvm/llvm-project/pull/140803
This helps to disambiguate accesses in the caller and the callee
after LLVM inlining in some apps. I did not see any performance
changes, but this is one step towards enabling other optimizations
in the apps that I am looking at.
The definition of llvm.noalias says:
```
... indicates that memory locations accessed via pointer values based on the argument or return value are not also accessed, during the execution of the function, via pointer values not based on the argument or return value. This guarantee only holds for memory locations that are modified, by any means, during the execution of the function.
```
I believe this exactly matches Fortran rules for the dummy arguments
that are modified during their subprogram execution.
I also set llvm.noalias and llvm.nocapture on the !fir.box<> arguments,
because the corresponding descriptors cannot be captured and cannot
alias anything (not based on them) during the execution of the subprogram.
>From 8ecc5a67289cf29d78634ded24a450eb301cf237 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Mon, 19 May 2025 17:14:19 -0700
Subject: [PATCH 1/2] [flang] Added noalias attribute to function arguments.
This helps to disambiguate accesses in the caller and the callee
after LLVM inlining in some apps. I did not see any performance
changes, but this is one step towards enabling other optimizations
in the apps that I am looking at.
The definition of llvm.noalias says:
```
... indicates that memory locations accessed via pointer values based on the argument or return value are not also accessed, during the execution of the function, via pointer values not based on the argument or return value. This guarantee only holds for memory locations that are modified, by any means, during the execution of the function.
```
I believe this exactly matches Fortran rules for the dummy arguments
that are modified during their subprogram execution.
I also set llvm.noalias and llvm.nocapture on the !fir.box<> arguments,
because the corresponding descriptors cannot be captured and cannot
alias anything (not based on them) during the execution of the subprogram.
---
.../flang/Optimizer/Transforms/Passes.td | 6 +
flang/lib/Optimizer/Passes/Pipelines.cpp | 6 +-
.../lib/Optimizer/Transforms/FunctionAttr.cpp | 29 +++--
flang/test/Fir/array-coor.fir | 2 +-
flang/test/Fir/arrayset.fir | 2 +-
flang/test/Fir/arrexp.fir | 18 +--
flang/test/Fir/box-offset-codegen.fir | 8 +-
flang/test/Fir/box-typecode.fir | 2 +-
flang/test/Fir/box.fir | 18 +--
flang/test/Fir/boxproc.fir | 4 +-
flang/test/Fir/commute.fir | 2 +-
flang/test/Fir/coordinateof.fir | 2 +-
flang/test/Fir/embox.fir | 8 +-
flang/test/Fir/field-index.fir | 4 +-
.../Fir/ignore-missing-type-descriptor.fir | 2 +-
flang/test/Fir/polymorphic.fir | 2 +-
flang/test/Fir/rebox.fir | 12 +-
.../test/Fir/struct-passing-x86-64-byval.fir | 48 ++++----
.../Fir/target-rewrite-complex-10-x86.fir | 2 +-
flang/test/Fir/target.fir | 8 +-
flang/test/Fir/tbaa-codegen.fir | 2 +-
flang/test/Fir/tbaa-codegen2.fir | 2 +-
flang/test/Integration/OpenMP/copyprivate.f90 | 34 +++---
flang/test/Integration/debug-local-var-2.f90 | 4 +-
flang/test/Integration/unroll-loops.f90 | 2 +-
flang/test/Lower/HLFIR/unroll-loops.fir | 2 +-
flang/test/Lower/forall/character-1.f90 | 2 +-
.../constant-argument-globalisation.fir | 4 +-
.../Transforms/function-attrs-noalias.fir | 113 ++++++++++++++++++
flang/test/Transforms/function-attrs.fir | 2 +-
30 files changed, 240 insertions(+), 112 deletions(-)
create mode 100644 flang/test/Transforms/function-attrs-noalias.fir
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td
index c0d88a8e19f80..e1497aeb3aa36 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -418,6 +418,12 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> {
"Set the unsafe-fp-math attribute on functions in the module.">,
Option<"tuneCPU", "tune-cpu", "std::string", /*default=*/"",
"Set the tune-cpu attribute on functions in the module.">,
+ Option<"setNoCapture", "set-nocapture", "bool", /*default=*/"false",
+ "Set LLVM nocapture attribute on function arguments, "
+ "if possible">,
+ Option<"setNoAlias", "set-noalias", "bool", /*default=*/"false",
+ "Set LLVM noalias attribute on function arguments, "
+ "if possible">,
];
}
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 77751908e35be..378913fcb1329 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -350,11 +350,15 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
else
framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::None;
+ bool setNoCapture = false, setNoAlias = false;
+ if (config.OptLevel.isOptimizingForSpeed())
+ setNoCapture = setNoAlias = true;
+
pm.addPass(fir::createFunctionAttr(
{framePointerKind, config.InstrumentFunctionEntry,
config.InstrumentFunctionExit, config.NoInfsFPMath, config.NoNaNsFPMath,
config.ApproxFuncFPMath, config.NoSignedZerosFPMath, config.UnsafeFPMath,
- ""}));
+ /*tuneCPU=*/"", setNoCapture, setNoAlias}));
if (config.EnableOpenMP) {
pm.addNestedPass<mlir::func::FuncOp>(
diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
index 43e4c1a7af3cd..c8cdba0d6f9c4 100644
--- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
+++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
@@ -27,17 +27,8 @@ namespace {
class FunctionAttrPass : public fir::impl::FunctionAttrBase<FunctionAttrPass> {
public:
- FunctionAttrPass(const fir::FunctionAttrOptions &options) {
- instrumentFunctionEntry = options.instrumentFunctionEntry;
- instrumentFunctionExit = options.instrumentFunctionExit;
- framePointerKind = options.framePointerKind;
- noInfsFPMath = options.noInfsFPMath;
- noNaNsFPMath = options.noNaNsFPMath;
- approxFuncFPMath = options.approxFuncFPMath;
- noSignedZerosFPMath = options.noSignedZerosFPMath;
- unsafeFPMath = options.unsafeFPMath;
- }
- FunctionAttrPass() {}
+ FunctionAttrPass(const fir::FunctionAttrOptions &options) : Base{options} {}
+ FunctionAttrPass() = default;
void runOnOperation() override;
};
@@ -56,14 +47,28 @@ void FunctionAttrPass::runOnOperation() {
if ((isFromModule || !func.isDeclaration()) &&
!fir::hasBindcAttr(func.getOperation())) {
llvm::StringRef nocapture = mlir::LLVM::LLVMDialect::getNoCaptureAttrName();
+ llvm::StringRef noalias = mlir::LLVM::LLVMDialect::getNoAliasAttrName();
mlir::UnitAttr unitAttr = mlir::UnitAttr::get(func.getContext());
for (auto [index, argType] : llvm::enumerate(func.getArgumentTypes())) {
+ bool isNoCapture = false;
+ bool isNoAlias = false;
if (mlir::isa<fir::ReferenceType>(argType) &&
!func.getArgAttr(index, fir::getTargetAttrName()) &&
!func.getArgAttr(index, fir::getAsynchronousAttrName()) &&
- !func.getArgAttr(index, fir::getVolatileAttrName()))
+ !func.getArgAttr(index, fir::getVolatileAttrName())) {
+ isNoCapture = true;
+ isNoAlias = !fir::isPointerType(argType);
+ } else if (mlir::isa<fir::BaseBoxType>(argType)) {
+ // !fir.box arguments will be passed as descriptor pointers
+ // at LLVM IR dialect level - they cannot be captured,
+ // and cannot alias with anything within the function.
+ isNoCapture = isNoAlias = true;
+ }
+ if (isNoCapture && setNoCapture)
func.setArgAttr(index, nocapture, unitAttr);
+ if (isNoAlias && setNoAlias)
+ func.setArgAttr(index, noalias, unitAttr);
}
}
diff --git a/flang/test/Fir/array-coor.fir b/flang/test/Fir/array-coor.fir
index a765670d20b28..2caa727a10c50 100644
--- a/flang/test/Fir/array-coor.fir
+++ b/flang/test/Fir/array-coor.fir
@@ -33,7 +33,7 @@ func.func @test_array_coor_box_component_slice(%arg0: !fir.box<!fir.array<2x!fir
func.func private @take_int(%arg0: !fir.ref<i32>) -> ()
// CHECK-LABEL: define void @test_array_coor_box_component_slice(
-// CHECK-SAME: ptr %[[VAL_0:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[VAL_0:.*]])
// CHECK: %[[VAL_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[VAL_0]], i32 0, i32 7, i32 0, i32 2
// CHECK: %[[VAL_2:.*]] = load i64, ptr %[[VAL_1]]
// CHECK: %[[VAL_3:.*]] = mul nsw i64 1, %[[VAL_2]]
diff --git a/flang/test/Fir/arrayset.fir b/flang/test/Fir/arrayset.fir
index dab939aba1702..cb26971cb962d 100644
--- a/flang/test/Fir/arrayset.fir
+++ b/flang/test/Fir/arrayset.fir
@@ -1,7 +1,7 @@
// RUN: tco %s | FileCheck %s
// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s
-// CHECK-LABEL: define void @x(ptr captures(none) %0)
+// CHECK-LABEL: define void @x(
func.func @x(%arr : !fir.ref<!fir.array<10xf32>>) {
%1 = arith.constant 0 : index
%2 = arith.constant 9 : index
diff --git a/flang/test/Fir/arrexp.fir b/flang/test/Fir/arrexp.fir
index 924c1fab8d84b..6c7f71f6f1f9c 100644
--- a/flang/test/Fir/arrexp.fir
+++ b/flang/test/Fir/arrexp.fir
@@ -1,7 +1,7 @@
// RUN: tco %s | FileCheck %s
// CHECK-LABEL: define void @f1
-// CHECK: (ptr captures(none) %[[A:[^,]*]], {{.*}}, float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:[^,]*]], {{.*}}, float %[[F:.*]])
func.func @f1(%a : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : index, %p : index, %f : f32) {
%c1 = arith.constant 1 : index
%s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shapeshift<2>
@@ -23,7 +23,7 @@ func.func @f1(%a : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : i
}
// CHECK-LABEL: define void @f2
-// CHECK: (ptr captures(none) %[[A:[^,]*]], {{.*}}, float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:[^,]*]], {{.*}}, float %[[F:.*]])
func.func @f2(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : index, %p : index, %f : f32) {
%c1 = arith.constant 1 : index
%s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shapeshift<2>
@@ -47,7 +47,7 @@ func.func @f2(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
}
// CHECK-LABEL: define void @f3
-// CHECK: (ptr captures(none) %[[A:[^,]*]], {{.*}}, float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:[^,]*]], {{.*}}, float %[[F:.*]])
func.func @f3(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : index, %p : index, %f : f32) {
%c1 = arith.constant 1 : index
%s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shapeshift<2>
@@ -72,7 +72,7 @@ func.func @f3(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
}
// CHECK-LABEL: define void @f4
-// CHECK: (ptr captures(none) %[[A:[^,]*]], {{.*}}, float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:[^,]*]], {{.*}}, float %[[F:.*]])
func.func @f4(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : index, %p : index, %f : f32) {
%c1 = arith.constant 1 : index
%s = fir.shape_shift %o, %n, %p, %m : (index, index, index, index) -> !fir.shapeshift<2>
@@ -102,7 +102,7 @@ func.func @f4(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
// `a = b + f`, with and v assumed shapes.
// Tests that the stride from the descriptor is used.
// CHECK-LABEL: define void @f5
-// CHECK: (ptr %[[A:.*]], ptr %[[B:.*]], float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:.*]], ptr {{[^%]*}}%[[B:.*]], float %[[F:.*]])
func.func @f5(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: !fir.box<!fir.array<?xf32>>, %arg2: f32) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
@@ -135,7 +135,7 @@ func.func @f5(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: !fir.box<!fir.array<?xf
// contiguous array (e.g. `a(2:10:1) = a(1:9:1) + f`, with a assumed shape).
// Test that a temp is created.
// CHECK-LABEL: define void @f6
-// CHECK: (ptr %[[A:[^,]*]], float %[[F:.*]])
+// CHECK: (ptr {{[^%]*}}%[[A:[^,]*]], float %[[F:.*]])
func.func @f6(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: f32) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
@@ -165,7 +165,7 @@ func.func @f6(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: f32) {
// Non contiguous array with lower bounds (x = y(100), with y(4:))
// Test array_coor offset computation.
// CHECK-LABEL: define void @f7(
-// CHECK: ptr captures(none) %[[X:[^,]*]], ptr %[[Y:.*]])
+// CHECK: ptr {{[^%]*}}%[[X:[^,]*]], ptr {{[^%]*}}%[[Y:.*]])
func.func @f7(%arg0: !fir.ref<f32>, %arg1: !fir.box<!fir.array<?xf32>>) {
%c4 = arith.constant 4 : index
%c100 = arith.constant 100 : index
@@ -181,7 +181,7 @@ func.func @f7(%arg0: !fir.ref<f32>, %arg1: !fir.box<!fir.array<?xf32>>) {
// Test A(:, :)%x reference codegen with A constant shape.
// CHECK-LABEL: define void @f8(
-// CHECK-SAME: ptr captures(none) %[[A:.*]], i32 %[[I:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[A:.*]], i32 %[[I:.*]])
func.func @f8(%a : !fir.ref<!fir.array<2x2x!fir.type<t{i:i32}>>>, %i : i32) {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index
@@ -198,7 +198,7 @@ func.func @f8(%a : !fir.ref<!fir.array<2x2x!fir.type<t{i:i32}>>>, %i : i32) {
// Test casts in in array_coor offset computation when type parameters are not i64
// CHECK-LABEL: define ptr @f9(
-// CHECK-SAME: i32 %[[I:.*]], i64 %{{.*}}, i64 %{{.*}}, ptr captures(none) %[[C:.*]])
+// CHECK-SAME: i32 %[[I:.*]], i64 %{{.*}}, i64 %{{.*}}, ptr {{[^%]*}}%[[C:.*]])
func.func @f9(%i: i32, %e : i64, %j: i64, %c: !fir.ref<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.ref<!fir.char<1,?>> {
%s = fir.shape %e, %e : (i64, i64) -> !fir.shape<2>
// CHECK: %[[CAST:.*]] = sext i32 %[[I]] to i64
diff --git a/flang/test/Fir/box-offset-codegen.fir b/flang/test/Fir/box-offset-codegen.fir
index 15c9a11e5aefe..11d5750ffc385 100644
--- a/flang/test/Fir/box-offset-codegen.fir
+++ b/flang/test/Fir/box-offset-codegen.fir
@@ -7,7 +7,7 @@ func.func @scalar_addr(%scalar : !fir.ref<!fir.box<!fir.type<t>>>) -> !fir.llvm_
return %addr : !fir.llvm_ptr<!fir.ref<!fir.type<t>>>
}
// CHECK-LABEL: define ptr @scalar_addr(
-// CHECK-SAME: ptr captures(none) %[[BOX:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[BOX]], i32 0, i32 0
// CHECK: ret ptr %[[VAL_0]]
@@ -16,7 +16,7 @@ func.func @scalar_tdesc(%scalar : !fir.ref<!fir.box<!fir.type<t>>>) -> !fir.llvm
return %tdesc : !fir.llvm_ptr<!fir.tdesc<!fir.type<t>>>
}
// CHECK-LABEL: define ptr @scalar_tdesc(
-// CHECK-SAME: ptr captures(none) %[[BOX:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[BOX]], i32 0, i32 7
// CHECK: ret ptr %[[VAL_0]]
@@ -25,7 +25,7 @@ func.func @array_addr(%array : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.ty
return %addr : !fir.llvm_ptr<!fir.ptr<!fir.array<?x!fir.type<t>>>>
}
// CHECK-LABEL: define ptr @array_addr(
-// CHECK-SAME: ptr captures(none) %[[BOX:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[BOX]], i32 0, i32 0
// CHECK: ret ptr %[[VAL_0]]
@@ -34,6 +34,6 @@ func.func @array_tdesc(%array : !fir.ref<!fir.class<!fir.ptr<!fir.array<?x!fir.t
return %tdesc : !fir.llvm_ptr<!fir.tdesc<!fir.type<t>>>
}
// CHECK-LABEL: define ptr @array_tdesc(
-// CHECK-SAME: ptr captures(none) %[[BOX:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]]){{.*}}{
// CHECK: %[[VAL_0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[BOX]], i32 0, i32 8
// CHECK: ret ptr %[[VAL_0]]
diff --git a/flang/test/Fir/box-typecode.fir b/flang/test/Fir/box-typecode.fir
index 766c5165b947c..a8d43eba39889 100644
--- a/flang/test/Fir/box-typecode.fir
+++ b/flang/test/Fir/box-typecode.fir
@@ -6,7 +6,7 @@ func.func @test_box_typecode(%a: !fir.class<none>) -> i32 {
}
// CHECK-LABEL: @test_box_typecode(
-// CHECK-SAME: ptr %[[BOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[BOX:.*]])
// CHECK: %[[GEP:.*]] = getelementptr { ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}} }, ptr %[[BOX]], i32 0, i32 4
// CHECK: %[[TYPE_CODE:.*]] = load i8, ptr %[[GEP]]
// CHECK: %[[TYPE_CODE_CONV:.*]] = sext i8 %[[TYPE_CODE]] to i32
diff --git a/flang/test/Fir/box.fir b/flang/test/Fir/box.fir
index 5e931a2e0d9aa..c0cf3d8375983 100644
--- a/flang/test/Fir/box.fir
+++ b/flang/test/Fir/box.fir
@@ -24,7 +24,7 @@ func.func private @g(%b : !fir.box<f32>)
func.func private @ga(%b : !fir.box<!fir.array<?xf32>>)
// CHECK-LABEL: define void @f
-// CHECK: (ptr captures(none) %[[ARG:.*]])
+// CHECK: (ptr {{[^%]*}}%[[ARG:.*]])
func.func @f(%a : !fir.ref<f32>) {
// CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }
// CHECK: %[[INS0:.*]] = insertvalue {{.*}} { ptr undef, i64 4, i32 20240719, i8 0, i8 27, i8 0, i8 0 }, ptr %[[ARG]], 0
@@ -38,7 +38,7 @@ func.func @f(%a : !fir.ref<f32>) {
}
// CHECK-LABEL: define void @fa
-// CHECK: (ptr captures(none) %[[ARG:.*]])
+// CHECK: (ptr {{[^%]*}}%[[ARG:.*]])
func.func @fa(%a : !fir.ref<!fir.array<100xf32>>) {
%c = fir.convert %a : (!fir.ref<!fir.array<100xf32>>) -> !fir.ref<!fir.array<?xf32>>
%c1 = arith.constant 1 : index
@@ -54,7 +54,7 @@ func.func @fa(%a : !fir.ref<!fir.array<100xf32>>) {
// Boxing of a scalar character of dynamic length
// CHECK-LABEL: define void @b1(
-// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[res:.*]], ptr {{[^%]*}}%[[arg0:.*]], i64 %[[arg1:.*]])
func.func @b1(%arg0 : !fir.ref<!fir.char<1,?>>, %arg1 : index) -> !fir.box<!fir.char<1,?>> {
// CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }
// CHECK: %[[size:.*]] = mul i64 1, %[[arg1]]
@@ -69,8 +69,8 @@ func.func @b1(%arg0 : !fir.ref<!fir.char<1,?>>, %arg1 : index) -> !fir.box<!fir.
// Boxing of a dynamic array of character with static length (5)
// CHECK-LABEL: define void @b2(
-// CHECK-SAME: ptr captures(none) %[[res]],
-// CHECK-SAME: ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[res]],
+// CHECK-SAME: ptr {{[^%]*}}%[[arg0:.*]], i64 %[[arg1:.*]])
func.func @b2(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,5>>>, %arg1 : index) -> !fir.box<!fir.array<?x!fir.char<1,5>>> {
%1 = fir.shape %arg1 : (index) -> !fir.shape<1>
// CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
@@ -85,7 +85,7 @@ func.func @b2(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,5>>>, %arg1 : index) ->
// Boxing of a dynamic array of character of dynamic length
// CHECK-LABEL: define void @b3(
-// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]], i64 %[[arg2:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[res:.*]], ptr {{[^%]*}}%[[arg0:.*]], i64 %[[arg1:.*]], i64 %[[arg2:.*]])
func.func @b3(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,?>>>, %arg1 : index, %arg2 : index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> {
%1 = fir.shape %arg2 : (index) -> !fir.shape<1>
// CHECK: %[[alloca:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
@@ -103,7 +103,7 @@ func.func @b3(%arg0 : !fir.ref<!fir.array<?x!fir.char<1,?>>>, %arg1 : index, %ar
// Boxing of a static array of character of dynamic length
// CHECK-LABEL: define void @b4(
-// CHECK-SAME: ptr captures(none) %[[res:.*]], ptr captures(none) %[[arg0:.*]], i64 %[[arg1:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[res:.*]], ptr {{[^%]*}}%[[arg0:.*]], i64 %[[arg1:.*]])
func.func @b4(%arg0 : !fir.ref<!fir.array<7x!fir.char<1,?>>>, %arg1 : index) -> !fir.box<!fir.array<7x!fir.char<1,?>>> {
%c_7 = arith.constant 7 : index
%1 = fir.shape %c_7 : (index) -> !fir.shape<1>
@@ -122,7 +122,7 @@ func.func @b4(%arg0 : !fir.ref<!fir.array<7x!fir.char<1,?>>>, %arg1 : index) ->
// Storing a fir.box into a fir.ref<fir.box> (modifying descriptors).
// CHECK-LABEL: define void @b5(
-// CHECK-SAME: ptr captures(none) %[[arg0:.*]], ptr %[[arg1:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[arg0:.*]], ptr {{[^%]*}}%[[arg1:.*]])
func.func @b5(%arg0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, %arg1 : !fir.box<!fir.heap<!fir.array<?x?xf32>>>) {
fir.store %arg1 to %arg0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>
// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %0, ptr %1, i32 72, i1 false)
@@ -132,7 +132,7 @@ func.func @b5(%arg0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf32>>>>, %arg1
func.func private @callee6(!fir.box<none>) -> i32
// CHECK-LABEL: define i32 @box6(
-// CHECK-SAME: ptr captures(none) %[[ARG0:.*]], i64 %[[ARG1:.*]], i64 %[[ARG2:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[ARG0:.*]], i64 %[[ARG1:.*]], i64 %[[ARG2:.*]])
func.func @box6(%0 : !fir.ref<!fir.array<?x?x?x?xf32>>, %1 : index, %2 : index) -> i32 {
%c100 = arith.constant 100 : index
%c50 = arith.constant 50 : index
diff --git a/flang/test/Fir/boxproc.fir b/flang/test/Fir/boxproc.fir
index e99dfd0b92afd..5d82522055adc 100644
--- a/flang/test/Fir/boxproc.fir
+++ b/flang/test/Fir/boxproc.fir
@@ -16,7 +16,7 @@
// CHECK: call void @_QPtest_proc_dummy_other(ptr %[[VAL_6]])
// CHECK-LABEL: define void @_QFtest_proc_dummyPtest_proc_dummy_a(ptr
-// CHECK-SAME: captures(none) %[[VAL_0:.*]], ptr nest captures(none) %[[VAL_1:.*]])
+// CHECK-SAME: {{[^%]*}}%[[VAL_0:.*]], ptr nest {{[^%]*}}%[[VAL_1:.*]])
// CHECK-LABEL: define void @_QPtest_proc_dummy_other(ptr
// CHECK-SAME: %[[VAL_0:.*]])
@@ -92,7 +92,7 @@ func.func @_QPtest_proc_dummy_other(%arg0: !fir.boxproc<() -> ()>) {
// CHECK: call void @llvm.stackrestore.p0(ptr %[[VAL_27]])
// CHECK-LABEL: define { ptr, i64 } @_QFtest_proc_dummy_charPgen_message(ptr
-// CHECK-SAME: captures(none) %[[VAL_0:.*]], i64 %[[VAL_1:.*]], ptr nest captures(none) %[[VAL_2:.*]])
+// CHECK-SAME: {{[^%]*}}%[[VAL_0:.*]], i64 %[[VAL_1:.*]], ptr nest {{[^%]*}}%[[VAL_2:.*]])
// CHECK: %[[VAL_3:.*]] = getelementptr { { ptr, i64 } }, ptr %[[VAL_2]], i32 0, i32 0
// CHECK: %[[VAL_4:.*]] = load { ptr, i64 }, ptr %[[VAL_3]], align 8
// CHECK: %[[VAL_5:.*]] = extractvalue { ptr, i64 } %[[VAL_4]], 0
diff --git a/flang/test/Fir/commute.fir b/flang/test/Fir/commute.fir
index a857ba55b00c5..8713c8ff24e7f 100644
--- a/flang/test/Fir/commute.fir
+++ b/flang/test/Fir/commute.fir
@@ -11,7 +11,7 @@ func.func @f1(%a : i32, %b : i32) -> i32 {
return %3 : i32
}
-// CHECK-LABEL: define i32 @f2(ptr captures(none) %0)
+// CHECK-LABEL: define i32 @f2(ptr {{[^%]*}}%0)
func.func @f2(%a : !fir.ref<i32>) -> i32 {
%1 = fir.load %a : !fir.ref<i32>
// CHECK: %[[r2:.*]] = load
diff --git a/flang/test/Fir/coordinateof.fir b/flang/test/Fir/coordinateof.fir
index 693bdf716ba1d..a01e9e9d1fc40 100644
--- a/flang/test/Fir/coordinateof.fir
+++ b/flang/test/Fir/coordinateof.fir
@@ -62,7 +62,7 @@ func.func @foo5(%box : !fir.box<!fir.ptr<!fir.array<?xi32>>>, %i : index) -> i32
}
// CHECK-LABEL: @foo6
-// CHECK-SAME: (ptr %[[box:.*]], i64 %{{.*}}, ptr captures(none) %{{.*}})
+// CHECK-SAME: (ptr {{[^%]*}}%[[box:.*]], i64 %{{.*}}, ptr {{[^%]*}}%{{.*}})
func.func @foo6(%box : !fir.box<!fir.ptr<!fir.array<?x!fir.char<1>>>>, %i : i64 , %res : !fir.ref<!fir.char<1>>) {
// CHECK: %[[addr_gep:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[box]], i32 0, i32 0
// CHECK: %[[addr:.*]] = load ptr, ptr %[[addr_gep]]
diff --git a/flang/test/Fir/embox.fir b/flang/test/Fir/embox.fir
index 18b5efbc6a0e4..0f304cff2c79e 100644
--- a/flang/test/Fir/embox.fir
+++ b/flang/test/Fir/embox.fir
@@ -2,7 +2,7 @@
// RUN: %flang_fc1 -mmlir -disable-external-name-interop -emit-llvm %s -o -| FileCheck %s
-// CHECK-LABEL: define void @_QPtest_callee(ptr %0)
+// CHECK-LABEL: define void @_QPtest_callee(
func.func @_QPtest_callee(%arg0: !fir.box<!fir.array<?xi32>>) {
return
}
@@ -29,7 +29,7 @@ func.func @_QPtest_slice() {
return
}
-// CHECK-LABEL: define void @_QPtest_dt_callee(ptr %0)
+// CHECK-LABEL: define void @_QPtest_dt_callee(
func.func @_QPtest_dt_callee(%arg0: !fir.box<!fir.array<?xi32>>) {
return
}
@@ -63,7 +63,7 @@ func.func @_QPtest_dt_slice() {
func.func private @takesRank2CharBox(!fir.box<!fir.array<?x?x!fir.char<1,?>>>)
// CHECK-LABEL: define void @emboxSubstring(
-// CHECK-SAME: ptr captures(none) %[[arg0:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[arg0:.*]])
func.func @emboxSubstring(%arg0: !fir.ref<!fir.array<2x3x!fir.char<1,4>>>) {
%c2 = arith.constant 2 : index
%c3 = arith.constant 3 : index
@@ -84,7 +84,7 @@ func.func @emboxSubstring(%arg0: !fir.ref<!fir.array<2x3x!fir.char<1,4>>>) {
func.func private @do_something(!fir.box<!fir.array<?xf32>>) -> ()
// CHECK: define void @fir_dev_issue_1416
-// CHECK-SAME: ptr captures(none) %[[base_addr:.*]], i64 %[[low:.*]], i64 %[[up:.*]], i64 %[[at:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[base_addr:.*]], i64 %[[low:.*]], i64 %[[up:.*]], i64 %[[at:.*]])
func.func @fir_dev_issue_1416(%arg0: !fir.ref<!fir.array<40x?xf32>>, %low: index, %up: index, %at : index) {
// Test fir.embox with a constant interior array shape.
%c1 = arith.constant 1 : index
diff --git a/flang/test/Fir/field-index.fir b/flang/test/Fir/field-index.fir
index 55d173201f29a..19cfd2c04ad99 100644
--- a/flang/test/Fir/field-index.fir
+++ b/flang/test/Fir/field-index.fir
@@ -7,7 +7,7 @@
// CHECK-DAG: %[[c:.*]] = type { float, %[[b]] }
// CHECK-LABEL: @simple_field
-// CHECK-SAME: (ptr captures(none) %[[arg0:.*]])
+// CHECK-SAME: (ptr {{[^%]*}}%[[arg0:.*]])
func.func @simple_field(%arg0: !fir.ref<!fir.type<a{x:f32,i:i32}>>) -> i32 {
// CHECK: %[[GEP:.*]] = getelementptr %a, ptr %[[arg0]], i32 0, i32 1
%2 = fir.coordinate_of %arg0, i : (!fir.ref<!fir.type<a{x:f32,i:i32}>>) -> !fir.ref<i32>
@@ -17,7 +17,7 @@ func.func @simple_field(%arg0: !fir.ref<!fir.type<a{x:f32,i:i32}>>) -> i32 {
}
// CHECK-LABEL: @derived_field
-// CHECK-SAME: (ptr captures(none) %[[arg0:.*]])
+// CHECK-SAME: (ptr {{[^%]*}}%[[arg0:.*]])
func.func @derived_field(%arg0: !fir.ref<!fir.type<c{x:f32,some_b:!fir.type<b{x:f32,i:i32}>}>>) -> i32 {
// CHECK: %[[GEP:.*]] = getelementptr %c, ptr %[[arg0]], i32 0, i32 1, i32 1
%3 = fir.coordinate_of %arg0, some_b, i : (!fir.ref<!fir.type<c{x:f32,some_b:!fir.type<b{x:f32,i:i32}>}>>) -> !fir.ref<i32>
diff --git a/flang/test/Fir/ignore-missing-type-descriptor.fir b/flang/test/Fir/ignore-missing-type-descriptor.fir
index f9dcb7db77afe..d3e6dd166ca45 100644
--- a/flang/test/Fir/ignore-missing-type-descriptor.fir
+++ b/flang/test/Fir/ignore-missing-type-descriptor.fir
@@ -15,7 +15,7 @@ func.func @test_embox(%addr: !fir.ref<!some_freestyle_type>) {
return
}
// CHECK-LABEL: define void @test_embox(
-// CHECK-SAME: ptr captures(none) %[[ADDR:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[ADDR:.*]])
// CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
// CHECK-SAME: { ptr undef, i64 4,
// CHECK-SAME: i32 20240719, i8 0, i8 42, i8 0, i8 1, ptr null, [1 x i64] zeroinitializer },
diff --git a/flang/test/Fir/polymorphic.fir b/flang/test/Fir/polymorphic.fir
index ea1099af6b988..84fa2e950633f 100644
--- a/flang/test/Fir/polymorphic.fir
+++ b/flang/test/Fir/polymorphic.fir
@@ -86,7 +86,7 @@ func.func @_QMunlimitedPsub1(%arg0: !fir.class<!fir.array<?xnone>> {fir.bindc_na
}
// CHECK-LABEL: define void @_QMunlimitedPsub1(
-// CHECK-SAME: ptr %[[ARRAY:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[ARRAY:.*]]){{.*}}{
// CHECK: %[[BOX:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }
// CHECK: %{{.}} = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ARRAY]], i32 0, i32 7, i32 0, i32 2
// CHECK: %[[TYPE_DESC_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ARRAY]], i32 0, i32 8
diff --git a/flang/test/Fir/rebox.fir b/flang/test/Fir/rebox.fir
index 140308be6a814..0c9f6d9bb94ad 100644
--- a/flang/test/Fir/rebox.fir
+++ b/flang/test/Fir/rebox.fir
@@ -9,7 +9,7 @@
func.func private @bar1(!fir.box<!fir.array<?xf32>>)
// CHECK-LABEL: define void @test_rebox_1(
-// CHECK-SAME: ptr %[[INBOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INBOX:.*]])
func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
// CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
%c2 = arith.constant 2 : index
@@ -54,7 +54,7 @@ func.func @test_rebox_1(%arg0: !fir.box<!fir.array<?x?xf32>>) {
func.func private @bar_rebox_test2(!fir.box<!fir.array<?x?x!fir.char<1,?>>>)
// CHECK-LABEL: define void @test_rebox_2(
-// CHECK-SAME: ptr %[[INBOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INBOX:.*]])
func.func @test_rebox_2(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
%c1 = arith.constant 1 : index
%c4 = arith.constant 4 : index
@@ -82,7 +82,7 @@ func.func @test_rebox_2(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
func.func private @bar_rebox_test3(!fir.box<!fir.array<?x?x?xf32>>)
// CHECK-LABEL: define void @test_rebox_3(
-// CHECK-SAME: ptr %[[INBOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INBOX:.*]])
func.func @test_rebox_3(%arg0: !fir.box<!fir.array<?xf32>>) {
// CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] }
%c2 = arith.constant 2 : index
@@ -116,7 +116,7 @@ func.func @test_rebox_3(%arg0: !fir.box<!fir.array<?xf32>>) {
// time constant length.
// CHECK-LABEL: define void @test_rebox_4(
-// CHECK-SAME: ptr %[[INPUT:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INPUT:.*]])
func.func @test_rebox_4(%arg0: !fir.box<!fir.array<?x!fir.char<1,?>>>) {
// CHECK: %[[NEWBOX_STORAGE:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
// CHECK: %[[EXTENT_GEP:.*]] = getelementptr {{{.*}}}, ptr %[[INPUT]], i32 0, i32 7, i32 0, i32 1
@@ -144,7 +144,7 @@ func.func private @bar_test_rebox_4(!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,1
// end subroutine
// CHECK-LABEL: define void @test_cmplx_1(
-// CHECK-SAME: ptr %[[INBOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INBOX:.*]])
func.func @test_cmplx_1(%arg0: !fir.box<!fir.array<?xcomplex<f32>>>) {
// CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
%c1 = arith.constant 1 : index
@@ -184,7 +184,7 @@ func.func @test_cmplx_1(%arg0: !fir.box<!fir.array<?xcomplex<f32>>>) {
// end subroutine
// CHECK-LABEL: define void @test_cmplx_2(
-// CHECK-SAME: ptr %[[INBOX:.*]])
+// CHECK-SAME: ptr {{[^%]*}}%[[INBOX:.*]])
func.func @test_cmplx_2(%arg0: !fir.box<!fir.array<?xcomplex<f32>>>) {
// CHECK: %[[OUTBOX_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }
%c7 = arith.constant 7 : index
diff --git a/flang/test/Fir/struct-passing-x86-64-byval.fir b/flang/test/Fir/struct-passing-x86-64-byval.fir
index 8451c26095226..997d2930f836c 100644
--- a/flang/test/Fir/struct-passing-x86-64-byval.fir
+++ b/flang/test/Fir/struct-passing-x86-64-byval.fir
@@ -80,27 +80,27 @@ func.func @not_enough_int_reg_3(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32,
}
}
-// CHECK: define void @takes_toobig(ptr byval(%toobig) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @takes_toobig_align16(ptr byval(%toobig_align16) align 16 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_int_reg_1b(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_int_reg_2(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_2_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @ftakes_toobig(ptr byval(%ftoobig) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @ftakes_toobig_align16(ptr byval(%ftoobig_align16) align 16 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_sse_reg_1b(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, ptr byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_sse_reg_1c(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, ptr byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr byval(%fits_in_2_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @test_contains_x87(ptr byval(%contains_x87) align 16 captures(none) %{{.*}}) {
-// CHECK: define void @test_contains_complex_x87(ptr byval(%contains_complex_x87) align 16 captures(none) %{{.*}}) {
-// CHECK: define void @test_nested_toobig(ptr byval(%nested_toobig) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @test_badly_aligned(ptr byval(%badly_aligned) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @test_logical_toobig(ptr byval(%logical_too_big) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @l_not_enough_int_reg(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%l_fits_in_2_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @test_complex_toobig(ptr byval(%complex_too_big) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @cplx_not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr byval(%cplx_fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @test_char_to_big(ptr byval(%char_too_big) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @char_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%char_fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @mix_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%mix_in_1_int_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @mix_not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr byval(%mix_in_1_int_reg_1_sse_reg) align 8 captures(none) %{{.*}}) {
-// CHECK: define void @not_enough_int_reg_3(ptr sret({ fp128, fp128 }) align 16 captures(none) %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}})
+// CHECK: define void @takes_toobig(ptr noalias byval(%toobig) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @takes_toobig_align16(ptr noalias byval(%toobig_align16) align 16 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_int_reg_1b(ptr noalias captures(none) %{{.*}}, ptr noalias captures(none) %{{.*}}, ptr noalias captures(none) %{{.*}}, ptr noalias captures(none) %{{.*}}, ptr noalias captures(none) %{{.*}}, ptr noalias captures(none) %{{.*}}, ptr noalias byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_int_reg_2(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%fits_in_2_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @ftakes_toobig(ptr noalias byval(%ftoobig) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @ftakes_toobig_align16(ptr noalias byval(%ftoobig_align16) align 16 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr noalias byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_sse_reg_1b(<2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, <2 x float> %{{.*}}, ptr noalias byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_sse_reg_1c(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, ptr noalias byval(%fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr noalias byval(%fits_in_2_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @test_contains_x87(ptr noalias byval(%contains_x87) align 16 captures(none) %{{.*}}) {
+// CHECK: define void @test_contains_complex_x87(ptr noalias byval(%contains_complex_x87) align 16 captures(none) %{{.*}}) {
+// CHECK: define void @test_nested_toobig(ptr noalias byval(%nested_toobig) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @test_badly_aligned(ptr noalias byval(%badly_aligned) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @test_logical_toobig(ptr noalias byval(%logical_too_big) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @l_not_enough_int_reg(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%l_fits_in_2_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @test_complex_toobig(ptr noalias byval(%complex_too_big) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @cplx_not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr noalias byval(%cplx_fits_in_1_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @test_char_to_big(ptr noalias byval(%char_too_big) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @char_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%char_fits_in_1_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @mix_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%mix_in_1_int_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @mix_not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr noalias byval(%mix_in_1_int_reg_1_sse_reg) align 8 captures(none) %{{.*}}) {
+// CHECK: define void @not_enough_int_reg_3(ptr noalias sret({ fp128, fp128 }) align 16 captures(none) %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr noalias byval(%fits_in_1_int_reg) align 8 captures(none) %{{.*}})
diff --git a/flang/test/Fir/target-rewrite-complex-10-x86.fir b/flang/test/Fir/target-rewrite-complex-10-x86.fir
index 6404b4f766d39..5f917ee42d598 100644
--- a/flang/test/Fir/target-rewrite-complex-10-x86.fir
+++ b/flang/test/Fir/target-rewrite-complex-10-x86.fir
@@ -30,5 +30,5 @@ func.func @takecomplex10(%z: complex<f80>) {
// AMD64: %[[VAL_3:.*]] = fir.alloca complex<f80>
// AMD64: fir.store %[[VAL_2]] to %[[VAL_3]] : !fir.ref<complex<f80>>
-// AMD64_LLVM: define void @takecomplex10(ptr byval({ x86_fp80, x86_fp80 }) align 16 captures(none) %0)
+// AMD64_LLVM: define void @takecomplex10(ptr noalias byval({ x86_fp80, x86_fp80 }) align 16 captures(none) %0)
}
diff --git a/flang/test/Fir/target.fir b/flang/test/Fir/target.fir
index 781d153f525ff..e1190649e0803 100644
--- a/flang/test/Fir/target.fir
+++ b/flang/test/Fir/target.fir
@@ -26,7 +26,7 @@ func.func @gen4() -> complex<f32> {
return %6 : complex<f32>
}
-// I32-LABEL: define void @gen8(ptr sret({ double, double }) align 4 captures(none) %
+// I32-LABEL: define void @gen8(ptr noalias sret({ double, double }) align 4 captures(none) %
// X64-LABEL: define { double, double } @gen8()
// AARCH64-LABEL: define { double, double } @gen8()
// PPC-LABEL: define { double, double } @gen8()
@@ -93,9 +93,9 @@ func.func @call8() {
return
}
-// I32-LABEL: define i64 @char1lensum(ptr captures(none) %0, ptr captures(none) %1, i32 %2, i32 %3)
-// X64-LABEL: define i64 @char1lensum(ptr captures(none) %0, ptr captures(none) %1, i64 %2, i64 %3)
-// PPC-LABEL: define i64 @char1lensum(ptr captures(none) %0, ptr captures(none) %1, i64 %2, i64 %3)
+// I32-LABEL: define i64 @char1lensum(ptr {{[^%]*}}%0, ptr {{[^%]*}}%1, i32 %2, i32 %3)
+// X64-LABEL: define i64 @char1lensum(ptr {{[^%]*}}%0, ptr {{[^%]*}}%1, i64 %2, i64 %3)
+// PPC-LABEL: define i64 @char1lensum(ptr {{[^%]*}}%0, ptr {{[^%]*}}%1, i64 %2, i64 %3)
func.func @char1lensum(%arg0 : !fir.boxchar<1>, %arg1 : !fir.boxchar<1>) -> i64 {
// X64-DAG: %[[p0:.*]] = insertvalue { ptr, i64 } undef, ptr %1, 0
// X64-DAG: = insertvalue { ptr, i64 } %[[p0]], i64 %3, 1
diff --git a/flang/test/Fir/tbaa-codegen.fir b/flang/test/Fir/tbaa-codegen.fir
index 87bb15c0fea6c..b6b0982b3934e 100644
--- a/flang/test/Fir/tbaa-codegen.fir
+++ b/flang/test/Fir/tbaa-codegen.fir
@@ -28,7 +28,7 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
}
// CHECK-LABEL: define void @_QPsimple(
-// CHECK-SAME: ptr %[[ARG0:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[ARG0:.*]]){{.*}}{
// [...]
// load a(2):
// CHECK: %[[VAL20:.*]] = getelementptr i8, ptr %{{.*}}, i64 %{{.*}}
diff --git a/flang/test/Fir/tbaa-codegen2.fir b/flang/test/Fir/tbaa-codegen2.fir
index 8f8b6a29129e7..69b36c2611505 100644
--- a/flang/test/Fir/tbaa-codegen2.fir
+++ b/flang/test/Fir/tbaa-codegen2.fir
@@ -60,7 +60,7 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
}
}
// CHECK-LABEL: define void @_QPfunc(
-// CHECK-SAME: ptr %[[ARG0:.*]]){{.*}}{
+// CHECK-SAME: ptr {{[^%]*}}%[[ARG0:.*]]){{.*}}{
// [...]
// CHECK: %[[VAL5:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[ARG0]], i32 0, i32 7, i32 0, i32 0
// box access:
diff --git a/flang/test/Integration/OpenMP/copyprivate.f90 b/flang/test/Integration/OpenMP/copyprivate.f90
index 3bae003ea8d83..e0e4abe015438 100644
--- a/flang/test/Integration/OpenMP/copyprivate.f90
+++ b/flang/test/Integration/OpenMP/copyprivate.f90
@@ -8,25 +8,25 @@
!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s
-!CHECK-DAG: define internal void @_copy_box_Uxi32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_10xi32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_i64(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_Uxi64(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_f32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_2x3xf32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_z32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_10xz32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_l32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_5xl32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_c8x8(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_10xc8x8(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_c16x5(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_rec__QFtest_typesTdt(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_heap_Uxi32(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
-!CHECK-DAG: define internal void @_copy_box_ptr_Uxc8x9(ptr captures(none) %{{.*}}, ptr captures(none) %{{.*}})
+!CHECK-DAG: define internal void @_copy_box_Uxi32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_10xi32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_i64(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_Uxi64(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_f32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_2x3xf32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_z32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_10xz32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_l32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_5xl32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_c8x8(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_10xc8x8(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_c16x5(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_rec__QFtest_typesTdt(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_heap_Uxi32(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
+!CHECK-DAG: define internal void @_copy_box_ptr_Uxc8x9(ptr {{[^%]*}}%{{.*}}, ptr {{[^%]*}}%{{.*}})
!CHECK-LABEL: define internal void @_copy_i32(
-!CHECK-SAME: ptr captures(none) %[[DST:.*]], ptr captures(none) %[[SRC:.*]]){{.*}} {
+!CHECK-SAME: ptr {{[^%]*}}%[[DST:.*]], ptr {{[^%]*}}%[[SRC:.*]]){{.*}} {
!CHECK-NEXT: %[[SRC_VAL:.*]] = load i32, ptr %[[SRC]]
!CHECK-NEXT: store i32 %[[SRC_VAL]], ptr %[[DST]]
!CHECK-NEXT: ret void
diff --git a/flang/test/Integration/debug-local-var-2.f90 b/flang/test/Integration/debug-local-var-2.f90
index 08aeb0999b01b..468bb0c5a1289 100644
--- a/flang/test/Integration/debug-local-var-2.f90
+++ b/flang/test/Integration/debug-local-var-2.f90
@@ -20,7 +20,7 @@
! BOTH-LABEL: }
! BOTH-LABEL: define {{.*}}i64 @_QFPfn1
-! BOTH-SAME: (ptr captures(none) %[[ARG1:.*]], ptr captures(none) %[[ARG2:.*]], ptr captures(none) %[[ARG3:.*]])
+! BOTH-SAME: (ptr {{[^%]*}}%[[ARG1:.*]], ptr {{[^%]*}}%[[ARG2:.*]], ptr {{[^%]*}}%[[ARG3:.*]])
! RECORDS-DAG: #dbg_declare(ptr %[[ARG1]], ![[A1:.*]], !DIExpression(), !{{.*}})
! RECORDS-DAG: #dbg_declare(ptr %[[ARG2]], ![[B1:.*]], !DIExpression(), !{{.*}})
! RECORDS-DAG: #dbg_declare(ptr %[[ARG3]], ![[C1:.*]], !DIExpression(), !{{.*}})
@@ -29,7 +29,7 @@
! BOTH-LABEL: }
! BOTH-LABEL: define {{.*}}i32 @_QFPfn2
-! BOTH-SAME: (ptr captures(none) %[[FN2ARG1:.*]], ptr captures(none) %[[FN2ARG2:.*]], ptr captures(none) %[[FN2ARG3:.*]])
+! BOTH-SAME: (ptr {{[^%]*}}%[[FN2ARG1:.*]], ptr {{[^%]*}}%[[FN2ARG2:.*]], ptr {{[^%]*}}%[[FN2ARG3:.*]])
! RECORDS-DAG: #dbg_declare(ptr %[[FN2ARG1]], ![[A2:.*]], !DIExpression(), !{{.*}})
! RECORDS-DAG: #dbg_declare(ptr %[[FN2ARG2]], ![[B2:.*]], !DIExpression(), !{{.*}})
! RECORDS-DAG: #dbg_declare(ptr %[[FN2ARG3]], ![[C2:.*]], !DIExpression(), !{{.*}})
diff --git a/flang/test/Integration/unroll-loops.f90 b/flang/test/Integration/unroll-loops.f90
index debe45e0ec359..87ab9efeb703b 100644
--- a/flang/test/Integration/unroll-loops.f90
+++ b/flang/test/Integration/unroll-loops.f90
@@ -13,7 +13,7 @@
! RUN: %if x86-registered-target %{ %{check-nounroll} %}
!
! CHECK-LABEL: @unroll
-! CHECK-SAME: (ptr writeonly captures(none) %[[ARG0:.*]])
+! CHECK-SAME: (ptr {{[^%]*}}%[[ARG0:.*]])
subroutine unroll(a)
integer(kind=8), intent(out) :: a(1000)
integer(kind=8) :: i
diff --git a/flang/test/Lower/HLFIR/unroll-loops.fir b/flang/test/Lower/HLFIR/unroll-loops.fir
index 1321f39677405..89e8ce82d6f3f 100644
--- a/flang/test/Lower/HLFIR/unroll-loops.fir
+++ b/flang/test/Lower/HLFIR/unroll-loops.fir
@@ -11,7 +11,7 @@
// RUN: %if x86-registered-target %{ %{check-nounroll} %}
// CHECK-LABEL: @unroll
-// CHECK-SAME: (ptr writeonly captures(none) %[[ARG0:.*]])
+// CHECK-SAME: (ptr {{[^%]*}}%[[ARG0:.*]])
func.func @unroll(%arg0: !fir.ref<!fir.array<1000 x index>> {fir.bindc_name = "a"}) {
%scope = fir.dummy_scope : !fir.dscope
%c1000 = arith.constant 1000 : index
diff --git a/flang/test/Lower/forall/character-1.f90 b/flang/test/Lower/forall/character-1.f90
index 69064ddfcf0be..1e4bb73350871 100644
--- a/flang/test/Lower/forall/character-1.f90
+++ b/flang/test/Lower/forall/character-1.f90
@@ -22,7 +22,7 @@ end subroutine sub
end program test
! CHECK-LABEL: define internal void @_QFPsub(
-! CHECK-SAME: ptr %[[arg:.*]])
+! CHECK-SAME: ptr {{[^%]*}}%[[arg:.*]])
! CHECK: %[[extent:.*]] = getelementptr { {{.*}}, [1 x [3 x i64]] }, ptr %[[arg]], i32 0, i32 7, i64 0, i32 1
! CHECK: %[[extval:.*]] = load i64, ptr %[[extent]]
! CHECK: %[[elesize:.*]] = getelementptr { {{.*}}, [1 x [3 x i64]] }, ptr %[[arg]], i32 0, i32 1
diff --git a/flang/test/Transforms/constant-argument-globalisation.fir b/flang/test/Transforms/constant-argument-globalisation.fir
index 02349de40bc0b..4e5995bdf2207 100644
--- a/flang/test/Transforms/constant-argument-globalisation.fir
+++ b/flang/test/Transforms/constant-argument-globalisation.fir
@@ -49,8 +49,8 @@ module {
// DISABLE-LABEL: ; ModuleID =
// DISABLE-NOT: @_extruded
// DISABLE: define void @sub1(
-// DISABLE-SAME: ptr captures(none) [[ARG0:%.*]],
-// DISABLE-SAME: ptr captures(none) [[ARG1:%.*]])
+// DISABLE-SAME: ptr {{[^%]*}}[[ARG0:%.*]],
+// DISABLE-SAME: ptr {{[^%]*}}[[ARG1:%.*]])
// DISABLE-SAME: {
// DISABLE: [[CONST_R0:%.*]] = alloca double
// DISABLE: [[CONST_R1:%.*]] = alloca double
diff --git a/flang/test/Transforms/function-attrs-noalias.fir b/flang/test/Transforms/function-attrs-noalias.fir
new file mode 100644
index 0000000000000..6733fa96457bc
--- /dev/null
+++ b/flang/test/Transforms/function-attrs-noalias.fir
@@ -0,0 +1,113 @@
+// RUN: fir-opt --function-attr="set-noalias=true" %s | FileCheck %s
+
+// Test the annotation of function arguments with llvm.noalias.
+
+// Test !fir.ref arguments.
+// CHECK-LABEL: func.func private @test_ref(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {llvm.noalias}) {
+func.func private @test_ref(%arg0: !fir.ref<i32>) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_target(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.target}) {
+func.func private @test_ref_target(%arg0: !fir.ref<i32> {fir.target}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_volatile(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.volatile}) {
+func.func private @test_ref_volatile(%arg0: !fir.ref<i32> {fir.volatile}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_asynchronous(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.asynchronous}) {
+func.func private @test_ref_asynchronous(%arg0: !fir.ref<i32> {fir.asynchronous}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_box(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<i32>> {llvm.noalias}) {
+// Test !fir.ref<!fir.box<>> arguments:
+func.func private @test_ref_box(%arg0: !fir.ref<!fir.box<i32>>) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_box_target(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<i32>> {fir.target}) {
+func.func private @test_ref_box_target(%arg0: !fir.ref<!fir.box<i32>> {fir.target}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_box_volatile(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<i32>> {fir.volatile}) {
+func.func private @test_ref_box_volatile(%arg0: !fir.ref<!fir.box<i32>> {fir.volatile}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_ref_box_asynchronous(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<i32>> {fir.asynchronous}) {
+func.func private @test_ref_box_asynchronous(%arg0: !fir.ref<!fir.box<i32>> {fir.asynchronous}) {
+ return
+}
+
+// Test POINTER arguments.
+// CHECK-LABEL: func.func private @test_ref_box_ptr(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>) {
+func.func private @test_ref_box_ptr(%arg0: !fir.ref<!fir.box<!fir.ptr<i32>>>) {
+ return
+}
+
+// Test ALLOCATABLE arguments.
+// CHECK-LABEL: func.func private @test_ref_box_heap(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<i32>>> {llvm.noalias}) {
+func.func private @test_ref_box_heap(%arg0: !fir.ref<!fir.box<!fir.heap<i32>>>) {
+ return
+}
+
+// BIND(C) functions are not annotated.
+// CHECK-LABEL: func.func private @test_ref_bindc(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32>)
+func.func private @test_ref_bindc(%arg0: !fir.ref<i32>) attributes {fir.bindc_name = "test_ref_bindc", fir.proc_attrs = #fir.proc_attrs<bind_c>} {
+ return
+}
+
+// Test function declaration from a module.
+// CHECK-LABEL: func.func private @_QMtest_modPcheck_module(
+// CHECK-SAME: !fir.ref<i32> {llvm.noalias})
+func.func private @_QMtest_modPcheck_module(!fir.ref<i32>)
+
+// Test !fir.box arguments:
+// CHECK-LABEL: func.func private @test_box(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {llvm.noalias}) {
+func.func private @test_box(%arg0: !fir.box<i32>) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_target(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.target, llvm.noalias}) {
+func.func private @test_box_target(%arg0: !fir.box<i32> {fir.target}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_volatile(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.volatile, llvm.noalias}) {
+func.func private @test_box_volatile(%arg0: !fir.box<i32> {fir.volatile}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_asynchronous(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.asynchronous, llvm.noalias}) {
+func.func private @test_box_asynchronous(%arg0: !fir.box<i32> {fir.asynchronous}) {
+ return
+}
+
+// !fir.boxchar<> is lowered before FunctionAttrPass, but let's
+// make sure we do not annotate it.
+// CHECK-LABEL: func.func private @test_boxchar(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1>) {
+func.func private @test_boxchar(%arg0: !fir.boxchar<1>) {
+ return
+}
+
diff --git a/flang/test/Transforms/function-attrs.fir b/flang/test/Transforms/function-attrs.fir
index 5f871a1a7b6c5..5ebf316586cd0 100644
--- a/flang/test/Transforms/function-attrs.fir
+++ b/flang/test/Transforms/function-attrs.fir
@@ -1,4 +1,4 @@
-// RUN: fir-opt --function-attr %s | FileCheck %s
+// RUN: fir-opt --function-attr="set-nocapture=true" %s | FileCheck %s
// If a function has a body and is not bind(c), and if the dummy argument doesn't have the target,
// asynchronous, volatile, or pointer attribute, then add llvm.nocapture to the dummy argument.
>From 99ea15e1b0ac888e00522067873bfa35bece8e19 Mon Sep 17 00:00:00 2001
From: Slava Zakharin <szakharin at nvidia.com>
Date: Tue, 20 May 2025 14:11:53 -0700
Subject: [PATCH 2/2] Updated nocapture test.
---
flang/test/Transforms/function-attrs.fir | 25 ++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/flang/test/Transforms/function-attrs.fir b/flang/test/Transforms/function-attrs.fir
index 5ebf316586cd0..8e3a896fd58bf 100644
--- a/flang/test/Transforms/function-attrs.fir
+++ b/flang/test/Transforms/function-attrs.fir
@@ -43,3 +43,28 @@ func.func private @_QMarg_modPcheck_args(!fir.ref<i32> {fir.target}, !fir.ref<i3
// CHECK-SAME: !fir.ref<i32> {llvm.nocapture},
// CHECK-SAME: !fir.boxchar<1>,
// CHECK-SAME: !fir.ref<complex<f32>> {llvm.nocapture})
+
+// Test !fir.box arguments:
+// CHECK-LABEL: func.func private @test_box(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {llvm.nocapture}) {
+func.func private @test_box(%arg0: !fir.box<i32>) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_target(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.target, llvm.nocapture}) {
+func.func private @test_box_target(%arg0: !fir.box<i32> {fir.target}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_volatile(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.volatile, llvm.nocapture}) {
+func.func private @test_box_volatile(%arg0: !fir.box<i32> {fir.volatile}) {
+ return
+}
+
+// CHECK-LABEL: func.func private @test_box_asynchronous(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.box<i32> {fir.asynchronous, llvm.nocapture}) {
+func.func private @test_box_asynchronous(%arg0: !fir.box<i32> {fir.asynchronous}) {
+ return
+}
More information about the flang-commits
mailing list