From bdacd56fd1f4825cfe19cf8de0cf24a3d1ff18fa Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Fri, 8 Dec 2023 10:51:20 +0000 Subject: [flang][CodeGen] add nsw to address calculations (#74709) `nsw` is a flag for LLVM arithmetic operations meaning "no signed wrap". If this keyword is present, the result of the operation is a poison value if overflow occurs. Adding this keyword permits LLVM to re-order integer arithmetic more aggressively. In https://discourse.llvm.org/t/rfc-changes-to-fircg-xarray-coor-codegen-to-allow-better-hoisting/75257/16 @vzakhari observed that adding nsw is useful to enable hoisting of address calculations after some loops (or is at least a step in that direction). Classic flang also adds nsw to address calculations. --- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 41 ++++++---- flang/test/Fir/array-coor.fir | 12 +-- flang/test/Fir/arrexp.fir | 8 +- flang/test/Fir/convert-to-llvm.fir | 138 ++++++++++++++++---------------- flang/test/Fir/coordinateof.fir | 8 +- flang/test/Fir/tbaa.fir | 12 +-- 6 files changed, 115 insertions(+), 104 deletions(-) diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index bf175c8..293208c 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -2387,6 +2387,9 @@ struct XArrayCoorOpConversion const bool baseIsBoxed = coor.getMemref().getType().isa(); TypePair baseBoxTyPair = baseIsBoxed ? getBoxTypePair(coor.getMemref().getType()) : TypePair{}; + mlir::LLVM::IntegerOverflowFlagsAttr nsw = + mlir::LLVM::IntegerOverflowFlagsAttr::get( + rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); // For each dimension of the array, generate the offset calculation. for (unsigned i = 0; i < rank; ++i, ++indexOffset, ++shapeOffset, @@ -2407,14 +2410,15 @@ struct XArrayCoorOpConversion if (normalSlice) step = integerCast(loc, rewriter, idxTy, operands[sliceOffset + 2]); } - auto idx = rewriter.create(loc, idxTy, index, lb); + auto idx = rewriter.create(loc, idxTy, index, lb, nsw); mlir::Value diff = - rewriter.create(loc, idxTy, idx, step); + rewriter.create(loc, idxTy, idx, step, nsw); if (normalSlice) { mlir::Value sliceLb = integerCast(loc, rewriter, idxTy, operands[sliceOffset]); - auto adj = rewriter.create(loc, idxTy, sliceLb, lb); - diff = rewriter.create(loc, idxTy, diff, adj); + auto adj = + rewriter.create(loc, idxTy, sliceLb, lb, nsw); + diff = rewriter.create(loc, idxTy, diff, adj, nsw); } // Update the offset given the stride and the zero based index `diff` // that was just computed. @@ -2422,17 +2426,21 @@ struct XArrayCoorOpConversion // Use stride in bytes from the descriptor. mlir::Value stride = getStrideFromBox(loc, baseBoxTyPair, operands[0], i, rewriter); - auto sc = rewriter.create(loc, idxTy, diff, stride); - offset = rewriter.create(loc, idxTy, sc, offset); + auto sc = + rewriter.create(loc, idxTy, diff, stride, nsw); + offset = + rewriter.create(loc, idxTy, sc, offset, nsw); } else { // Use stride computed at last iteration. - auto sc = rewriter.create(loc, idxTy, diff, prevExt); - offset = rewriter.create(loc, idxTy, sc, offset); + auto sc = + rewriter.create(loc, idxTy, diff, prevExt, nsw); + offset = + rewriter.create(loc, idxTy, sc, offset, nsw); // Compute next stride assuming contiguity of the base array // (in element number). auto nextExt = integerCast(loc, rewriter, idxTy, operands[shapeOffset]); - prevExt = - rewriter.create(loc, idxTy, prevExt, nextExt); + prevExt = rewriter.create(loc, idxTy, prevExt, + nextExt, nsw); } } @@ -2491,8 +2499,8 @@ struct XArrayCoorOpConversion assert(coor.getLenParams().size() == 1); auto length = integerCast(loc, rewriter, idxTy, operands[coor.lenParamsOffset()]); - offset = - rewriter.create(loc, idxTy, offset, length); + offset = rewriter.create(loc, idxTy, offset, + length, nsw); } else { TODO(loc, "compute size of derived type with type parameters"); } @@ -2665,6 +2673,9 @@ private: auto cpnTy = fir::dyn_cast_ptrOrBoxEleTy(boxObjTy); mlir::Type llvmPtrTy = ::getLlvmPtrType(coor.getContext()); mlir::Type byteTy = ::getI8Type(coor.getContext()); + mlir::LLVM::IntegerOverflowFlagsAttr nsw = + mlir::LLVM::IntegerOverflowFlagsAttr::get( + rewriter.getContext(), mlir::LLVM::IntegerOverflowFlags::nsw); for (unsigned i = 1, last = operands.size(); i < last; ++i) { if (auto arrTy = cpnTy.dyn_cast()) { @@ -2680,9 +2691,9 @@ private: index < lastIndex; ++index) { mlir::Value stride = getStrideFromBox(loc, boxTyPair, operands[0], index - i, rewriter); - auto sc = rewriter.create(loc, idxTy, - operands[index], stride); - off = rewriter.create(loc, idxTy, sc, off); + auto sc = rewriter.create( + loc, idxTy, operands[index], stride, nsw); + off = rewriter.create(loc, idxTy, sc, off, nsw); } resultAddr = rewriter.create( loc, llvmPtrTy, byteTy, resultAddr, diff --git a/flang/test/Fir/array-coor.fir b/flang/test/Fir/array-coor.fir index 738acd7..a765670 100644 --- a/flang/test/Fir/array-coor.fir +++ b/flang/test/Fir/array-coor.fir @@ -9,12 +9,12 @@ func.func @array_coor_box_value(%29 : !fir.box>, } // CHECK-LABEL: define double @array_coor_box_value -// CHECK: %[[t3:.*]] = sub i64 %{{.*}}, 1 -// CHECK: %[[t4:.*]] = mul i64 %[[t3]], 1 +// CHECK: %[[t3:.*]] = sub nsw i64 %{{.*}}, 1 +// CHECK: %[[t4:.*]] = mul 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 i64 %[[t4]], %[[t6]] -// CHECK: %[[t8:.*]] = add i64 %[[t7]], 0 +// CHECK: %[[t7:.*]] = mul nsw i64 %[[t4]], %[[t6]] +// CHECK: %[[t8:.*]] = add 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]] @@ -36,8 +36,8 @@ func.func private @take_int(%arg0: !fir.ref) -> () // 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 i64 1, %[[VAL_2]] -// CHECK: %[[VAL_4:.*]] = add i64 %[[VAL_3]], 0 +// CHECK: %[[VAL_3:.*]] = mul nsw i64 1, %[[VAL_2]] +// CHECK: %[[VAL_4:.*]] = add 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]] diff --git a/flang/test/Fir/arrexp.fir b/flang/test/Fir/arrexp.fir index 87a2763..5d265a5 100644 --- a/flang/test/Fir/arrexp.fir +++ b/flang/test/Fir/arrexp.fir @@ -114,8 +114,8 @@ func.func @f5(%arg0: !fir.box>, %arg1: !fir.box (!fir.array) { // 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 i64 %{{.*}}, %[[B_STRIDE]] - // CHECK: %[[B_OFFSET:.*]] = add i64 %[[B_DIM_OFFSET]], 0 + // CHECK: %[[B_DIM_OFFSET:.*]] = mul nsw i64 %{{.*}}, %[[B_STRIDE]] + // CHECK: %[[B_OFFSET:.*]] = add 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]] @@ -172,7 +172,7 @@ func.func @f7(%arg0: !fir.ref, %arg1: !fir.box>) { %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 i64 96, %[[STRIDE]] + // CHECK: mul nsw i64 96, %[[STRIDE]] %1 = fir.array_coor %arg1(%0) %c100 : (!fir.box>, !fir.shift<1>, index) -> !fir.ref %2 = fir.load %1 : !fir.ref fir.store %2 to %arg0 : !fir.ref @@ -202,7 +202,7 @@ func.func @f8(%a : !fir.ref>>, %i : i32) { func.func @f9(%i: i32, %e : i64, %j: i64, %c: !fir.ref>>) -> !fir.ref> { %s = fir.shape %e, %e : (i64, i64) -> !fir.shape<2> // CHECK: %[[CAST:.*]] = sext i32 %[[I]] to i64 - // CHECK: %[[OFFSET:.*]] = mul i64 %{{.*}}, %[[CAST]] + // CHECK: %[[OFFSET:.*]] = mul nsw i64 %{{.*}}, %[[CAST]] // CHECK: getelementptr i8, ptr %[[C]], i64 %[[OFFSET]] %a = fir.array_coor %c(%s) %j, %j typeparams %i : (!fir.ref>>, !fir.shape<2>, i64, i64, i32) -> !fir.ref> return %a : !fir.ref> diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir index 993058e..be82ffa 100644 --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -2027,10 +2027,10 @@ func.func @ext_array_coor0(%arg0: !fir.ref>) { // 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]] : i64 -// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64 -// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] : i64 +// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow : i64 +// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow : i64 +// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow : i64 // CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32 // Conversion with shift and slice. @@ -2046,12 +2046,12 @@ func.func @ext_array_coor1(%arg0: !fir.ref>) { // 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]], %[[C0]] : i64 -// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] : i64 -// CHECK: %[[ADJ:.*]] = llvm.sub %[[C0]], %[[C0]] : i64 -// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] : i64 -// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] : i64 +// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C0]] overflow : i64 +// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C0]] overflow : i64 +// CHECK: %[[ADJ:.*]] = llvm.sub %[[C0]], %[[C0]] overflow : i64 +// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow : i64 +// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow : i64 // CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32 // Conversion for a dynamic length char. @@ -2067,10 +2067,10 @@ func.func @ext_array_coor2(%arg0: !fir.ref>>) { // 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]] : i64 -// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64 -// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] : i64 +// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow : i64 +// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow : i64 +// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[C1]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow : i64 // CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // Conversion for a `fir.box`. @@ -2086,12 +2086,12 @@ func.func @ext_array_coor3(%arg0: !fir.box>) { // 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]] : i64 -// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64 +// CHECK: %[[IDX:.*]] = llvm.sub %[[C0]], %[[C1]] overflow : i64 +// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow : 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]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] : i64 +// CHECK: %[[SC:.*]] = llvm.mul %[[DIFF0]], %[[LOADEDSTRIDE]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[SC]], %[[C0_1]] overflow : 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 @@ -2115,12 +2115,12 @@ func.func @ext_array_coor4(%arg0: !fir.ref>) { // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[C1_1:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[C0_1:.*]] = llvm.mlir.constant(0 : i64) : i64 -// CHECK: %[[IDX:.*]] = llvm.sub %[[C1]], %[[C0]] : i64 -// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] : i64 -// CHECK: %[[ADJ:.*]] = llvm.sub %[[C10]], %[[C0]] : i64 -// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] : i64 -// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] : i64 +// CHECK: %[[IDX:.*]] = llvm.sub %[[C1]], %[[C0]] overflow : i64 +// CHECK: %[[DIFF0:.*]] = llvm.mul %[[IDX]], %[[C1]] overflow : i64 +// CHECK: %[[ADJ:.*]] = llvm.sub %[[C10]], %[[C0]] overflow : i64 +// CHECK: %[[DIFF1:.*]] = llvm.add %[[DIFF0]], %[[ADJ]] overflow : i64 +// CHECK: %[[STRIDE:.*]] = llvm.mul %[[DIFF1]], %[[C1_1]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[STRIDE]], %[[C0_1]] overflow : i64 // CHECK: %{{.*}} = llvm.getelementptr %[[ARG0]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32 // Conversion with index type shape and slice @@ -2134,13 +2134,13 @@ func.func @ext_array_coor5(%arg0: !fir.ref>, %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]] : i64 -// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] : i64 -// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] : i64 -// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] : i64 -// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] : i64 +// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow : i64 +// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow : i64 +// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow : i64 +// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow : i64 // CHECK: %[[VAL_16:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_13]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32 // CHECK: } @@ -2155,27 +2155,27 @@ func.func @ext_array_coor6(%arg0: !fir.ref>, %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]] : i64 -// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] : i64 -// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] : i64 -// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] : i64 -// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] : i64 -// CHECK: %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]] : i64 -// CHECK: %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]] : i64 -// CHECK: %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]] : i64 -// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]] : i64 -// CHECK: %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]] : i64 -// CHECK: %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]] : i64 -// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] : i64 -// CHECK: %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]] : i64 -// CHECK: %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]] : i64 -// CHECK: %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]] : i64 -// CHECK: %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]] : i64 +// CHECK: %[[VAL_8:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_9:.*]] = llvm.mul %[[VAL_8]], %[[VAL_4]] overflow : i64 +// CHECK: %[[VAL_10:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_11:.*]] = llvm.add %[[VAL_9]], %[[VAL_10]] overflow : i64 +// CHECK: %[[VAL_12:.*]] = llvm.mul %[[VAL_11]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_13:.*]] = llvm.add %[[VAL_12]], %[[VAL_7]] overflow : i64 +// CHECK: %[[VAL_14:.*]] = llvm.mul %[[VAL_6]], %[[VAL_1]] overflow : i64 +// CHECK: %[[VAL_15:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_16:.*]] = llvm.mul %[[VAL_15]], %[[VAL_4]] overflow : i64 +// CHECK: %[[VAL_17:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_18:.*]] = llvm.add %[[VAL_16]], %[[VAL_17]] overflow : i64 +// CHECK: %[[VAL_19:.*]] = llvm.mul %[[VAL_18]], %[[VAL_14]] overflow : i64 +// CHECK: %[[VAL_20:.*]] = llvm.add %[[VAL_19]], %[[VAL_13]] overflow : i64 +// CHECK: %[[VAL_21:.*]] = llvm.mul %[[VAL_14]], %[[VAL_1]] overflow : i64 +// CHECK: %[[VAL_22:.*]] = llvm.sub %[[VAL_5]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_23:.*]] = llvm.mul %[[VAL_22]], %[[VAL_4]] overflow : i64 +// CHECK: %[[VAL_24:.*]] = llvm.sub %[[VAL_2]], %[[VAL_6]] overflow : i64 +// CHECK: %[[VAL_25:.*]] = llvm.add %[[VAL_23]], %[[VAL_24]] overflow : i64 +// CHECK: %[[VAL_26:.*]] = llvm.mul %[[VAL_25]], %[[VAL_21]] overflow : i64 +// CHECK: %[[VAL_27:.*]] = llvm.add %[[VAL_26]], %[[VAL_20]] overflow : i64 +// CHECK: %[[VAL_28:.*]] = llvm.mul %[[VAL_21]], %[[VAL_1]] overflow : i64 // CHECK: %[[VAL_30:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_27]]] : (!llvm.ptr, i64) -> !llvm.ptr, i32 // CHECK: llvm.return // CHECK: } @@ -2193,13 +2193,13 @@ func.func @ext_array_coor_dt_slice(%arg0: !fir.ref : i64 +// CHECK: %[[VAL_10:.*]] = llvm.mul %[[VAL_9]], %[[VAL_4]] overflow : i64 +// CHECK: %[[VAL_11:.*]] = llvm.sub %[[VAL_2]], %[[VAL_7]] overflow : i64 +// CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_10]], %[[VAL_11]] overflow : i64 +// CHECK: %[[VAL_13:.*]] = llvm.mul %[[VAL_12]], %[[VAL_7]] overflow : i64 +// CHECK: %[[VAL_14:.*]] = llvm.add %[[VAL_13]], %[[VAL_8]] overflow : i64 +// CHECK: %[[VAL_15:.*]] = llvm.mul %[[VAL_7]], %[[VAL_1]] overflow : i64 // CHECK: %[[VAL_17:.*]] = llvm.getelementptr %[[VAL_0]][%[[VAL_14]], 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<"_QFtest_dt_sliceTt", (i32, i32)> // CHECK: llvm.return // CHECK: } @@ -2452,8 +2452,8 @@ func.func @coordinate_box_array_1d(%arg0: !fir.box>, %arg1: // Index of the 1st CFI_dim_t object (corresonds the the 1st dimension) // CHECK-NEXT: %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][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-NEXT: %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64 -// CHECK-NEXT: %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] : i64 -// CHECK-NEXT: %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] : i64 +// CHECK-NEXT: %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] overflow : i64 +// CHECK-NEXT: %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow : i64 // CHECK-NEXT: %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // CHECK-NEXT: llvm.return @@ -2471,8 +2471,8 @@ func.func @coordinate_of_box_dynamic_array_1d(%arg0: !fir.box !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK-NEXT: %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64 -// CHECK-NEXT: %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] : i64 -// CHECK-NEXT: %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] : i64 +// CHECK-NEXT: %[[BYTE_OFFSET:.*]] = llvm.mul %[[COORDINATE]], %[[DIM_1_MEM_STRIDE_VAL]] overflow : i64 +// CHECK-NEXT: %[[SUBOJECT_OFFSET:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow : i64 // CHECK-NEXT: %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOJECT_OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // CHECK-NEXT: llvm.return @@ -2492,13 +2492,13 @@ func.func @coordinate_box_array_2d(%arg0: !fir.box>, % // Index of the 1st CFI_dim_t object (corresonds the the 1st dimension) // CHECK-NEXT: %[[DIM_1_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK-NEXT: %[[DIM_1_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_1_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64 -// CHECK-NEXT: %[[BYTE_OFFSET_1:.*]] = llvm.mul %[[COORDINATE_1]], %[[DIM_1_MEM_STRIDE_VAL]] : i64 -// CHECK-NEXT: %[[SUBOBJECT_OFFSET_1:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] : i64 +// CHECK-NEXT: %[[BYTE_OFFSET_1:.*]] = llvm.mul %[[COORDINATE_1]], %[[DIM_1_MEM_STRIDE_VAL]] overflow : i64 +// CHECK-NEXT: %[[SUBOBJECT_OFFSET_1:.*]] = llvm.add %[[BYTE_OFFSET]], %[[OFFSET_INIT]] overflow : i64 // Index of the 1st CFI_dim_t object (corresonds the the 2nd dimension) // CHECK-NEXT: %[[DIM_2_MEM_STRIDE_ADDR:.*]] = llvm.getelementptr %[[BOX]][0, 7, 1, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK-NEXT: %[[DIM_2_MEM_STRIDE_VAL:.*]] = llvm.load %[[DIM_2_MEM_STRIDE_ADDR]] : !llvm.ptr -> i64 -// CHECK-NEXT: %[[BYTE_OFFSET_2:.*]] = llvm.mul %[[COORDINATE_2]], %[[DIM_2_MEM_STRIDE_VAL]] : i64 -// CHECK-NEXT: %[[SUBOBJECT_OFFSET_2:.*]] = llvm.add %[[BYTE_OFFSET_2]], %[[SUBOBJECT_OFFSET_1]] : i64 +// CHECK-NEXT: %[[BYTE_OFFSET_2:.*]] = llvm.mul %[[COORDINATE_2]], %[[DIM_2_MEM_STRIDE_VAL]] overflow : i64 +// CHECK-NEXT: %[[SUBOBJECT_OFFSET_2:.*]] = llvm.add %[[BYTE_OFFSET_2]], %[[SUBOBJECT_OFFSET_1]] overflow : i64 // CHECK-NEXT: %[[SUBOBJECT_ADDR:.*]] = llvm.getelementptr %[[ARRAY_OBJECT]][%[[SUBOBJECT_OFFSET_2]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // CHECK-NEXT: llvm.return @@ -2520,8 +2520,8 @@ func.func @coordinate_box_derived_inside_array(%arg0: !fir.box !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_14:.*]] = llvm.load %[[VAL_13]] : !llvm.ptr -> i64 -// CHECK: %[[VAL_15:.*]] = llvm.mul %[[COORDINATE_1]], %[[VAL_14]] : i64 -// CHECK: %[[OFFSET:.*]] = llvm.add %[[VAL_15]], %[[VAL_8]] : i64 +// CHECK: %[[VAL_15:.*]] = llvm.mul %[[COORDINATE_1]], %[[VAL_14]] overflow : i64 +// CHECK: %[[OFFSET:.*]] = llvm.add %[[VAL_15]], %[[VAL_8]] overflow : i64 // CHECK: %[[DERIVED:.*]] = llvm.getelementptr %[[ARRAY]][%[[OFFSET]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // CHECK: %[[VAL_20:.*]] = llvm.getelementptr %[[DERIVED]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"derived_3", (f32, f32)> // CHECK: llvm.return diff --git a/flang/test/Fir/coordinateof.fir b/flang/test/Fir/coordinateof.fir index c605f43..acb9fd5 100644 --- a/flang/test/Fir/coordinateof.fir +++ b/flang/test/Fir/coordinateof.fir @@ -30,8 +30,8 @@ func.func @foo3(%box : !fir.box>, %i : i32) -> i32 { // CHECK: %[[boxptr:.*]] = load ptr, ptr %[[gep0]] // CHECK: %[[gep1:.*]] = getelementptr { ptr, i64, {{.*}} i32 7 // CHECK: %[[stride:.*]] = load i64, ptr %[[gep1]] - // CHECK: %[[dimoffset:.*]] = mul i64 %[[cvt]], %[[stride]] - // CHECK: %[[offset:.*]] = add i64 %[[dimoffset]], 0 + // CHECK: %[[dimoffset:.*]] = mul nsw i64 %[[cvt]], %[[stride]] + // CHECK: %[[offset:.*]] = add nsw i64 %[[dimoffset]], 0 // CHECK: %[[gep2:.*]] = getelementptr i8, ptr %[[boxptr]], i64 %[[offset]] %1 = fir.coordinate_of %box, %ii : (!fir.box>, index) -> !fir.ref // CHECK: load i32, ptr %[[gep2]] @@ -68,8 +68,8 @@ func.func @foo6(%box : !fir.box>>>, %i : i64 // CHECK: %[[addr:.*]] = load ptr, ptr %[[addr_gep]] // CHECK: %[[stride_gep:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[box]], i32 0, i32 7, i32 0, i32 2 // CHECK: %[[stride:.*]] = load i64, ptr %[[stride_gep]] - // CHECK: %[[mul:.*]] = mul i64 %{{.*}}, %[[stride]] - // CHECK: %[[offset:.*]] = add i64 %[[mul]], 0 + // CHECK: %[[mul:.*]] = mul nsw i64 %{{.*}}, %[[stride]] + // CHECK: %[[offset:.*]] = add nsw i64 %[[mul]], 0 // CHECK: %[[gep:.*]] = getelementptr i8, ptr %[[addr]], i64 %[[offset]] %coor = fir.coordinate_of %box, %i : (!fir.box>>>, i64) -> !fir.ref> diff --git a/flang/test/Fir/tbaa.fir b/flang/test/Fir/tbaa.fir index bbc8a81..4474bbb 100644 --- a/flang/test/Fir/tbaa.fir +++ b/flang/test/Fir/tbaa.fir @@ -41,8 +41,8 @@ module { // CHECK: %[[VAL_8:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_9:.*]] = 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>>, ptr, array<1 x i64>)> // CHECK: %[[VAL_10:.*]] = llvm.load %[[VAL_9]] {tbaa = [#[[$BOXT]]]} : !llvm.ptr -> i64 -// CHECK: %[[VAL_11:.*]] = llvm.mul %[[VAL_4]], %[[VAL_10]] : i64 -// CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_11]], %[[VAL_8]] : i64 +// CHECK: %[[VAL_11:.*]] = llvm.mul %[[VAL_4]], %[[VAL_10]] overflow : i64 +// CHECK: %[[VAL_12:.*]] = llvm.add %[[VAL_11]], %[[VAL_8]] overflow : i64 // CHECK: %[[VAL_14:.*]] = llvm.getelementptr %[[VAL_7]]{{\[}}%[[VAL_12]]] : (!llvm.ptr, i64) -> !llvm.ptr, i8 // CHECK: %[[VAL_16:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[VAL_17:.*]] = llvm.mlir.constant(-1 : i32) : i32 @@ -330,12 +330,12 @@ func.func @tbaa(%arg0: !fir.box>) { // 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]] : i64 -// CHECK: %[[VAL_5:.*]] = llvm.mul %[[VAL_4]], %[[VAL_2]] : i64 +// CHECK: %[[VAL_4:.*]] = llvm.sub %[[VAL_1]], %[[VAL_2]] overflow : i64 +// CHECK: %[[VAL_5:.*]] = llvm.mul %[[VAL_4]], %[[VAL_2]] overflow : 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]] : i64 -// CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_8]], %[[VAL_3]] : i64 +// CHECK: %[[VAL_8:.*]] = llvm.mul %[[VAL_5]], %[[VAL_7]] overflow : i64 +// CHECK: %[[VAL_9:.*]] = llvm.add %[[VAL_8]], %[[VAL_3]] overflow : 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 -- cgit v1.1