[Flang] Apply nusw nuw flags on array_coor gep's (#184573)

When generating the LLVM IR, since #110060, `nsw` is applied to
operations when lowering the subscripts. This was, up until now, only
applied to arithmetic, and not the related getelementptr's.

The original Discouse thread noted that NSW helped with vectorisation
later on in the process. Changes to the BasicAA pipeline has led to
vectorisation no longer being applied where wrapping cannot be
guaranteed for array_coor instructions. By applying the `nusw nuw` flags
to the GEP's, this enables vectorisation in the middle end. Supporting
arithmatic instructions will also be marked `nuw` to ensure instcombine
does not remove these flags when transforming instructions.

There does need to be some consideration to the `sub` operations
generated in this process. There are cases, such as when an array is
shifted, where unsigned wrapping may occur due to using negative values.
To protect against this, if an array is shifted, `nuw` won't be applied
to the `sub` operations.

This patch has been verified using the following with no regressions:
- llvm-test-suite
- Fujitsu test suite
- Various Opensource HPC Applications

Original Discourse thread:
https://discourse.llvm.org/t/rfc-add-nsw-flags-to-arithmetic-integer-operations-using-the-option-fno-wrapv/77584

Assisted-by: Codex
This commit is contained in:
Jack Styles 2026-03-13 11:03:53 +00:00 committed by GitHub
parent 1a4a26bcd8
commit 7e0ef4a203
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 211 additions and 165 deletions

View File

@ -2730,6 +2730,16 @@ struct XArrayCoorOpConversion
baseIsBoxed ? getBoxTypePair(coor.getMemref().getType()) : TypePair{};
mlir::LLVM::IntegerOverflowFlags nsw =
mlir::LLVM::IntegerOverflowFlags::nsw;
mlir::LLVM::IntegerOverflowFlags nuw =
mlir::LLVM::IntegerOverflowFlags::nuw;
// TODO Allow for non-default lower bounds that are positive
// We know at compile time this is possible, so could be updated in future
// to allow for this, and just exclude non-default lower bounds that are
// negative. Currently, all shifted XArrayCoorOp's only have nsw on sub
// operations.
mlir::LLVM::IntegerOverflowFlags subFlags = isShifted ? nsw : (nsw | nuw);
mlir::LLVM::IntegerOverflowFlags addMulFlags = nsw | nuw;
mlir::LLVM::GEPNoWrapFlags gepFlags = mlir::LLVM::GEPNoWrapFlags::nusw | mlir::LLVM::GEPNoWrapFlags::nuw;
// For each dimension of the array, generate the offset calculation.
for (unsigned i = 0; i < rank; ++i, ++indexOffset, ++shapeOffset,
@ -2751,15 +2761,16 @@ struct XArrayCoorOpConversion
step = integerCast(loc, rewriter, idxTy, operands[sliceOffset + 2]);
}
auto idx =
mlir::LLVM::SubOp::create(rewriter, loc, idxTy, index, lb, nsw);
mlir::Value diff =
mlir::LLVM::MulOp::create(rewriter, loc, idxTy, idx, step, nsw);
mlir::LLVM::SubOp::create(rewriter, loc, idxTy, index, lb, subFlags);
mlir::Value diff = mlir::LLVM::MulOp::create(rewriter, loc, idxTy, idx,
step, addMulFlags);
if (normalSlice) {
mlir::Value sliceLb =
integerCast(loc, rewriter, idxTy, operands[sliceOffset]);
auto adj =
mlir::LLVM::SubOp::create(rewriter, loc, idxTy, sliceLb, lb, nsw);
diff = mlir::LLVM::AddOp::create(rewriter, loc, idxTy, diff, adj, nsw);
auto adj = mlir::LLVM::SubOp::create(rewriter, loc, idxTy, sliceLb, lb,
subFlags);
diff = mlir::LLVM::AddOp::create(rewriter, loc, idxTy, diff, adj,
addMulFlags);
}
// Update the offset given the stride and the zero based index `diff`
// that was just computed.
@ -2767,21 +2778,21 @@ struct XArrayCoorOpConversion
// Use stride in bytes from the descriptor.
mlir::Value stride =
getStrideFromBox(loc, baseBoxTyPair, operands[0], i, rewriter);
auto sc =
mlir::LLVM::MulOp::create(rewriter, loc, idxTy, diff, stride, nsw);
offset =
mlir::LLVM::AddOp::create(rewriter, loc, idxTy, sc, offset, nsw);
auto sc = mlir::LLVM::MulOp::create(rewriter, loc, idxTy, diff, stride,
addMulFlags);
offset = mlir::LLVM::AddOp::create(rewriter, loc, idxTy, sc, offset,
addMulFlags);
} else {
// Use stride computed at last iteration.
auto sc =
mlir::LLVM::MulOp::create(rewriter, loc, idxTy, diff, prevExt, nsw);
offset =
mlir::LLVM::AddOp::create(rewriter, loc, idxTy, sc, offset, nsw);
auto sc = mlir::LLVM::MulOp::create(rewriter, loc, idxTy, diff, prevExt,
addMulFlags);
offset = mlir::LLVM::AddOp::create(rewriter, loc, idxTy, sc, offset,
addMulFlags);
// Compute next stride assuming contiguity of the base array
// (in element number).
auto nextExt = integerCast(loc, rewriter, idxTy, operands[shapeOffset]);
prevExt = mlir::LLVM::MulOp::create(rewriter, loc, idxTy, prevExt,
nextExt, nsw);
nextExt, addMulFlags);
}
}
@ -2794,7 +2805,7 @@ struct XArrayCoorOpConversion
getBaseAddrFromBox(loc, baseBoxTyPair, operands[0], rewriter);
llvm::SmallVector<mlir::LLVM::GEPArg> args{offset};
auto addr = mlir::LLVM::GEPOp::create(rewriter, loc, llvmPtrTy, byteTy,
base, args);
base, args, gepFlags);
if (coor.getSubcomponent().empty()) {
rewriter.replaceOp(coor, addr);
return mlir::success();
@ -2819,8 +2830,8 @@ struct XArrayCoorOpConversion
operands.slice(coor.getSubcomponentOperandIndex(),
coor.getSubcomponent().size()));
args.append(indices.begin(), indices.end());
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(coor, llvmPtrTy,
elementType, addr, args);
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
coor, llvmPtrTy, elementType, addr, args, gepFlags);
return mlir::success();
}
@ -2842,7 +2853,7 @@ struct XArrayCoorOpConversion
auto length = integerCast(loc, rewriter, idxTy,
operands[coor.getLenParamsOperandIndex()]);
offset = mlir::LLVM::MulOp::create(rewriter, loc, idxTy, offset,
length, nsw);
length, addMulFlags);
} else {
TODO(loc, "compute size of derived type with type parameters");
}
@ -2858,7 +2869,7 @@ struct XArrayCoorOpConversion
args.append(indices.begin(), indices.end());
}
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
coor, llvmPtrTy, gepObjectType, adaptor.getMemref(), args);
coor, llvmPtrTy, gepObjectType, adaptor.getMemref(), args, gepFlags);
return mlir::success();
}
};

