diff options
author | s-watanabe314 <watanabe.shu-06@fujitsu.com> | 2024-11-28 15:39:26 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-28 15:39:26 +0900 |
commit | f3cf24fcc46ab1b9612d7dcb55ec5f18ea2dc62f (patch) | |
tree | eef5f40cc4d752755713cb95a5288a5485151634 | |
parent | 1c7695846559c2b191463aec46beb26c4a5c2bae (diff) | |
download | llvm-f3cf24fcc46ab1b9612d7dcb55ec5f18ea2dc62f.zip llvm-f3cf24fcc46ab1b9612d7dcb55ec5f18ea2dc62f.tar.gz llvm-f3cf24fcc46ab1b9612d7dcb55ec5f18ea2dc62f.tar.bz2 |
[flang] Apply nocapture attribute to dummy arguments (#116182)
Apply llvm.nocapture attribute to dummy arguments that do not have the
target, asynchronous, volatile, or pointer attributes in a procedure
that is not a bind(c). This was discussed in
https://discourse.llvm.org/t/applying-the-nocapture-attribute-to-reference-passed-arguments-in-fortran-subroutines/81401
22 files changed, 164 insertions, 100 deletions
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 1568165..0b7b3ba 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -278,22 +278,17 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, // Add function attributes mlir::LLVM::framePointerKind::FramePointerKind framePointerKind; - if (config.FramePointerKind != llvm::FramePointerKind::None || - config.NoInfsFPMath || config.NoNaNsFPMath || config.ApproxFuncFPMath || - config.NoSignedZerosFPMath || config.UnsafeFPMath) { - if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf) - framePointerKind = - mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf; - else if (config.FramePointerKind == llvm::FramePointerKind::All) - framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::All; - else - framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::None; - - pm.addPass(fir::createFunctionAttr( - {framePointerKind, config.NoInfsFPMath, config.NoNaNsFPMath, - config.ApproxFuncFPMath, config.NoSignedZerosFPMath, - config.UnsafeFPMath})); - } + if (config.FramePointerKind == llvm::FramePointerKind::NonLeaf) + framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::NonLeaf; + else if (config.FramePointerKind == llvm::FramePointerKind::All) + framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::All; + else + framePointerKind = mlir::LLVM::framePointerKind::FramePointerKind::None; + + pm.addPass(fir::createFunctionAttr( + {framePointerKind, config.NoInfsFPMath, config.NoNaNsFPMath, + config.ApproxFuncFPMath, config.NoSignedZerosFPMath, + config.UnsafeFPMath})); fir::addFIRToLLVMPass(pm, config); } diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp index 69c4159..c79843f 100644 --- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp +++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp @@ -10,6 +10,8 @@ /// \file /// This is a generic pass for adding attributes to functions. //===----------------------------------------------------------------------===// +#include "flang/Optimizer/Dialect/FIROpsSupport.h" +#include "flang/Optimizer/Support/InternalNames.h" #include "flang/Optimizer/Transforms/Passes.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -45,6 +47,24 @@ void FunctionAttrPass::runOnOperation() { LLVM_DEBUG(llvm::dbgs() << "Func-name:" << func.getSymName() << "\n"); + llvm::StringRef name = func.getSymName(); + auto deconstructed = fir::NameUniquer::deconstruct(name); + bool isFromModule = !deconstructed.second.modules.empty(); + + if ((isFromModule || !func.isDeclaration()) && + !fir::hasBindcAttr(func.getOperation())) { + llvm::StringRef nocapture = mlir::LLVM::LLVMDialect::getNoCaptureAttrName(); + mlir::UnitAttr unitAttr = mlir::UnitAttr::get(func.getContext()); + + for (auto [index, argType] : llvm::enumerate(func.getArgumentTypes())) { + if (mlir::isa<fir::ReferenceType>(argType) && + !func.getArgAttr(index, fir::getTargetAttrName()) && + !func.getArgAttr(index, fir::getAsynchronousAttrName()) && + !func.getArgAttr(index, fir::getVolatileAttrName())) + func.setArgAttr(index, nocapture, unitAttr); + } + } + mlir::MLIRContext *context = &getContext(); if (framePointerKind != mlir::LLVM::framePointerKind::FramePointerKind::None) func->setAttr("frame_pointer", mlir::LLVM::FramePointerKindAttr::get( diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 7d57135..33c8183 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -123,5 +123,7 @@ end program ! ALL-NEXT: ExternalNameConversion ! ALL-NEXT: TargetRewrite ! ALL-NEXT: CompilerGeneratedNamesConversion +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: FunctionAttr ! ALL-NEXT: FIRToLLVMLowering ! ALL-NOT: LLVMIRLoweringPass diff --git a/flang/test/Fir/arrayset.fir b/flang/test/Fir/arrayset.fir index a9630c8..d201e34 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 %0) +// CHECK-LABEL: define void @x(ptr nocapture %0) 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 5d265a5..3363ead 100644 --- a/flang/test/Fir/arrexp.fir +++ b/flang/test/Fir/arrexp.fir @@ -1,7 +1,7 @@ // RUN: tco %s | FileCheck %s // CHECK-LINE: define void @f1 -// CHECK: (ptr %[[A:[^,]*]], {{.*}}, float %[[F:.*]]) +// CHECK: (ptr nocapture %[[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-LINE: define void @f2 -// CHECK: (ptr %[[A:[^,]*]], {{.*}}, float %[[F:.*]]) +// CHECK: (ptr nocapture %[[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-LINE: define void @f3 -// CHECK: (ptr %[[A:[^,]*]], {{.*}}, float %[[F:.*]]) +// CHECK: (ptr nocapture %[[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-LINE: define void @f4 -// CHECK: (ptr %[[A:[^,]*]], {{.*}}, float %[[F:.*]]) +// CHECK: (ptr nocapture %[[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> @@ -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 %[[X:[^,]*]], ptr %[[Y:.*]]) +// CHECK: ptr nocapture %[[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 %[[A:.*]], i32 %[[I:.*]]) +// CHECK-SAME: ptr nocapture %[[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 %[[C:.*]]) +// CHECK-SAME: i32 %[[I:.*]], i64 %{{.*}}, i64 %{{.*}}, ptr nocapture %[[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/basic-program.fir b/flang/test/Fir/basic-program.fir index 4b18acb..ad5201a 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -120,6 +120,8 @@ func.func @_QQmain() { // PASSES-NEXT: (S) 0 num-dce'd - Number of operations eliminated // PASSES-NEXT: TargetRewrite // PASSES-NEXT: CompilerGeneratedNamesConversion +// PASSES-NEXT: 'func.func' Pipeline +// PASSES-NEXT: FunctionAttr // PASSES-NEXT: FIRToLLVMLowering // PASSES-NEXT: ReconcileUnrealizedCasts // PASSES-NEXT: LLVMIRLoweringPass diff --git a/flang/test/Fir/box-offset-codegen.fir b/flang/test/Fir/box-offset-codegen.fir index 389ceeb..5be3ad1 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 %[[BOX:.*]]){{.*}}{ +// CHECK-SAME: ptr nocapture %[[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 %[[BOX:.*]]){{.*}}{ +// CHECK-SAME: ptr nocapture %[[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 %[[BOX:.*]]){{.*}}{ +// CHECK-SAME: ptr nocapture %[[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 %[[BOX:.*]]){{.*}}{ +// CHECK-SAME: ptr nocapture %[[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.fir b/flang/test/Fir/box.fir index fd9fa1f..841e10d 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 %[[ARG:.*]]) +// CHECK: (ptr nocapture %[[ARG:.*]]) func.func @f(%a : !fir.ref<f32>) { // CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } // CHECK: %[[INS0:.*]] = insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), 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 %[[ARG:.*]]) +// CHECK: (ptr nocapture %[[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 %[[res:.*]], ptr %[[arg0:.*]], i64 %[[arg1:.*]]) +// CHECK-SAME: ptr nocapture %[[res:.*]], ptr nocapture %[[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 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[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 %[[res]], -// CHECK-SAME: ptr %[[arg0:.*]], i64 %[[arg1:.*]]) +// CHECK-SAME: ptr nocapture %[[res]], +// CHECK-SAME: ptr nocapture %[[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 %[[res:.*]], ptr %[[arg0:.*]], i64 %[[arg1:.*]], i64 %[[arg2:.*]]) +// CHECK-SAME: ptr nocapture %[[res:.*]], ptr nocapture %[[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 %[[res:.*]], ptr %[[arg0:.*]], i64 %[[arg1:.*]]) +// CHECK-SAME: ptr nocapture %[[res:.*]], ptr nocapture %[[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 %[[arg0:.*]], ptr %[[arg1:.*]]) +// CHECK-SAME: ptr nocapture %[[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 %[[ARG0:.*]], i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) +// CHECK-SAME: ptr nocapture %[[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 9e4ea0b..27d8953 100644 --- a/flang/test/Fir/boxproc.fir +++ b/flang/test/Fir/boxproc.fir @@ -12,7 +12,7 @@ // CHECK: call void @_QPtest_proc_dummy_other(ptr %[[VAL_6]]) // CHECK-LABEL: define void @_QFtest_proc_dummyPtest_proc_dummy_a(ptr -// CHECK-SAME: %[[VAL_0:.*]], ptr nest %[[VAL_1:.*]]) +// CHECK-SAME: nocapture %[[VAL_0:.*]], ptr nest nocapture %[[VAL_1:.*]]) // CHECK-LABEL: define void @_QPtest_proc_dummy_other(ptr // CHECK-SAME: %[[VAL_0:.*]]) @@ -86,7 +86,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: %[[VAL_0:.*]], i64 %[[VAL_1:.*]], ptr nest %[[VAL_2:.*]]) +// CHECK-SAME: nocapture %[[VAL_0:.*]], i64 %[[VAL_1:.*]], ptr nest nocapture %[[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 be25fd6..7533816 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 %0) +// CHECK-LABEL: define i32 @f2(ptr nocapture %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 acb9fd5..f96f5b48 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 %{{.*}}) +// CHECK-SAME: (ptr %[[box:.*]], i64 %{{.*}}, ptr nocapture %{{.*}}) 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 cd13c5c..b21e134 100644 --- a/flang/test/Fir/embox.fir +++ b/flang/test/Fir/embox.fir @@ -64,7 +64,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 %[[arg0:.*]]) +// CHECK-SAME: ptr nocapture %[[arg0:.*]]) func.func @emboxSubstring(%arg0: !fir.ref<!fir.array<2x3x!fir.char<1,4>>>) { %c2 = arith.constant 2 : index %c3 = arith.constant 3 : index @@ -85,7 +85,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 %[[base_addr:.*]], i64 %[[low:.*]], i64 %[[up:.*]], i64 %[[at:.*]]) +// CHECK-SAME: ptr nocapture %[[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 8c9391f..0865375 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 %[[arg0:.*]]) +// CHECK-SAME: (ptr nocapture %[[arg0:.*]]) func.func @simple_field(%arg0: !fir.ref<!fir.type<a{x:f32,i:i32}>>) -> i32 { %1 = fir.field_index i, !fir.type<a{x:f32,i:i32}> // CHECK: %[[GEP:.*]] = getelementptr %a, ptr %[[arg0]], i32 0, i32 1 @@ -18,7 +18,7 @@ func.func @simple_field(%arg0: !fir.ref<!fir.type<a{x:f32,i:i32}>>) -> i32 { } // CHECK-LABEL: @derived_field -// CHECK-SAME: (ptr %[[arg0:.*]]) +// CHECK-SAME: (ptr nocapture %[[arg0:.*]]) func.func @derived_field(%arg0: !fir.ref<!fir.type<c{x:f32,some_b:!fir.type<b{x:f32,i:i32}>}>>) -> i32 { %1 = fir.field_index some_b, !fir.type<c{x:f32,some_b:!fir.type<b{x:f32,i:i32}>}> %2 = fir.field_index i, !fir.type<b{x:f32,i:i32}> diff --git a/flang/test/Fir/ignore-missing-type-descriptor.fir b/flang/test/Fir/ignore-missing-type-descriptor.fir index 228d9a1c..009e110 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 %[[ADDR:.*]]) +// CHECK-SAME: ptr nocapture %[[ADDR:.*]]) // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } // CHECK-SAME: { ptr undef, i64 ptrtoint (ptr getelementptr (%some_not_mangled_type, ptr null, i32 1) to i64), // 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 78e5b8d..74b29ed 100644 --- a/flang/test/Fir/polymorphic.fir +++ b/flang/test/Fir/polymorphic.fir @@ -175,7 +175,7 @@ func.func @_QMmod2Pinitp(%arg0: !fir.ref<!fir.class<!fir.ptr<none>>> {fir.bindc_ func.func private @_FortranAPointerAssociate(!fir.ref<!fir.box<none>>, !fir.box<none>) -> none attributes {fir.runtime} // CHECK-LABEL: define void @_QMmod2Pinitp( -// CHECK-SAME: ptr %[[ARG0:.*]]){{.*}}{ +// CHECK-SAME: ptr nocapture %[[ARG0:.*]]){{.*}}{ // CHECK: %[[ALLOCA_CLASS_NONE:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } // CHECK: call void @llvm.memcpy.p0.p0.i32(ptr %[[ALLOCA_CLASS_NONE]], ptr %[[ARG0]], i32 40, i1 false) // CHECK: %{{.*}} = call {} @_FortranAPointerAssociate(ptr @_QMmod2Ep, ptr %[[ALLOCA_CLASS_NONE]]) diff --git a/flang/test/Fir/struct-passing-x86-64-byval.fir b/flang/test/Fir/struct-passing-x86-64-byval.fir index b686901..44256c0 100644 --- a/flang/test/Fir/struct-passing-x86-64-byval.fir +++ b/flang/test/Fir/struct-passing-x86-64-byval.fir @@ -81,27 +81,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 %{{.*}}) { -// CHECK: define void @takes_toobig_align16(ptr byval(%toobig_align16) align 16 %{{.*}}) { -// CHECK: define void @not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 %{{.*}}) { -// CHECK: define void @not_enough_int_reg_1b(ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 %{{.*}}) { -// CHECK: define void @not_enough_int_reg_2(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_2_int_reg) align 8 %{{.*}}) { -// CHECK: define void @ftakes_toobig(ptr byval(%ftoobig) align 8 %{{.*}}) { -// CHECK: define void @ftakes_toobig_align16(ptr byval(%ftoobig_align16) align 16 %{{.*}}) { -// 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 %{{.*}}) { -// 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 %{{.*}}) { -// 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 %{{.*}}) { -// CHECK: define void @not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr byval(%fits_in_2_sse_reg) align 8 %{{.*}}) { -// CHECK: define void @test_contains_x87(ptr byval(%contains_x87) align 16 %{{.*}}) { -// CHECK: define void @test_contains_complex_x87(ptr byval(%contains_complex_x87) align 16 %{{.*}}) { -// CHECK: define void @test_nested_toobig(ptr byval(%nested_toobig) align 8 %{{.*}}) { -// CHECK: define void @test_badly_aligned(ptr byval(%badly_aligned) align 8 %{{.*}}) { -// CHECK: define void @test_logical_toobig(ptr byval(%logical_too_big) align 8 %{{.*}}) { -// CHECK: define void @l_not_enough_int_reg(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%l_fits_in_2_int_reg) align 8 %{{.*}}) { -// CHECK: define void @test_complex_toobig(ptr byval(%complex_too_big) align 8 %{{.*}}) { -// 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 %{{.*}}) { -// CHECK: define void @test_char_to_big(ptr byval(%char_too_big) align 8 %{{.*}}) { -// 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 %{{.*}}) { -// CHECK: define void @mix_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%mix_in_1_int_reg) align 8 %{{.*}}) { -// 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 %{{.*}}) { -// CHECK: define void @not_enough_int_reg_3(ptr sret({ fp128, fp128 }) align 16 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr byval(%fits_in_1_int_reg) align 8 %{{.*}}) +// CHECK: define void @takes_toobig(ptr nocapture byval(%toobig) align 8 %{{.*}}) { +// CHECK: define void @takes_toobig_align16(ptr nocapture byval(%toobig_align16) align 16 %{{.*}}) { +// CHECK: define void @not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%fits_in_1_int_reg) align 8 %{{.*}}) { +// CHECK: define void @not_enough_int_reg_1b(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}, ptr nocapture %{{.*}}, ptr nocapture %{{.*}}, ptr nocapture %{{.*}}, ptr nocapture %{{.*}}, ptr nocapture byval(%fits_in_1_int_reg) align 8 %{{.*}}) { +// CHECK: define void @not_enough_int_reg_2(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%fits_in_2_int_reg) align 8 %{{.*}}) { +// CHECK: define void @ftakes_toobig(ptr nocapture byval(%ftoobig) align 8 %{{.*}}) { +// CHECK: define void @ftakes_toobig_align16(ptr nocapture byval(%ftoobig_align16) align 16 %{{.*}}) { +// CHECK: define void @not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr nocapture byval(%fits_in_1_sse_reg) align 8 %{{.*}}) { +// 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 nocapture byval(%fits_in_1_sse_reg) align 8 %{{.*}}) { +// CHECK: define void @not_enough_sse_reg_1c(double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, double %{{.*}}, ptr nocapture byval(%fits_in_1_sse_reg) align 8 %{{.*}}) { +// CHECK: define void @not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr nocapture byval(%fits_in_2_sse_reg) align 8 %{{.*}}) { +// CHECK: define void @test_contains_x87(ptr nocapture byval(%contains_x87) align 16 %{{.*}}) { +// CHECK: define void @test_contains_complex_x87(ptr nocapture byval(%contains_complex_x87) align 16 %{{.*}}) { +// CHECK: define void @test_nested_toobig(ptr nocapture byval(%nested_toobig) align 8 %{{.*}}) { +// CHECK: define void @test_badly_aligned(ptr nocapture byval(%badly_aligned) align 8 %{{.*}}) { +// CHECK: define void @test_logical_toobig(ptr nocapture byval(%logical_too_big) align 8 %{{.*}}) { +// CHECK: define void @l_not_enough_int_reg(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%l_fits_in_2_int_reg) align 8 %{{.*}}) { +// CHECK: define void @test_complex_toobig(ptr nocapture byval(%complex_too_big) align 8 %{{.*}}) { +// CHECK: define void @cplx_not_enough_sse_reg_1(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr nocapture byval(%cplx_fits_in_1_sse_reg) align 8 %{{.*}}) { +// CHECK: define void @test_char_to_big(ptr nocapture byval(%char_too_big) align 8 %{{.*}}) { +// CHECK: define void @char_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%char_fits_in_1_int_reg) align 8 %{{.*}}) { +// CHECK: define void @mix_not_enough_int_reg_1(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%mix_in_1_int_reg) align 8 %{{.*}}) { +// CHECK: define void @mix_not_enough_sse_reg_2(float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, ptr nocapture byval(%mix_in_1_int_reg_1_sse_reg) align 8 %{{.*}}) { +// CHECK: define void @not_enough_int_reg_3(ptr nocapture sret({ fp128, fp128 }) align 16 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}, ptr nocapture byval(%fits_in_1_int_reg) align 8 %{{.*}}) diff --git a/flang/test/Fir/target-rewrite-complex-10-x86.fir b/flang/test/Fir/target-rewrite-complex-10-x86.fir index 404f5f9..651d1e7 100644 --- a/flang/test/Fir/target-rewrite-complex-10-x86.fir +++ b/flang/test/Fir/target-rewrite-complex-10-x86.fir @@ -29,4 +29,4 @@ 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 %0) +// AMD64_LLVM: define void @takecomplex10(ptr nocapture byval({ x86_fp80, x86_fp80 }) align 16 %0) diff --git a/flang/test/Fir/target.fir b/flang/test/Fir/target.fir index 788deeb..478d681 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 % +// I32-LABEL: define void @gen8(ptr nocapture sret({ double, double }) align 4 % // 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 %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) +// I32-LABEL: define i64 @char1lensum(ptr nocapture %0, ptr nocapture %1, i32 %2, i32 %3) +// X64-LABEL: define i64 @char1lensum(ptr nocapture %0, ptr nocapture %1, i64 %2, i64 %3) +// PPC-LABEL: define i64 @char1lensum(ptr nocapture %0, ptr nocapture %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 @@ -111,9 +111,9 @@ func.func @char1lensum(%arg0 : !fir.boxchar<1>, %arg1 : !fir.boxchar<1>) -> i64 return %3 : i64 } -// I32-LABEL: define void @char1copy(ptr sret(i8) %0, i32 %1, ptr %2, i32 %3) -// I64-LABEL: define void @char1copy(ptr sret(i8) %0, i64 %1, ptr %2, i64 %3) -// PPC-LABEL: define void @char1copy(ptr sret(i8) %0, i64 %1, ptr %2, i64 %3) +// I32-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i32 %1, ptr nocapture %2, i32 %3) +// I64-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i64 %1, ptr nocapture %2, i64 %3) +// PPC-LABEL: define void @char1copy(ptr nocapture sret(i8) %0, i64 %1, ptr nocapture %2, i64 %3) func.func @char1copy(%arg0 : !fir.boxchar<1> {llvm.sret = !fir.char<1, ?>}, %arg1 : !fir.boxchar<1>) { // I32-DAG: %[[p0:.*]] = insertvalue { ptr, i32 } undef, ptr %2, 0 // I32-DAG: = insertvalue { ptr, i32 } %[[p0]], i32 %3, 1 diff --git a/flang/test/Integration/OpenMP/copyprivate.f90 b/flang/test/Integration/OpenMP/copyprivate.f90 index d32319a..47e932a 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 void @_copy_box_Uxi32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_10xi32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_i64(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_box_Uxi64(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_f32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_2x3xf32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_z32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_10xz32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_l32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_5xl32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_c8x8(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_10xc8x8(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_c16x5(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_rec__QFtest_typesTdt(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_box_heap_Uxi32(ptr %{{.*}}, ptr %{{.*}}) -!CHECK-DAG: define void @_copy_box_ptr_Uxc8x9(ptr %{{.*}}, ptr %{{.*}}) +!CHECK-DAG: define void @_copy_box_Uxi32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_10xi32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_i64(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_box_Uxi64(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_f32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_2x3xf32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_z32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_10xz32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_l32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_5xl32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_c8x8(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_10xc8x8(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_c16x5(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_rec__QFtest_typesTdt(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_box_heap_Uxi32(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) +!CHECK-DAG: define void @_copy_box_ptr_Uxc8x9(ptr nocapture %{{.*}}, ptr nocapture %{{.*}}) !CHECK-LABEL: define void @_copy_i32( -!CHECK-SAME: ptr %[[DST:.*]], ptr %[[SRC:.*]]){{.*}} { +!CHECK-SAME: ptr nocapture %[[DST:.*]], ptr nocapture %[[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 525474a..5a675cb 100644 --- a/flang/test/Integration/debug-local-var-2.f90 +++ b/flang/test/Integration/debug-local-var-2.f90 @@ -27,7 +27,7 @@ ! BOTH-LABEL: } ! BOTH-LABEL: define {{.*}}i64 @_QFPfn1 -! BOTH-SAME: (ptr %[[ARG1:.*]], ptr %[[ARG2:.*]], ptr %[[ARG3:.*]]) +! BOTH-SAME: (ptr nocapture %[[ARG1:.*]], ptr nocapture %[[ARG2:.*]], ptr nocapture %[[ARG3:.*]]) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[ARG1]], metadata ![[A1:.*]], metadata !DIExpression()) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[ARG2]], metadata ![[B1:.*]], metadata !DIExpression()) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[ARG3]], metadata ![[C1:.*]], metadata !DIExpression()) @@ -40,7 +40,7 @@ ! BOTH-LABEL: } ! BOTH-LABEL: define {{.*}}i32 @_QFPfn2 -! BOTH-SAME: (ptr %[[FN2ARG1:.*]], ptr %[[FN2ARG2:.*]], ptr %[[FN2ARG3:.*]]) +! BOTH-SAME: (ptr nocapture %[[FN2ARG1:.*]], ptr nocapture %[[FN2ARG2:.*]], ptr nocapture %[[FN2ARG3:.*]]) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[FN2ARG1]], metadata ![[A2:.*]], metadata !DIExpression()) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[FN2ARG2]], metadata ![[B2:.*]], metadata !DIExpression()) ! INTRINSICS-DAG: call void @llvm.dbg.declare(metadata ptr %[[FN2ARG3]], metadata ![[C2:.*]], metadata !DIExpression()) diff --git a/flang/test/Transforms/constant-argument-globalisation.fir b/flang/test/Transforms/constant-argument-globalisation.fir index 553c3c6..5656de0 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 [[ARG0:%.*]], -// DISABLE-SAME: ptr [[ARG1:%.*]]) +// DISABLE-SAME: ptr nocapture [[ARG0:%.*]], +// DISABLE-SAME: ptr nocapture [[ARG1:%.*]]) // DISABLE-SAME: { // DISABLE: [[CONST_R0:%.*]] = alloca double // DISABLE: [[CONST_R1:%.*]] = alloca double diff --git a/flang/test/Transforms/function-attrs.fir b/flang/test/Transforms/function-attrs.fir new file mode 100644 index 0000000..5f871a1 --- /dev/null +++ b/flang/test/Transforms/function-attrs.fir @@ -0,0 +1,45 @@ +// RUN: fir-opt --function-attr %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. + +func.func @_QParg_nocapture(%arg0: !fir.ref<i32> {fir.bindc_name = "tar", fir.target}, %arg1: !fir.ref<i32> {fir.asynchronous, fir.bindc_name = "asynch"}, %arg2: !fir.ref<i32> {fir.bindc_name = "vol", fir.volatile}, %arg3: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "ptr"}, %arg4: !fir.ref<i32> {fir.bindc_name = "nocap"}) { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFarg_nocaptureEtar"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + %2 = fir.declare %arg1 dummy_scope %0 {fortran_attrs = #fir.var_attrs<asynchronous>, uniq_name = "_QFarg_nocaptureEasynch"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + %3 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFarg_nocaptureEvol"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + %4 = fir.declare %arg3 dummy_scope %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFarg_nocaptureEptr"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.dscope) -> !fir.ref<!fir.box<!fir.ptr<i32>>> + %5 = fir.declare %arg4 dummy_scope %0 {uniq_name = "_QFarg_nocaptureEnocap"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + return +} +// CHECK-LABEL: func.func @_QParg_nocapture( +// CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "tar", fir.target}, +// CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.asynchronous, fir.bindc_name = "asynch"}, +// CHECK-SAME: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "vol", fir.volatile}, +// CHECK-SAME: %[[ARG3:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>> {fir.bindc_name = "ptr", llvm.nocapture}, +// CHECK-SAME: %[[ARG4:.*]]: !fir.ref<i32> {fir.bindc_name = "nocap", llvm.nocapture}) { +// CHECK: return +// CHECK-NEXT: } + +func.func @arg_nocapture_bindc(%arg0: !fir.ref<i32> {fir.bindc_name = "tar", fir.target}, %arg1: !fir.ref<i32> {fir.bindc_name = "nocap"}) attributes {fir.bindc_name = "arg_nocapture_bindc", fir.proc_attrs = #fir.proc_attrs<bind_c>} { + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFarg_nocapture_bindcEtar"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFarg_nocapture_bindcEnocap"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32> + return +} +// CHECK-LABEL: func.func @arg_nocapture_bindc( +// CHECK-NOT: llvm.nocapture + + +// If a function declaration is from a module 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. + +func.func private @_QMarg_modPcheck_args(!fir.ref<i32> {fir.target}, !fir.ref<i32> {fir.asynchronous}, !fir.ref<i32> {fir.volatile}, !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<i32>, !fir.boxchar<1>, !fir.ref<complex<f32>>) +// CHECK-LABEL: func.func private @_QMarg_modPcheck_args( +// CHECK-SAME: !fir.ref<i32> {fir.target}, +// CHECK-SAME: !fir.ref<i32> {fir.asynchronous}, +// CHECK-SAME: !fir.ref<i32> {fir.volatile}, +// CHECK-SAME: !fir.ref<!fir.box<!fir.ptr<i32>>> {llvm.nocapture}, +// CHECK-SAME: !fir.ref<i32> {llvm.nocapture}, +// CHECK-SAME: !fir.boxchar<1>, +// CHECK-SAME: !fir.ref<complex<f32>> {llvm.nocapture}) |