Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8736,12 +8736,6 @@ static mlir::Value genExtremumResult(mlir::Location loc,
fir::FirOpBuilder &builder,
mlir::Value left, mlir::Value right) {
mlir::Type type = left.getType();
mlir::arith::CmpIPredicate integerPredicate =
type.isUnsignedInteger() ? isMax ? mlir::arith::CmpIPredicate::ugt
: mlir::arith::CmpIPredicate::ult
: isMax ? mlir::arith::CmpIPredicate::sgt
: mlir::arith::CmpIPredicate::slt;
mlir::Value pred;
if (fir::isa_real(type)) {
switch (builder.getFPMaxminBehavior()) {
case Fortran::common::FPMaxminBehavior::Portable:
Expand Down Expand Up @@ -8782,26 +8776,41 @@ static mlir::Value genExtremumResult(mlir::Location loc,

llvm_unreachable("unsupported FPMaxminBehavior");
} else if (fir::isa_integer(type)) {
mlir::Value cmpLeft = left;
mlir::Value cmpRight = right;
// It is probably okay to use signed index.maxs/mins, but
// maybe the caller needs to specify signedness.
// There are currently no callers that pass values of index
// type, so just emit a TODO.
if (mlir::isa<mlir::IndexType>(type))
TODO(loc, "extremum for index type");

if (type.isUnsignedInteger()) {
// arith.maxui/minui operands must have singless type.
mlir::Type signlessType = mlir::IntegerType::get(
builder.getContext(), type.getIntOrFloatBitWidth(),
mlir::IntegerType::SignednessSemantics::Signless);
cmpLeft = builder.createConvert(loc, signlessType, left);
cmpRight = builder.createConvert(loc, signlessType, right);
left = builder.createConvert(loc, signlessType, left);
right = builder.createConvert(loc, signlessType, right);

mlir::Value result;
if constexpr (isMax)
result = mlir::arith::MaxUIOp::create(builder, loc, left, right);
else
result = mlir::arith::MinUIOp::create(builder, loc, left, right);

return builder.createConvert(loc, type, result);
} else {
if constexpr (isMax)
return mlir::arith::MaxSIOp::create(builder, loc, left, right);
else
return mlir::arith::MinSIOp::create(builder, loc, left, right);
}
pred = mlir::arith::CmpIOp::create(builder, loc, integerPredicate, cmpLeft,
cmpRight);
} else if (fir::isa_char(type) || fir::isa_char(fir::unwrapRefType(type))) {
// TODO: ! character min and max is tricky because the result
// length is the length of the longest argument!
// So we may need a temp.
TODO(loc, "intrinsic: min and max for CHARACTER");
}
assert(pred && "pred must be defined");

return mlir::arith::SelectOp::create(builder, loc, pred, left, right);
llvm_unreachable("unsupported extremum");
}

// UNLINK
Expand Down
48 changes: 9 additions & 39 deletions flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ template <bool IS_MAX>
static mlir::Value
genMinMaxComparison(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Value elem, mlir::Value reduction) {
// TODO: there is some opportunity to generalize this code with
// IntrinsicLibrary::genExtremum(), but one have to be careful
// to preserve the NaNs behavior (when needed) that is handled
// here with the three FP comparisons.
if (mlir::isa<mlir::FloatType>(reduction.getType())) {
// For FP reductions we want the first smallest value to be used, that
// is not NaN. A OGL/OLT condition will usually work for this unless all
Expand Down Expand Up @@ -802,6 +806,7 @@ class MinMaxvalAsElementalConverter
this->checkReductions(currentValue);
llvm::SmallVector<mlir::Value> result;
fir::FirOpBuilder &builder = this->builder;
builder.setFPMaxminBehavior(fpMaxminBehavior);
mlir::Location loc = this->loc;
hlfir::Entity elementValue =
hlfir::loadElementAt(loc, builder, array, oneBasedIndices);
Expand Down Expand Up @@ -893,45 +898,10 @@ class MinMaxvalAsElementalConverter
assert(!useIsFirst() &&
"unordered max/min reduction must not use first predicate");

if (mlir::isa<fir::CharacterType>(this->getSourceElementType()))
TODO(loc, "max/minval with CHARACTER type");

if (auto intType =
mlir::dyn_cast<mlir::IntegerType>(this->getSourceElementType())) {
if (intType.isUnsigned())
TODO(loc, "max/minval with UNSIGNED type");

if constexpr (isMax)
return mlir::arith::MaxSIOp::create(builder, loc, elementValue,
currentMinMax);
else
return mlir::arith::MinSIOp::create(builder, loc, elementValue,
currentMinMax);
}

if (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Extremum) {
if constexpr (isMax)
return mlir::arith::MaximumFOp::create(builder, loc, elementValue,
currentMinMax);
else
return mlir::arith::MinimumFOp::create(builder, loc, elementValue,
currentMinMax);
}

if (fpMaxminBehavior == Fortran::common::FPMaxminBehavior::ExtremeNum ||
(fpMaxminBehavior == Fortran::common::FPMaxminBehavior::Portable &&
mlir::arith::bitEnumContainsAll(
this->getFastMath(), mlir::arith::FastMathFlags::nnan |
mlir::arith::FastMathFlags::nsz))) {
if constexpr (isMax)
return mlir::arith::MaxNumFOp::create(builder, loc, elementValue,
currentMinMax);
else
return mlir::arith::MinNumFOp::create(builder, loc, elementValue,
currentMinMax);
}

llvm_unreachable("unhandled unordered max/min reduction");
if constexpr (isMax)
return fir::genMax(builder, loc, {elementValue, currentMinMax});
else
return fir::genMin(builder, loc, {elementValue, currentMinMax});
}

std::size_t getNumReductions() const { return useIsFirst() ? 2 : 1; }
Expand Down
3 changes: 1 addition & 2 deletions flang/test/Lower/HLFIR/array-ctor-as-elemental.f90
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ subroutine test_as_strided_elemental(lb, ub, stride)
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_13:.*]] = arith.divsi %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_15:.*]] = arith.cmpi sgt, %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.select %[[VAL_15]], %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.maxsi %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_6]], %[[VAL_16]] : i64
! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (i64) -> index
! CHECK: %[[VAL_19:.*]] = fir.shape %[[VAL_18]] : (index) -> !fir.shape<1>
Expand Down
12 changes: 4 additions & 8 deletions flang/test/Lower/HLFIR/array-ctor-as-inlined-temp.f90
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ subroutine test_implied_do(n)
! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_11:.*]] = arith.divsi %[[VAL_9]], %[[VAL_10]] : i64
! CHECK: %[[VAL_12:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_14:.*]] = arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_14:.*]] = arith.maxsi %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_15:.*]] = arith.muli %[[VAL_4]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.addi %[[VAL_3]], %[[VAL_15]] : i64
! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i64) -> index
Expand Down Expand Up @@ -191,8 +190,7 @@ subroutine test_strided_implied_do(lb, ub, stride)
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_15:.*]] = arith.divsi %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_17:.*]] = arith.cmpi sgt, %[[VAL_15]], %[[VAL_16]] : i64
! CHECK: %[[VAL_18:.*]] = arith.select %[[VAL_17]], %[[VAL_15]], %[[VAL_16]] : i64
! CHECK: %[[VAL_18:.*]] = arith.maxsi %[[VAL_15]], %[[VAL_16]] : i64
! CHECK: %[[VAL_19:.*]] = arith.muli %[[VAL_8]], %[[VAL_18]] : i64
! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_7]], %[[VAL_19]] : i64
! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i64) -> index
Expand Down Expand Up @@ -253,8 +251,7 @@ subroutine test_nested_implied_do(n, m)
! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_13:.*]] = arith.divsi %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: %[[VAL_14:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_15:.*]] = arith.cmpi sgt, %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.select %[[VAL_15]], %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_16:.*]] = arith.maxsi %[[VAL_13]], %[[VAL_14]] : i64
! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_6]], %[[VAL_16]] : i64
! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i64>
! CHECK: %[[VAL_19:.*]] = arith.constant 1 : i64
Expand All @@ -264,8 +261,7 @@ subroutine test_nested_implied_do(n, m)
! CHECK: %[[VAL_23:.*]] = arith.constant 1 : i64
! CHECK: %[[VAL_24:.*]] = arith.divsi %[[VAL_22]], %[[VAL_23]] : i64
! CHECK: %[[VAL_25:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_26:.*]] = arith.cmpi sgt, %[[VAL_24]], %[[VAL_25]] : i64
! CHECK: %[[VAL_27:.*]] = arith.select %[[VAL_26]], %[[VAL_24]], %[[VAL_25]] : i64
! CHECK: %[[VAL_27:.*]] = arith.maxsi %[[VAL_24]], %[[VAL_25]] : i64
! CHECK: %[[VAL_28:.*]] = arith.muli %[[VAL_17]], %[[VAL_27]] : i64
! CHECK: %[[VAL_29:.*]] = arith.addi %[[VAL_5]], %[[VAL_28]] : i64
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_29]] : (i64) -> index
Expand Down
3 changes: 1 addition & 2 deletions flang/test/Lower/HLFIR/binary-ops.f90
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ subroutine extremum(c, n, l)
! CHECK: hlfir.declare {{.*}}c"}
! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i64
! CHECK: %[[VAL_12:.*]] = fir.load %{{.*}} : !fir.ref<i64>
! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64
! CHECK: arith.maxsi %[[VAL_11]], %[[VAL_12]] : i64

subroutine cmp_int(l, x, y)
logical :: l
Expand Down
Loading