View File

@ -9,15 +9,15 @@ func.func @array_coor_box_value(%29 : !fir.box<!fir.array<2xf64>>,
}
// CHECK-LABEL: define double @array_coor_box_value
// CHECK: %[[t3:.*]] = sub nsw i64 %{{.*}}, 1
// CHECK: %[[t4:.*]] = mul nsw i64 %[[t3]], 1
// CHECK: %[[t3:.*]] = sub nuw nsw i64 %{{.*}}, 1
// CHECK: %[[t4:.*]] = mul nuw nsw i64 %[[t3]], 1
// CHECK: %[[t5:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %{{.*}}, i32 0, i32 7, i32 0, i32 2
// CHECK: %[[t6:.*]] = load i64, ptr %[[t5]]
// CHECK: %[[t7:.*]] = mul nsw i64 %[[t4]], %[[t6]]
// CHECK: %[[t8:.*]] = add nsw i64 %[[t7]], 0
// CHECK: %[[t7:.*]] = mul nuw nsw i64 %[[t4]], %[[t6]]
// CHECK: %[[t8:.*]] = add nuw nsw i64 %[[t7]], 0
// CHECK: %[[t9:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %{{.*}}, i32 0, i32 0
// CHECK: %[[t10:.*]] = load ptr, ptr %[[t9]]
// CHECK: %[[t11:.*]] = getelementptr i8, ptr %[[t10]], i64 %[[t8]]
// CHECK: %[[t11:.*]] = getelementptr nusw nuw i8, ptr %[[t10]], i64 %[[t8]]
// CHECK: %[[t12:.*]] = load double, ptr %[[t11]]
// CHECK: ret double %[[t12]]
@ -36,10 +36,10 @@ func.func private @take_int(%arg0: !fir.ref<i32>) -> ()
// 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]]
// CHECK: %[[VAL_4:.*]] = add nsw i64 %[[VAL_3]], 0
// CHECK: %[[VAL_3:.*]] = mul nuw nsw i64 1, %[[VAL_2]]
// CHECK: %[[VAL_4:.*]] = add nuw nsw i64 %[[VAL_3]], 0
// CHECK: %[[VAL_5:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[VAL_0]], i32 0, i32 0
// CHECK: %[[VAL_6:.*]] = load ptr, ptr %[[VAL_5]]
// CHECK: %[[VAL_7:.*]] = getelementptr i8, ptr %[[VAL_6]], i64 %[[VAL_4]]
// CHECK: %[[VAL_8:.*]] = getelementptr %t, ptr %[[VAL_7]], i32 0, i32 1
// CHECK: %[[VAL_7:.*]] = getelementptr nusw nuw i8, ptr %[[VAL_6]], i64 %[[VAL_4]]
// CHECK: %[[VAL_8:.*]] = getelementptr nusw nuw %t, ptr %[[VAL_7]], i32 0, i32 1
// CHECK: call void @take_int(ptr %[[VAL_8]])

View File

@ -0,0 +1,35 @@
// RUN: fir-opt --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
// Verify when nuw/nusw are added for array coordinate lowering where appropriate.
func.func @ext_array_coor_nuw_eligible(%arg0: !fir.ref<!fir.array<?xi32>>) {
%c0 = arith.constant 0 : i64
%0 = fircg.ext_array_coor %arg0(%c0) <%c0> : (!fir.ref<!fir.array<?xi32>>, i64, i64) -> !fir.ref<i32>
return
}
// CHECK-LABEL: llvm.func @ext_array_coor_nuw_eligible(
// CHECK: %[[VAL_0:.*]] = llvm.sub %{{.*}}, %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %[[VAL_1:.*]] = llvm.mul %[[VAL_0]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %[[VAL_2:.*]] = llvm.mul %[[VAL_1]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %[[VAL_3:.*]] = llvm.add %[[VAL_2]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %{{.*}}[%[[VAL_3]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// -----
func.func @ext_array_coor_shifted_nuw_ineligble(%arg0: !fir.ref<!fir.array<?xi32>>) {
%extent = arith.constant 10 : i64
%shift = arith.constant 1 : i64
%idx = arith.constant 3 : i64
%0 = fircg.ext_array_coor %arg0(%extent) origin %shift <%idx>
: (!fir.ref<!fir.array<?xi32>>, i64, i64, i64) -> !fir.ref<i32>
return
}
// CHECK-LABEL: llvm.func @ext_array_coor_shifted_nuw_ineligble(
// CHECK: %[[VAL_0:.*]] = llvm.sub %{{.*}}, %{{.*}} overflow<nsw> : i64
// CHECK: %[[VAL_1:.*]] = llvm.mul %[[VAL_0]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %[[VAL_2:.*]] = llvm.mul %[[VAL_1]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %[[VAL_3:.*]] = llvm.add %[[VAL_2]], %{{.*}} overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %{{.*}}[%[[VAL_3]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32

