Reland "[flang] Added noalias attribute to function arguments. (#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.
This commit is contained in:
parent
55c7d5cdad
commit
a0d699a8e6
@ -431,6 +431,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">,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -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>(
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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]]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]]
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 },
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) %{{.*}})
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 %{{.*}}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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(), !{{.*}})
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -22,7 +22,7 @@ contains
|
||||
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
|
||||
|
@ -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
|
||||
|
113
flang/test/Transforms/function-attrs-noalias.fir
Normal file
113
flang/test/Transforms/function-attrs-noalias.fir
Normal file
@ -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
|
||||
}
|
||||
|
@ -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.
|
||||
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user