mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 19:06:33 +00:00
[flang] fix MAXVAL(x%array_comp_with_custom_lower_bounds) (#129684)
The HLFIR inlining of MAXVAL kicks in at O1 and more when the argument is an array component reference but the implementation did not account for the rare cases where the array components have non default lower bounds. This patch fixes the issue by using `getElementAt` to compute the element address. Rename `indices` to `oneBasedIndices` for more clarity.
This commit is contained in:
parent
17f0aaac57
commit
9a659fac2f
@ -910,22 +910,25 @@ public:
|
||||
}
|
||||
|
||||
auto inlineSource =
|
||||
[elemental, &designate](
|
||||
fir::FirOpBuilder builder, mlir::Location loc,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &indices) -> mlir::Value {
|
||||
[elemental,
|
||||
&designate](fir::FirOpBuilder builder, mlir::Location loc,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
|
||||
-> mlir::Value {
|
||||
if (elemental) {
|
||||
// Inline the elemental and get the value from it.
|
||||
auto yield = inlineElementalOp(loc, builder, elemental, indices);
|
||||
auto yield =
|
||||
inlineElementalOp(loc, builder, elemental, oneBasedIndices);
|
||||
auto tmp = yield.getElementValue();
|
||||
yield->erase();
|
||||
return tmp;
|
||||
}
|
||||
if (designate) {
|
||||
// Create a designator over designator, then load the reference.
|
||||
auto resEntity = hlfir::Entity{designate.getResult()};
|
||||
auto tmp = builder.create<hlfir::DesignateOp>(
|
||||
loc, getVariableElementType(resEntity), designate, indices);
|
||||
return builder.create<fir::LoadOp>(loc, tmp);
|
||||
// Create a designator over the array designator, then load the
|
||||
// reference.
|
||||
mlir::Value elementAddr = hlfir::getElementAt(
|
||||
loc, builder, hlfir::Entity{designate.getResult()},
|
||||
oneBasedIndices);
|
||||
return builder.create<fir::LoadOp>(loc, elementAddr);
|
||||
}
|
||||
llvm_unreachable("unsupported type");
|
||||
};
|
||||
@ -936,38 +939,41 @@ public:
|
||||
GenBodyFn genBodyFn;
|
||||
if constexpr (std::is_same_v<Op, hlfir::AnyOp>) {
|
||||
init = builder.createIntegerConstant(loc, builder.getI1Type(), 0);
|
||||
genBodyFn =
|
||||
[inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &indices)
|
||||
genBodyFn = [inlineSource](
|
||||
fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
|
||||
-> mlir::Value {
|
||||
// Conditionally set the reduction variable.
|
||||
mlir::Value cond = builder.create<fir::ConvertOp>(
|
||||
loc, builder.getI1Type(), inlineSource(builder, loc, indices));
|
||||
loc, builder.getI1Type(),
|
||||
inlineSource(builder, loc, oneBasedIndices));
|
||||
return builder.create<mlir::arith::OrIOp>(loc, reduction, cond);
|
||||
};
|
||||
} else if constexpr (std::is_same_v<Op, hlfir::AllOp>) {
|
||||
init = builder.createIntegerConstant(loc, builder.getI1Type(), 1);
|
||||
genBodyFn =
|
||||
[inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &indices)
|
||||
genBodyFn = [inlineSource](
|
||||
fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
|
||||
-> mlir::Value {
|
||||
// Conditionally set the reduction variable.
|
||||
mlir::Value cond = builder.create<fir::ConvertOp>(
|
||||
loc, builder.getI1Type(), inlineSource(builder, loc, indices));
|
||||
loc, builder.getI1Type(),
|
||||
inlineSource(builder, loc, oneBasedIndices));
|
||||
return builder.create<mlir::arith::AndIOp>(loc, reduction, cond);
|
||||
};
|
||||
} else if constexpr (std::is_same_v<Op, hlfir::CountOp>) {
|
||||
init = builder.createIntegerConstant(loc, op.getType(), 0);
|
||||
genBodyFn =
|
||||
[inlineSource](fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &indices)
|
||||
genBodyFn = [inlineSource](
|
||||
fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
|
||||
-> mlir::Value {
|
||||
// Conditionally add one to the current value
|
||||
mlir::Value cond = builder.create<fir::ConvertOp>(
|
||||
loc, builder.getI1Type(), inlineSource(builder, loc, indices));
|
||||
loc, builder.getI1Type(),
|
||||
inlineSource(builder, loc, oneBasedIndices));
|
||||
mlir::Value one =
|
||||
builder.createIntegerConstant(loc, reduction.getType(), 1);
|
||||
mlir::Value add1 =
|
||||
@ -984,12 +990,12 @@ public:
|
||||
std::is_same_v<Op, hlfir::MinvalOp>) {
|
||||
bool isMax = std::is_same_v<Op, hlfir::MaxvalOp>;
|
||||
init = makeMinMaxInitValGenerator(isMax)(builder, loc, op.getType());
|
||||
genBodyFn = [inlineSource,
|
||||
isMax](fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &indices)
|
||||
genBodyFn = [inlineSource, isMax](
|
||||
fir::FirOpBuilder builder, mlir::Location loc,
|
||||
mlir::Value reduction,
|
||||
const llvm::SmallVectorImpl<mlir::Value> &oneBasedIndices)
|
||||
-> mlir::Value {
|
||||
mlir::Value val = inlineSource(builder, loc, indices);
|
||||
mlir::Value val = inlineSource(builder, loc, oneBasedIndices);
|
||||
mlir::Value cmp =
|
||||
generateMinMaxComparison(builder, loc, val, reduction, isMax);
|
||||
return builder.create<mlir::arith::SelectOp>(loc, cmp, val, reduction);
|
||||
|
@ -93,3 +93,25 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
|
||||
// CHECK-NEXT: hlfir.assign %[[V6]] to %3#0 : f32, !fir.ref<f32>
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// Verify that lower bounds of designator are applied in the indexing inside
|
||||
// the generated loop (hlfir.designate takes indices relative to the base lower
|
||||
// bounds).
|
||||
func.func @component_lower_bounds(%arg0: !fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>) -> i32 {
|
||||
%c10 = arith.constant 10 : index
|
||||
%c101 = arith.constant 101 : index
|
||||
%4 = fir.shape_shift %c101, %c10 : (index, index) -> !fir.shapeshift<1>
|
||||
%5 = hlfir.designate %arg0{"i"} shape %4 : (!fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
|
||||
%6 = hlfir.maxval %5 : (!fir.box<!fir.array<10xi32>>) -> i32
|
||||
return %6 : i32
|
||||
}
|
||||
// CHECK-LABEL: func.func @component_lower_bounds(
|
||||
// CHECK: %[[VAL_1:.*]] = arith.constant 100 : index
|
||||
// CHECK: %[[VAL_2:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[VAL_4:.*]] = arith.constant 10 : index
|
||||
// CHECK: %[[VAL_5:.*]] = arith.constant 101 : index
|
||||
// CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]], %[[VAL_4]] : (index, index) -> !fir.shapeshift<1>
|
||||
// CHECK: %[[VAL_7:.*]] = hlfir.designate %{{.*}}{"i"} shape %[[VAL_6]] : (!fir.ref<!fir.type<sometype{i:!fir.array<10xi32>}>>, !fir.shapeshift<1>) -> !fir.box<!fir.array<10xi32>>
|
||||
// CHECK: %[[VAL_8:.*]] = fir.do_loop %[[VAL_9:.*]] = %[[VAL_2]] to %[[VAL_4]] {{.*}}
|
||||
// CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_1]] : index
|
||||
// CHECK: hlfir.designate %[[VAL_7]] (%[[VAL_11]]) : (!fir.box<!fir.array<10xi32>>, index) -> !fir.ref<i32>
|
||||
|
Loading…
x
Reference in New Issue
Block a user