View File

@ -10,7 +10,7 @@ func.func @f1(%a : !fir.ref<!fir.array<?x?xf32>>, %n : index, %m : index, %o : i
%r = fir.do_loop %j = %p to %m step %c1 iter_args(%v1 = %vIn) -> !fir.array<?x?xf32> {
// CHECK: = icmp sgt
%r = fir.do_loop %i = %o to %n step %c1 iter_args(%v = %v1) -> !fir.array<?x?xf32> {
// CHECK: %[[AOFF:.*]] = getelementptr float, ptr %[[A]], i64
// CHECK: %[[AOFF:.*]] = getelementptr nusw nuw float, ptr %[[A]], i64
// CHECK: store float %[[F]], ptr %[[AOFF]]
%r = fir.array_update %v, %f, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
fir.result %r : !fir.array<?x?xf32>
@ -35,7 +35,7 @@ func.func @f2(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
%r = fir.do_loop %i = %o to %n step %c1 iter_args(%v = %v1) -> !fir.array<?x?xf32> {
%x = fir.array_fetch %wIn, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
%y = arith.addf %x, %f : f32
// CHECK: %[[AOFF:.*]] = getelementptr float, ptr %[[A]], i64
// CHECK: %[[AOFF:.*]] = getelementptr nusw nuw float, ptr %[[A]], i64
%r = fir.array_update %v, %y, %i, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
fir.result %r : !fir.array<?x?xf32>
}
@ -59,7 +59,7 @@ func.func @f3(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
%r = fir.do_loop %i = %o to %n step %c1 iter_args(%v = %v1) -> !fir.array<?x?xf32> {
%x = fir.array_fetch %wIn, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
%y = arith.addf %x, %f : f32
// CHECK: %[[AOFF:.*]] = getelementptr float, ptr %[[A]], i64
// CHECK: %[[AOFF:.*]] = getelementptr nusw nuw float, ptr %[[A]], i64
%i2 = arith.addi %i, %c1 : index
%r = fir.array_update %v, %y, %i2, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
fir.result %r : !fir.array<?x?xf32>
@ -86,7 +86,7 @@ func.func @f4(%a : !fir.ref<!fir.array<?x?xf32>>, %b : !fir.ref<!fir.array<?x?xf
%x = fir.array_fetch %wIn, %i, %j : (!fir.array<?x?xf32>, index, index) -> f32
%y = arith.addf %x, %f : f32
%y2 = arith.addf %y, %x2 : f32
// CHECK: %[[AOFF:.*]] = getelementptr float, ptr %[[A]], i64
// CHECK: %[[AOFF:.*]] = getelementptr nusw nuw float, ptr %[[A]], i64
%i2 = arith.addi %i, %c1 : index
%r = fir.array_update %v, %y2, %i2, %j : (!fir.array<?x?xf32>, f32, index, index) -> !fir.array<?x?xf32>
fir.result %r : !fir.array<?x?xf32>
@ -114,11 +114,11 @@ func.func @f5(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: !fir.box<!fir.array<?xf
%4 = fir.do_loop %arg3 = %c0 to %1 step %c1 iter_args(%arg4 = %2) -> (!fir.array<?xf32>) {
// CHECK: %[[B_STRIDE_GEP:.*]] = getelementptr {{.*}}, ptr %[[B]], i32 0, i32 7, i32 0, i32 2
// CHECK: %[[B_STRIDE:.*]] = load i64, ptr %[[B_STRIDE_GEP]]
// CHECK: %[[B_DIM_OFFSET:.*]] = mul nsw i64 %{{.*}}, %[[B_STRIDE]]
// CHECK: %[[B_OFFSET:.*]] = add nsw i64 %[[B_DIM_OFFSET]], 0
// CHECK: %[[B_DIM_OFFSET:.*]] = mul nuw nsw i64 %{{.*}}, %[[B_STRIDE]]
// CHECK: %[[B_OFFSET:.*]] = add nuw nsw i64 %[[B_DIM_OFFSET]], 0
// CHECK: %[[B_BASE_GEP:.*]] = getelementptr {{.*}}, ptr %{{.*}}, i32 0, i32 0
// CHECK: %[[B_BASE:.*]] = load ptr, ptr %[[B_BASE_GEP]]
// CHECK: %[[B_VOID_ADDR:.*]] = getelementptr i8, ptr %[[B_BASE]], i64 %[[B_OFFSET]]
// CHECK: %[[B_VOID_ADDR:.*]] = getelementptr nusw nuw i8, ptr %[[B_BASE]], i64 %[[B_OFFSET]]
// CHECK: %[[B_VAL:.*]] = load float, ptr %[[B_VOID_ADDR]]
// CHECK: fadd float %[[B_VAL]], %[[F]]
%5 = fir.array_fetch %3, %arg3 : (!fir.array<?xf32>, index) -> f32
@ -174,7 +174,7 @@ func.func @f7(%arg0: !fir.ref<f32>, %arg1: !fir.box<!fir.array<?xf32>>) {
%0 = fir.shift %c4 : (index) -> !fir.shift<1>
// CHECK: %[[STRIDE_GEP:.*]] = getelementptr {{.*}}, ptr %[[Y]], i32 0, i32 7, i32 0, i32 2
// CHECK: %[[STRIDE:.*]] = load i64, ptr %[[STRIDE_GEP]]
// CHECK: mul nsw i64 96, %[[STRIDE]]
// CHECK: mul nuw nsw i64 96, %[[STRIDE]]
%1 = fir.array_coor %arg1(%0) %c100 : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, index) -> !fir.ref<f32>
%2 = fir.load %1 : !fir.ref<f32>
fir.store %2 to %arg0 : !fir.ref<f32>
@ -191,7 +191,7 @@ func.func @f8(%a : !fir.ref<!fir.array<2x2x!fir.type<t{i:i32}>>>, %i : i32) {
%1 = fir.field_index i, !fir.type<t{i:i32}>
%2 = fir.shape %c2, %c2 : (index, index) -> !fir.shape<2>
%3 = fir.slice %c1, %c2, %c1, %c1, %c2, %c1 path %1 : (index, index, index, index, index, index, !fir.field) -> !fir.slice<2>
// CHECK: %[[GEP:.*]] = getelementptr %t, ptr %[[A]], i64 0, i32 0
// CHECK: %[[GEP:.*]] = getelementptr nusw nuw %t, ptr %[[A]], i64 0, i32 0
%4 = fir.array_coor %a(%2) [%3] %c1, %c1 : (!fir.ref<!fir.array<2x2x!fir.type<t{i:i32}>>>, !fir.shape<2>, !fir.slice<2>, index, index) -> !fir.ref<i32>
// CHECK: store i32 %[[I]], ptr %[[GEP]], align 4
fir.store %i to %4 : !fir.ref<i32>
@ -204,8 +204,8 @@ func.func @f8(%a : !fir.ref<!fir.array<2x2x!fir.type<t{i:i32}>>>, %i : i32) {
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
// CHECK: %[[OFFSET:.*]] = mul nsw i64 %{{.*}}, %[[CAST]]
// CHECK: getelementptr i8, ptr %[[C]], i64 %[[OFFSET]]
// CHECK: %[[OFFSET:.*]] = mul nuw nsw i64 %{{.*}}, %[[CAST]]
// CHECK: getelementptr nusw nuw i8, ptr %[[C]], i64 %[[OFFSET]]
%a = fir.array_coor %c(%s) %j, %j typeparams %i : (!fir.ref<!fir.array<?x?x!fir.char<1,?>>>, !fir.shape<2>, i64, i64, i32) -> !fir.ref<!fir.char<1,?>>
return %a : !fir.ref<!fir.char<1,?>>
}

View File

@ -68,11 +68,11 @@
// CHECK: %[[VAL10:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL11:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL12:.*]] = llvm.sub %[[VAL2]], %[[VAL6]] overflow<nsw> : i64
// CHECK: %[[VAL13:.*]] = llvm.mul %[[VAL12]], %[[VAL10]] overflow<nsw> : i64
// CHECK: %[[VAL14:.*]] = llvm.mul %[[VAL13]], %[[VAL10]] overflow<nsw> : i64
// CHECK: %[[VAL15:.*]] = llvm.add %[[VAL14]], %[[VAL11]] overflow<nsw> : i64
// CHECK: %[[VAL16:.*]] = llvm.mul %[[VAL10]], %[[VAL8]] overflow<nsw> : i64
// CHECK: %[[VAL17:.*]] = llvm.getelementptr %[[VAL4]][%[[VAL15]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[VAL13:.*]] = llvm.mul %[[VAL12]], %[[VAL10]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL14:.*]] = llvm.mul %[[VAL13]], %[[VAL10]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL15:.*]] = llvm.add %[[VAL14]], %[[VAL11]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL16:.*]] = llvm.mul %[[VAL10]], %[[VAL8]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL17:.*]] = llvm.getelementptr nusw|nuw %[[VAL4]][%[[VAL15]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[VAL18:.*]] = llvm.load %[[VAL17]] {nontemporal} : !llvm.ptr -> i32
// CHECK: %[[VAL19:.*]] = llvm.load %{{.*}} : !llvm.ptr -> i32
// CHECK: %[[VAL20:.*]] = llvm.add %[[VAL18]], %[[VAL19]] : i32

View File

@ -2223,11 +2223,11 @@ func.func @ext_array_coor0(%arg0: !fir.ref<!fir.array<?xi32>>) {
// CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw> : i64
// CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// Conversion with shift and slice.
@ -2243,12 +2243,12 @@ func.func @ext_array_coor1(%arg0: !fir.ref<!fir.array<?xi32>>) {
// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C0]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] overflow<nsw, nuw> : i64
// CHECK: %[[ADJ:.*]] = llvm.sub %[[C0]], %[[C0]] overflow<nsw> : i64
// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw> : i64
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw> : i64
// CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw, nuw> : i64
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// Conversion for a dynamic length char.
@ -2263,11 +2263,11 @@ func.func @ext_array_coor2(%arg0: !fir.ref<!fir.array<?x!fir.char<1,?>>>) {
// CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw> : i64
// CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// Conversion for a `fir.box`.
@ -2282,15 +2282,15 @@ func.func @ext_array_coor3(%arg0: !fir.box<!fir.array<?xi32>>) {
// CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[GEPSTRIDE:.*]] = llvm.getelementptr %[[ARG0]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
// CHECK: %[[LOADEDSTRIDE:.*]] = llvm.load %[[GEPSTRIDE]] : !llvm.ptr -> i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[LOADEDSTRIDE]] overflow<nsw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw> : i64
// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[LOADEDSTRIDE]] overflow<nsw, nuw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow<nsw, nuw> : i64
// CHECK: %[[GEPADDR:.*]] = llvm.getelementptr %[[ARG0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>
// CHECK: %[[LOADEDADDR:.*]] = llvm.load %[[GEPADDR]] : !llvm.ptr -> !llvm.ptr
// CHECK: %[[GEPADDROFFSET:.*]] = llvm.getelementptr %[[LOADEDADDR]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// CHECK: %[[GEPADDROFFSET:.*]] = llvm.getelementptr nusw|nuw %[[LOADEDADDR]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// Conversion with non zero shift and slice.
@ -2312,12 +2312,12 @@ func.func @ext_array_coor4(%arg0: !fir.ref<!fir.array<100xi32>>) {
// CHECK: %[[C1_1:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[IDX:.*]] = llvm.sub %[[C1]], %[[C0]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw> : i64
// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow<nsw, nuw> : i64
// CHECK: %[[ADJ:.*]] = llvm.sub %[[C10]], %[[C0]] overflow<nsw> : i64
// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw> : i64
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] overflow<nsw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw> : i64
// CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow<nsw, nuw> : i64
// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] overflow<nsw, nuw> : i64
// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow<nsw, nuw> : i64
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// Conversion with index type shape and slice
@ -2330,14 +2330,14 @@ func.func @ext_array_coor5(%arg0: !fir.ref<!fir.array<?xi32>>, %idx1 : index, %i
// CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw> : i64
// CHECK: %[[VAL_16:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_13]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_16:.*]] = llvm.getelementptr nusw|nuw %[[VAL_0]][%[[VAL_13]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: }
// Conversion for 3-d array
@ -2351,28 +2351,28 @@ func.func @ext_array_coor6(%arg0: !fir.ref<!fir.array<?x?x?xi32>>, %idx1 : index
// CHECK-SAME: %[[VAL_0:.*]]: !llvm.ptr, %[[VAL_1:.*]]: i64, %[[VAL_2:.*]]: i64, %[[VAL_3:.*]]: i64, %[[VAL_4:.*]]: i64, %[[VAL_5:.*]]: i64) {
// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_7:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw> : i64
// CHECK: %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]] overflow<nsw> : i64
// CHECK: %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]] overflow<nsw> : i64
// CHECK: %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]] overflow<nsw> : i64
// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]] overflow<nsw> : i64
// CHECK: %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]] overflow<nsw> : i64
// CHECK: %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]] overflow<nsw> : i64
// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw> : i64
// CHECK: %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]] overflow<nsw> : i64
// CHECK: %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]] overflow<nsw> : i64
// CHECK: %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]] overflow<nsw> : i64
// CHECK: %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]] overflow<nsw> : i64
// CHECK: %[[VAL_30:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_27]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_30:.*]] = llvm.getelementptr nusw|nuw %[[VAL_0]][%[[VAL_27]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32
// CHECK: llvm.return
// CHECK: }
@ -2389,14 +2389,14 @@ func.func @ext_array_coor_dt_slice(%arg0: !fir.ref<!fir.array<20x!fir.type<_QFte
// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(0 : i32) : i32
// CHECK: %[[VAL_7:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_9:.*]] = llvm.sub %[[VAL_5]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.mul %[[VAL_9]], %[[VAL_4]] overflow<nsw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.sub %[[VAL_2]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_10]], %[[VAL_11]] overflow<nsw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.mul %[[VAL_12]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.add %[[VAL_13]], %[[VAL_8]] overflow<nsw> : i64
// CHECK: %[[VAL_15:.*]] = llvm.mul %[[VAL_7]], %[[VAL_1]] overflow<nsw> : i64
// CHECK: %[[VAL_17:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_14]], 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_sliceTt", (i32, i32)>
// CHECK: %[[VAL_9:.*]] = llvm.sub %[[VAL_5]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.mul %[[VAL_9]], %[[VAL_4]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_11:.*]] = llvm.sub %[[VAL_2]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_10]], %[[VAL_11]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_13:.*]] = llvm.mul %[[VAL_12]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_14:.*]] = llvm.add %[[VAL_13]], %[[VAL_8]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_15:.*]] = llvm.mul %[[VAL_7]], %[[VAL_1]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_17:.*]] = llvm.getelementptr nusw|nuw %[[VAL_0]][%[[VAL_14]], 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_sliceTt", (i32, i32)>
// CHECK: llvm.return
// CHECK: }
@ -2410,7 +2410,7 @@ func.func @ext_array_coor_dt_slice2(%arg0: !fir.ref<!fir.array<2x!fir.type<_QFte
// CHECK-LABEL: llvm.func @ext_array_coor_dt_slice2(
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr, %[[IDX1:.*]]: i64, %[[IDX2:.*]]: i64, %[[IDX3:.*]]: i64, %[[IDX4:.*]]: i64, %[[IDX5:.*]]: i64, %[[IDX6:.*]]: i64, %[[IDX7:.*]]: i64) {
// CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%{{.*}}, 0, %[[IDX6]], %[[IDX5]]] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_slice2Tt", (array<3 x array<2 x i32>>)>
// CHECK: %{{.*}} = llvm.getelementptr nusw|nuw %[[ARG0]][%{{.*}}, 0, %[[IDX6]], %[[IDX5]]] : (!llvm.ptr, i64, i64, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_slice2Tt", (array<3 x array<2 x i32>>)>
// CHECK: llvm.return
// CHECK: }

View File

@ -31,11 +31,11 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
// CHECK-SAME: ptr {{[^%]*}}%[[ARG0:.*]]){{.*}}{
// [...]
// load a(2):
// CHECK: %[[VAL20:.*]] = getelementptr i8, ptr %{{.*}}, i64 %{{.*}}
// CHECK: %[[VAL20:.*]] = getelementptr nusw nuw i8, ptr %{{.*}}, i64 %{{.*}}
// CHECK: %[[A2:.*]] = load i32, ptr %[[VAL20]], align 4, !tbaa ![[A_ACCESS_TAG:.*]]
// [...]
// store a(2) to a(1):
// CHECK: %[[A1:.*]] = getelementptr i8, ptr %{{.*}}, i64 %{{.*}}
// CHECK: %[[A1:.*]] = getelementptr nusw nuw i8, ptr %{{.*}}, i64 %{{.*}}
// CHECK: store i32 %[[A2]], ptr %[[A1]], align 4, !tbaa ![[A_ACCESS_TAG]]
// CHECK: ret void
// CHECK: }

View File

@ -94,11 +94,11 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
// CHECK: %[[VAL40:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %{{.*}}, i32 0, i32 0
// box access:
// CHECK: %[[VAL41:.*]] = load ptr, ptr %[[VAL40]], align 8, !tbaa ![[BOX_ACCESS_TAG]]
// CHECK: %[[VAL42:.*]] = getelementptr i8, ptr %[[VAL41]], i64 %{{.*}}
// CHECK: %[[VAL42:.*]] = getelementptr nusw nuw i8, ptr %[[VAL41]], i64 %{{.*}}
// access to 'a':
// CHECK: %[[VAL43:.*]] = load i32, ptr %[[VAL42]], align 4, !tbaa ![[A_ACCESS_TAG:.*]]
// [...]
// CHECK: %[[VAL50:.*]] = getelementptr i32, ptr %{{.*}}, i64 %{{.*}}
// CHECK: %[[VAL50:.*]] = getelementptr nusw nuw i32, ptr %{{.*}}, i64 %{{.*}}
// store to the temporary:
// CHECK: store i32 %{{.*}}, ptr %[[VAL50]], align 4, !tbaa ![[TMP_DATA_ACCESS_TAG:.*]]
// [...]

View File

@ -338,15 +338,15 @@ func.func @tbaa(%arg0: !fir.box<!fir.array<?xi32>>) {
// CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_2:.*]] = llvm.mlir.constant(1 : i64) : i64
// CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(0 : i64) : i64
// CHECK: %[[VAL_4:.*]] = llvm.sub %[[VAL_1]], %[[VAL_2]] overflow<nsw> : i64
// CHECK: %[[VAL_5:.*]] = llvm.mul %[[VAL_4]], %[[VAL_2]] overflow<nsw> : i64
// CHECK: %[[VAL_4:.*]] = llvm.sub %[[VAL_1]], %[[VAL_2]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_5:.*]] = llvm.mul %[[VAL_4]], %[[VAL_2]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_6:.*]] = llvm.getelementptr %[[VAL_0]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
// CHECK: %[[VAL_7:.*]] = llvm.load %[[VAL_6]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr -> i64
// CHECK: %[[VAL_8:.*]] = llvm.mul %[[VAL_5]], %[[VAL_7]] overflow<nsw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_8]], %[[VAL_3]] overflow<nsw> : i64
// CHECK: %[[VAL_8:.*]] = llvm.mul %[[VAL_5]], %[[VAL_7]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_8]], %[[VAL_3]] overflow<nsw, nuw> : i64
// CHECK: %[[VAL_10:.*]] = llvm.getelementptr %[[VAL_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>
// CHECK: %[[VAL_11:.*]] = llvm.load %[[VAL_10]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr -> !llvm.ptr
// CHECK: %[[VAL_13:.*]] = llvm.getelementptr %[[VAL_11]]{{\[}}%[[VAL_9]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// CHECK: %[[VAL_13:.*]] = llvm.getelementptr nusw|nuw %[[VAL_11]]{{\[}}%[[VAL_9]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8
// CHECK: llvm.return
// CHECK: }

View File

@ -27,7 +27,7 @@ func.func @no_shape_merge(%cdt: i1, %from: !fir.ref<!fir.array<?xf64>>, %to : !f
// Note: block merging happens in the output below, but after FIR codegen.
// CHECK-LABEL: define void @no_shape_merge(
// CHECK: %[[GEP:.*]] = getelementptr i8, ptr %{{.*}}
// CHECK: %[[GEP:.*]] = getelementptr nusw nuw i8, ptr %{{.*}}
// CHECK: %[[LOAD:.*]] = load double, ptr %[[GEP]]
// CHECK: store double %[[LOAD]], ptr %{{.*}}
// CHECK: ret void

View File

@ -816,11 +816,11 @@ end subroutine mapType_common_block_members
!CHECK: %[[GEP_DESC_PTR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 0
!CHECK: %[[SZ_CALC_1:.*]] = load ptr, ptr %[[GEP_DESC_PTR]], align 8
!CHECK: %[[SZ_CALC_2:.*]] = sub nsw i64 2, %[[LOAD_LB]]
!CHECK: %[[SZ_CALC_3:.*]] = mul nsw i64 %[[SZ_CALC_2]], 1
!CHECK: %[[SZ_CALC_4:.*]] = mul nsw i64 %[[SZ_CALC_3]], 1
!CHECK: %[[SZ_CALC_5:.*]] = add nsw i64 %[[SZ_CALC_4]], 0
!CHECK: %[[SZ_CALC_6:.*]] = mul nsw i64 1, %[[LOAD_UB]]
!CHECK: %[[SZ_CALC_7:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_1]], i64 %[[SZ_CALC_5]]
!CHECK: %[[SZ_CALC_3:.*]] = mul nuw nsw i64 %[[SZ_CALC_2]], 1
!CHECK: %[[SZ_CALC_4:.*]] = mul nuw nsw i64 %[[SZ_CALC_3]], 1
!CHECK: %[[SZ_CALC_5:.*]] = add nuw nsw i64 %[[SZ_CALC_4]], 0
!CHECK: %[[SZ_CALC_6:.*]] = mul nuw nsw i64 1, %[[LOAD_UB]]
!CHECK: %[[SZ_CALC_7:.*]] = getelementptr nusw nuw %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_1]], i64 %[[SZ_CALC_5]]
!CHECK: %[[SZ_CALC_8:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_7]], i32 0, i32 2
!CHECK: %[[OFF_PTR_4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[SZ_CALC_8]], i32 0, i32 0
!CHECK: %[[OFF_PTR_CALC_1:.*]] = sub i64 %[[OFF_PTR_CALC_0]], 0

View File

@ -43,8 +43,8 @@ End Program
! ...
! check that we use the private copy of table for table/=50
! CHECK: omp.par.region3:
! CHECK: %[[VAL_44:.*]] = sub nsw i64 %{{.*}}, 1
! CHECK: %[[VAL_45:.*]] = mul nsw i64 %[[VAL_44]], 1
! CHECK: %[[VAL_46:.*]] = mul nsw i64 %[[VAL_45]], 1
! CHECK: %[[VAL_47:.*]] = add nsw i64 %[[VAL_46]], 0
! CHECK: %[[VAL_48:.*]] = getelementptr i32, ptr %[[PRIV_TABLE]], i64 %[[VAL_47]]
! CHECK: %[[VAL_44:.*]] = sub nuw nsw i64 %{{.*}}, 1
! CHECK: %[[VAL_45:.*]] = mul nuw nsw i64 %[[VAL_44]], 1
! CHECK: %[[VAL_46:.*]] = mul nuw nsw i64 %[[VAL_45]], 1
! CHECK: %[[VAL_47:.*]] = add nuw nsw i64 %[[VAL_46]], 0
! CHECK: %[[VAL_48:.*]] = getelementptr nusw nuw i32, ptr %[[PRIV_TABLE]], i64 %[[VAL_47]]

View File

@ -10,11 +10,11 @@ subroutine ivdep_test1
!CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT:.*]]
!CHECK: %[[VAL_8:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT]]
!CHECK: %[[VAL_9:.*]] = sext i32 %[[VAL_8]] to i64
!CHECK: %[[VAL_10:.*]] = sub nsw i64 %[[VAL_9]], 1
!CHECK: %[[VAL_11:.*]] = mul nsw i64 %[[VAL_10]], 1
!CHECK: %[[VAL_12:.*]] = mul nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = add nsw i64 %[[VAL_12]], 0
!CHECK: %[[VAL_14:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_13]]
!CHECK: %[[VAL_10:.*]] = sub nuw nsw i64 %[[VAL_9]], 1
!CHECK: %[[VAL_11:.*]] = mul nuw nsw i64 %[[VAL_10]], 1
!CHECK: %[[VAL_12:.*]] = mul nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = add nuw nsw i64 %[[VAL_12]], 0
!CHECK: %[[VAL_14:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_13]]
!CHECK: store i32 %[[VAL_8]], ptr %[[VAL_14]], align 4, !llvm.access.group [[DISTRINCT]]
!CHECK: %[[VAL_15:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT]]
!CHECK: %[[VAL_16:.*]] = add nsw i32 %[[VAL_15]], 1
@ -35,24 +35,24 @@ subroutine ivdep_test2
!CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1:.*]]
!CHECK: %[[VAL_10:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]]
!CHECK: %[[VAL_11:.*]] = sext i32 %[[VAL_10]] to i64
!CHECK: %[[VAL_12:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = mul nsw i64 %[[VAL_12]], 1
!CHECK: %[[VAL_14:.*]] = mul nsw i64 %[[VAL_13]], 1
!CHECK: %[[VAL_15:.*]] = add nsw i64 %[[VAL_14]], 0
!CHECK: %[[VAL_16:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_15]]
!CHECK: %[[VAL_12:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = mul nuw nsw i64 %[[VAL_12]], 1
!CHECK: %[[VAL_14:.*]] = mul nuw nsw i64 %[[VAL_13]], 1
!CHECK: %[[VAL_15:.*]] = add nuw nsw i64 %[[VAL_14]], 0
!CHECK: %[[VAL_16:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_15]]
!CHECK: %[[VAL_17:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]]
!CHECK: %[[VAL_18:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_19:.*]] = mul nsw i64 %[[VAL_18]], 1
!CHECK: %[[VAL_20:.*]] = mul nsw i64 %[[VAL_19]], 1
!CHECK: %[[VAL_21:.*]] = add nsw i64 %[[VAL_20]], 0
!CHECK: %[[VAL_22:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_21]]
!CHECK: %[[VAL_18:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_19:.*]] = mul nuw nsw i64 %[[VAL_18]], 1
!CHECK: %[[VAL_20:.*]] = mul nuw nsw i64 %[[VAL_19]], 1
!CHECK: %[[VAL_21:.*]] = add nuw nsw i64 %[[VAL_20]], 0
!CHECK: %[[VAL_22:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_21]]
!CHECK: %[[VAL_23:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]]
!CHECK: %[[VAL_24:.*]] = add i32 %[[VAL_17]], %[[VAL_23]]
!CHECK: %[[VAL_25:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_26:.*]] = mul nsw i64 %[[VAL_25]], 1
!CHECK: %[[VAL_27:.*]] = mul nsw i64 %[[VAL_26]], 1
!CHECK: %[[VAL_28:.*]] = add nsw i64 %[[VAL_27]], 0
!CHECK: %[[VAL_29:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_28]]
!CHECK: %[[VAL_25:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_26:.*]] = mul nuw nsw i64 %[[VAL_25]], 1
!CHECK: %[[VAL_27:.*]] = mul nuw nsw i64 %[[VAL_26]], 1
!CHECK: %[[VAL_28:.*]] = add nuw nsw i64 %[[VAL_27]], 0
!CHECK: %[[VAL_29:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_28]]
!CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT1]]
!CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT1]]
!CHECK: %[[VAL_31:.*]] = add nsw i32 %[[VAL_30]], 1
@ -73,24 +73,24 @@ subroutine ivdep_test3
!CHECK: store i32 {{.*}}, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2:.*]]
!CHECK: %[[VAL_10:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]]
!CHECK: %[[VAL_11:.*]] = sext i32 %[[VAL_10]] to i64
!CHECK: %[[VAL_12:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = mul nsw i64 %[[VAL_12]], 1
!CHECK: %[[VAL_14:.*]] = mul nsw i64 %[[VAL_13]], 1
!CHECK: %[[VAL_15:.*]] = add nsw i64 %[[VAL_14]], 0
!CHECK: %[[VAL_16:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_15]]
!CHECK: %[[VAL_12:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_13:.*]] = mul nuw nsw i64 %[[VAL_12]], 1
!CHECK: %[[VAL_14:.*]] = mul nuw nsw i64 %[[VAL_13]], 1
!CHECK: %[[VAL_15:.*]] = add nuw nsw i64 %[[VAL_14]], 0
!CHECK: %[[VAL_16:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_15]]
!CHECK: %[[VAL_17:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]]
!CHECK: %[[VAL_18:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_19:.*]] = mul nsw i64 %[[VAL_18]], 1
!CHECK: %[[VAL_20:.*]] = mul nsw i64 %[[VAL_19]], 1
!CHECK: %[[VAL_21:.*]] = add nsw i64 %[[VAL_20]], 0
!CHECK: %[[VAL_22:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_21]]
!CHECK: %[[VAL_18:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_19:.*]] = mul nuw nsw i64 %[[VAL_18]], 1
!CHECK: %[[VAL_20:.*]] = mul nuw nsw i64 %[[VAL_19]], 1
!CHECK: %[[VAL_21:.*]] = add nuw nsw i64 %[[VAL_20]], 0
!CHECK: %[[VAL_22:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_21]]
!CHECK: %[[VAL_23:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]]
!CHECK: %[[VAL_24:.*]] = add i32 %[[VAL_17]], %[[VAL_23]]
!CHECK: %[[VAL_25:.*]] = sub nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_26:.*]] = mul nsw i64 %[[VAL_25]], 1
!CHECK: %[[VAL_27:.*]] = mul nsw i64 %[[VAL_26]], 1
!CHECK: %[[VAL_28:.*]] = add nsw i64 %[[VAL_27]], 0
!CHECK: %[[VAL_29:.*]] = getelementptr i32, ptr {{.*}}, i64 %[[VAL_28]]
!CHECK: %[[VAL_25:.*]] = sub nuw nsw i64 %[[VAL_11]], 1
!CHECK: %[[VAL_26:.*]] = mul nuw nsw i64 %[[VAL_25]], 1
!CHECK: %[[VAL_27:.*]] = mul nuw nsw i64 %[[VAL_26]], 1
!CHECK: %[[VAL_28:.*]] = add nuw nsw i64 %[[VAL_27]], 0
!CHECK: %[[VAL_29:.*]] = getelementptr nusw nuw i32, ptr {{.*}}, i64 %[[VAL_28]]
!CHECK: store i32 %[[VAL_24]], ptr %[[VAL_29]], align 4, !llvm.access.group [[DISTRINCT2]]
!CHECK: call void @_QFivdep_test3Pfoo(), !llvm.access.group [[DISTRINCT2]]
!CHECK: %[[VAL_30:.*]] = load i32, ptr {{.*}}, align 4, !llvm.access.group [[DISTRINCT2]]

View File

@ -28,7 +28,7 @@ subroutine test_prefetch_01()
! LLVM: %[[LOAD_I:.*]] = load i32, ptr %[[VAR_I]], align 4
! LLVM: %{{.*}} = add nsw i32 %[[LOAD_I]], 64
! LLVM: %[[GEP_A:.*]] = getelementptr i32, ptr %[[VAR_A]], i64 {{.*}}
! LLVM: %[[GEP_A:.*]] = getelementptr nusw nuw i32, ptr %[[VAR_A]], i64 {{.*}}
! LLVM: call void @llvm.prefetch.p0(ptr %[[GEP_A]], i32 0, i32 3, i32 1)
! LLVM: call void @llvm.prefetch.p0(ptr %[[VAR_J]], i32 0, i32 3, i32 1)