[flang-commits] [flang] [Flang] Return APInt from getIntIfConstant (PR #211233)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Wed Jul 22 04:07:15 PDT 2026
https://github.com/tblah created https://github.com/llvm/llvm-project/pull/211233
Preserve the full bit width of integer attributes when extracting constants from FIR values. Return llvm::APInt directly and update fixed-width consumers to use checked signed extraction.
This avoids truncating or asserting on constants wider than 64 bits while retaining existing fallback behavior at int64_t boundaries.
This should be NFC everywhere we didn't have a latent overflow bug. I didn't go so far as updating the interfaces of every function built on top of getIntIfConstant: this is mostly to make an APInt version available because it looks useful for another PR. Fixing the builder API to use APInt would be a larger change - let me know if anyone wants to see that.
Assisted-by: Codex
>From 0d225495f7c23a6c14ba2728ecb61eacf67335f0 Mon Sep 17 00:00:00 2001
From: Tom Eccles <tom.eccles at arm.com>
Date: Wed, 22 Jul 2026 11:06:01 +0100
Subject: [PATCH] [Flang] Return APInt from getIntIfConstant
Preserve the full bit width of integer attributes when extracting
constants from FIR values. Return llvm::APInt directly and update
fixed-width consumers to use checked signed extraction.
This avoids truncating or asserting on constants wider than 64 bits
while retaining existing fallback behavior at int64_t boundaries.
This should be NFC everywhere we didn't have a latent overflow bug.
I didn't go so far as updating the interfaces of every function built on
top of getIntIfConstant: this is mostly to make an APInt version
available because it looks useful for another PR. Fixing the builder API
to use APInt would be a larger change - let me know if anyone wants to see
that.
Assisted-by: Codex
---
.../flang/Optimizer/Dialect/FIROpsSupport.h | 5 +--
flang/lib/Lower/ConvertExprToHLFIR.cpp | 8 +++--
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 11 ++++++-
flang/lib/Lower/OpenMP/OpenMP.cpp | 5 +--
.../Analysis/ArraySectionAnalyzer.cpp | 19 ++++++-----
flang/lib/Optimizer/Builder/Character.cpp | 3 +-
flang/lib/Optimizer/Builder/FIRBuilder.cpp | 2 +-
flang/lib/Optimizer/Builder/HLFIRTools.cpp | 14 +++++---
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 33 ++++++++++---------
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 13 +++++---
flang/lib/Optimizer/Dialect/FIROps.cpp | 22 +++++++------
flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 14 ++++++--
.../HLFIR/Transforms/BufferizeHLFIR.cpp | 3 +-
.../LowerHLFIROrderedAssignments.cpp | 4 ++-
.../Transforms/SimplifyHLFIRIntrinsics.cpp | 13 ++++++--
.../Support/FIROpenACCTypeInterfaces.cpp | 7 ++--
.../OpenACC/Support/FIROpenACCUtils.cpp | 12 ++++---
.../Transforms/DebugTypeGenerator.cpp | 14 +++++---
.../lib/Optimizer/Transforms/FIRToMemRef.cpp | 5 ++-
19 files changed, 133 insertions(+), 74 deletions(-)
diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index 944b9926387d8..a354f7aef511b 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -12,6 +12,7 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/BuiltinOps.h"
+#include "llvm/ADT/APInt.h"
namespace fir {
@@ -188,8 +189,8 @@ bool valueMayHaveFirAttributes(mlir::Value value,
/// function has any host associations, for example.
bool anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr);
-/// Unwrap integer constant from an mlir::Value.
-std::optional<std::int64_t> getIntIfConstant(mlir::Value value);
+/// Unwrap an integer constant from an mlir::Value as an APInt.
+std::optional<llvm::APInt> getIntIfConstant(mlir::Value value);
static constexpr llvm::StringRef getAdaptToByRefAttrName() {
return "adapt.valuebyref";
diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 6f718a8eb5926..936616ccbaa6e 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -2338,9 +2338,11 @@ HlfirDesignatorBuilder::genSubscript(const Fortran::evaluate::Expr<T> &expr) {
// IR harder to read: directly use index constants for constant subscripts.
mlir::Type idxTy = builder.getIndexType();
if (!loweredExpr.isArray() && loweredExpr.getType() != idxTy)
- if (auto cstIndex = fir::getIntIfConstant(loweredExpr))
- return hlfir::EntityWithAttributes{
- builder.createIntegerConstant(getLoc(), idxTy, *cstIndex)};
+ if (std::optional<llvm::APInt> cstIndex =
+ fir::getIntIfConstant(loweredExpr))
+ if (std::optional<std::int64_t> cstIndex64 = cstIndex->trySExtValue())
+ return hlfir::EntityWithAttributes{
+ builder.createIntegerConstant(getLoc(), idxTy, *cstIndex64)};
return hlfir::loadTrivialScalar(loc, builder, loweredExpr);
}
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 318bdaa4f2f30..5a554def351ea 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1098,7 +1098,16 @@ addAlignedClause(lower::AbstractConverter &converter,
std::get<std::optional<Aligned::Alignment>>(clause.t)) {
mlir::Value operand = fir::getBase(
converter.genExprValue(*alignmentValueParserExpr, stmtCtx));
- alignment = *fir::getIntIfConstant(operand);
+ std::optional<llvm::APInt> constantAlignment =
+ fir::getIntIfConstant(operand);
+ if (!constantAlignment)
+ fir::emitFatalError(operand.getLoc(), "alignment must be a constant");
+ std::optional<std::int64_t> constantAlignment64 =
+ constantAlignment->trySExtValue();
+ if (!constantAlignment64)
+ fir::emitFatalError(operand.getLoc(),
+ "alignment does not fit in a 64-bit integer");
+ alignment = *constantAlignment64;
} else {
llvm::StringMap<bool> featuresMap = getTargetFeatures(builder.getModule());
llvm::Triple triple = fir::getTargetTriple(builder.getModule());
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index a3acc2e991307..2e45f99172d3b 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1057,8 +1057,9 @@ static void genCollapsedLoopNestBody(lower::AbstractConverter &converter,
// Last value the induction variable at \p lvl actually takes:
// lb + ((ub - lb) / step) * step. For unit steps this is exactly ub.
auto computeLastIV = [&](const int lvl) -> mlir::Value {
- const auto constStep = fir::getIntIfConstant(steps[lvl]);
- if (constStep && (*constStep == 1 || *constStep == -1))
+ const std::optional<llvm::APInt> constStep =
+ fir::getIntIfConstant(steps[lvl]);
+ if (constStep && (constStep->isOne() || constStep->isAllOnes()))
return ubs[lvl];
const mlir::Value lb = lbs[lvl];
const mlir::Value ub = ubs[lvl];
diff --git a/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp b/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
index 6eec184b99a7f..d1a90f1324c2c 100644
--- a/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
+++ b/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
@@ -31,7 +31,7 @@ void ArraySectionAnalyzer::SectionDesc::normalize() {
stride = nullptr;
if (stride)
if (auto val = fir::getIntIfConstant(stride))
- if (*val == 1)
+ if (val->isOne())
stride = nullptr;
}
@@ -56,7 +56,7 @@ ArraySectionAnalyzer::getOrderedBounds(const SectionDesc &desc) {
return {desc.lb, desc.ub};
// Reverse the bounds, if stride is negative.
if (auto val = fir::getIntIfConstant(stride)) {
- if (*val >= 0)
+ if (!val->isNegative())
return {desc.lb, desc.ub};
else
return {desc.ub, desc.lb};
@@ -203,7 +203,7 @@ bool ArraySectionAnalyzer::isLess(mlir::Value v1, mlir::Value v2) {
auto isPositiveConstant = [](mlir::Value v) -> bool {
if (auto val = fir::getIntIfConstant(v))
- return *val > 0;
+ return val->isStrictlyPositive();
return false;
};
@@ -213,9 +213,12 @@ bool ArraySectionAnalyzer::isLess(mlir::Value v1, mlir::Value v2) {
return false;
// Check if they are both constants.
- if (auto val1 = fir::getIntIfConstant(op1->getResult(0)))
- if (auto val2 = fir::getIntIfConstant(op2->getResult(0)))
- return *val1 < *val2;
+ std::optional<llvm::APInt> val1 = fir::getIntIfConstant(op1->getResult(0));
+ std::optional<llvm::APInt> val2 = fir::getIntIfConstant(op2->getResult(0));
+ if (val1 && val2) {
+ unsigned width = std::max(val1->getBitWidth(), val2->getBitWidth());
+ return val1->sext(width).slt(val2->sext(width));
+ }
// Handle some variable cases (C > 0):
// v2 = v1 + C
@@ -263,7 +266,7 @@ getDesignatorIndices(hlfir::DesignateOp designate) {
if (auto subOp =
mlir::dyn_cast_or_null<mlir::arith::SubIOp>(v.getDefiningOp())) {
auto cst = fir::getIntIfConstant(subOp.getRhs());
- if (!cst || *cst != 1)
+ if (!cst || !cst->isOne())
return false;
if (auto dimsOp = mlir::dyn_cast_or_null<fir::BoxDimsOp>(
subOp.getLhs().getDefiningOp())) {
@@ -271,7 +274,7 @@ getDesignatorIndices(hlfir::DesignateOp designate) {
dimsOp.getResult(0) != subOp.getLhs())
return false;
auto dimsOpDim = fir::getIntIfConstant(dimsOp.getDim());
- return dimsOpDim && dimsOpDim == dim;
+ return dimsOpDim && *dimsOpDim == dim;
}
}
return false;
diff --git a/flang/lib/Optimizer/Builder/Character.cpp b/flang/lib/Optimizer/Builder/Character.cpp
index 155bc0fbd19ce..a5e32fec05978 100644
--- a/flang/lib/Optimizer/Builder/Character.cpp
+++ b/flang/lib/Optimizer/Builder/Character.cpp
@@ -373,7 +373,8 @@ fir::factory::CharacterExprHelper::createCharacterTemp(mlir::Type type,
auto typeLen = fir::CharacterType::unknownLen();
// If len is a constant, reflect the length in the type.
if (auto cstLen = getIntIfConstant(len))
- typeLen = *cstLen;
+ if (std::optional<std::int64_t> cstLen64 = cstLen->trySExtValue())
+ typeLen = *cstLen64;
auto *ctxt = builder.getContext();
auto charTy = fir::CharacterType::get(ctxt, kind, typeLen);
llvm::SmallVector<mlir::Value> lenParams;
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 33360d891c3fa..59bae963ee026 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -1726,7 +1726,7 @@ fir::factory::getExtentFromTriplet(mlir::Value lb, mlir::Value ub,
std::function<std::optional<std::int64_t>(mlir::Value)> getConstantValue =
[&](mlir::Value value) -> std::optional<std::int64_t> {
if (auto valInt = fir::getIntIfConstant(value))
- return *valInt;
+ return valInt->trySExtValue();
auto *definingOp = value.getDefiningOp();
if (mlir::isa_and_nonnull<fir::ConvertOp>(definingOp)) {
auto valOp = mlir::dyn_cast<fir::ConvertOp>(definingOp);
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index f95af2deb08da..f35ed4dd59e12 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -467,7 +467,7 @@ static mlir::Value genUBound(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Value lb, mlir::Value extent,
mlir::Value one) {
if (auto constantLb = fir::getIntIfConstant(lb))
- if (*constantLb == 1)
+ if (constantLb->isOne())
return extent;
extent = builder.createConvert(loc, one.getType(), extent);
lb = builder.createConvert(loc, one.getType(), lb);
@@ -761,14 +761,17 @@ std::optional<std::int64_t> hlfir::getCharLengthIfConst(hlfir::Entity entity) {
llvm::SmallVector<mlir::Value> param;
if (getExprLengthParameters(expr, param)) {
assert(param.size() == 1 && "characters must have one length parameters");
- return fir::getIntIfConstant(param.pop_back_val());
+ if (std::optional<llvm::APInt> constant =
+ fir::getIntIfConstant(param.pop_back_val()))
+ return constant->trySExtValue();
}
return std::nullopt;
}
// entity is a var
if (mlir::Value len = tryGettingNonDeferredCharLen(entity))
- return fir::getIntIfConstant(len);
+ if (std::optional<llvm::APInt> constant = fir::getIntIfConstant(len))
+ return constant->trySExtValue();
auto charType =
mlir::cast<fir::CharacterType>(entity.getFortranElementType());
if (charType.hasConstantLen())
@@ -905,7 +908,8 @@ static hlfir::ExprType getArrayExprType(mlir::Type elementType,
if (auto shapeOp = shape.getDefiningOp<fir::ShapeOp>())
for (auto extent : llvm::enumerate(shapeOp.getExtents()))
if (auto cstExtent = fir::getIntIfConstant(extent.value()))
- typeShape[extent.index()] = *cstExtent;
+ if (std::optional<std::int64_t> cstExtent64 = cstExtent->trySExtValue())
+ typeShape[extent.index()] = *cstExtent64;
return hlfir::ExprType::get(elementType.getContext(), typeShape, elementType,
isPolymorphic);
}
@@ -1775,7 +1779,7 @@ bool hlfir::designatePreservesContinuity(hlfir::DesignateOp op) {
i += 2;
mlir::Value step = subscripts[i++];
auto constantStep = fir::getIntIfConstant(step);
- if (!constantStep || *constantStep != 1)
+ if (!constantStep || !constantStep->isOne())
return false;
}
} else {
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 9ec64844cf6d6..6987092ea921d 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -8254,15 +8254,16 @@ IntrinsicLibrary::genSize(mlir::Type resultType,
// Get the DIM argument.
mlir::Value dim = fir::getBase(args[1]);
+ std::optional<std::int64_t> cstDim;
if (!args[0].hasAssumedRank())
- if (std::optional<std::int64_t> cstDim = fir::getIntIfConstant(dim)) {
- // If both DIM and the rank are compile time constants, skip the runtime
- // call.
- return builder.createConvert(
- loc, resultType,
- fir::factory::readExtent(builder, loc, fir::BoxValue{array},
- cstDim.value() - 1));
- }
+ if (std::optional<llvm::APInt> constantDim = fir::getIntIfConstant(dim))
+ cstDim = constantDim->trySExtValue();
+ // If both DIM and the rank are compile time constants, skip the runtime call.
+ if (cstDim)
+ return builder.createConvert(loc, resultType,
+ fir::factory::readExtent(builder, loc,
+ fir::BoxValue{array},
+ cstDim.value() - 1));
if (!fir::isa_ref_type(dim.getType()))
return builder.createConvert(
loc, resultType, fir::runtime::genSizeDim(builder, loc, array, dim));
@@ -8465,14 +8466,16 @@ IntrinsicLibrary::genLbound(mlir::Type resultType,
// If it is a compile time constant and the rank is known, skip the runtime
// call.
+ std::optional<std::int64_t> cstDim;
if (!array.hasAssumedRank())
- if (std::optional<std::int64_t> cstDim = fir::getIntIfConstant(dim)) {
- mlir::Value one = builder.createIntegerConstant(loc, resultType, 1);
- mlir::Value zero = builder.createIntegerConstant(loc, indexType, 0);
- mlir::Value lb =
- computeLBOUND(builder, loc, array, *cstDim - 1, zero, one);
- return builder.createConvert(loc, resultType, lb);
- }
+ if (std::optional<llvm::APInt> constantDim = fir::getIntIfConstant(dim))
+ cstDim = constantDim->trySExtValue();
+ if (cstDim) {
+ mlir::Value one = builder.createIntegerConstant(loc, resultType, 1);
+ mlir::Value zero = builder.createIntegerConstant(loc, indexType, 0);
+ mlir::Value lb = computeLBOUND(builder, loc, array, *cstDim - 1, zero, one);
+ return builder.createConvert(loc, resultType, lb);
+ }
fir::ExtendedValue box = createBoxForRuntimeBoundInquiry(loc, builder, array);
return builder.createConvert(
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 994112599dda3..0e88524126f11 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -111,9 +111,12 @@ static mlir::Block *createBlock(mlir::ConversionPatternRewriter &rewriter,
/// Extract constant from a value that must be the result of one of the
/// ConstantOp operations.
static int64_t getConstantIntValue(mlir::Value val) {
- if (auto constVal = fir::getIntIfConstant(val))
- return *constVal;
- fir::emitFatalError(val.getLoc(), "must be a constant");
+ std::optional<llvm::APInt> constVal = fir::getIntIfConstant(val);
+ if (!constVal)
+ fir::emitFatalError(val.getLoc(), "must be a constant");
+ if (std::optional<std::int64_t> constVal64 = constVal->trySExtValue())
+ return *constVal64;
+ fir::emitFatalError(val.getLoc(), "constant must fit in a 64-bit integer");
}
static unsigned getTypeDescFieldId(mlir::Type ty) {
@@ -1062,8 +1065,8 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
// Do folding for constant inputs.
if (auto constVal = fir::getIntIfConstant(op0)) {
- mlir::Value normVal =
- fir::genConstantIndex(loc, toTy, rewriter, *constVal ? 1 : 0);
+ mlir::Value normVal = fir::genConstantIndex(loc, toTy, rewriter,
+ constVal->isZero() ? 0 : 1);
rewriter.replaceOp(convert, normVal);
return mlir::success();
}
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index b9968897ade6d..798ab130c1d30 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -776,7 +776,7 @@ struct SimplifyArrayCoorOp : public mlir::OpRewritePattern<fir::ArrayCoorOp> {
if (!lowerBounds.empty()) {
mlir::Value lb = lowerBounds[i];
auto constLb = fir::getIntIfConstant(lb);
- if (!(constLb && *constLb == 1)) {
+ if (!(constLb && constLb->isOne())) {
mlir::Location loc = op.getLoc();
mlir::Value extLb =
fir::ConvertOp::create(rewriter, loc, idxTy, lb);
@@ -1630,7 +1630,9 @@ struct SimplifyBoxDimsFromCreateBox
if (!createBox)
return mlir::failure();
- std::optional<std::int64_t> dim = fir::getIntIfConstant(op.getDim());
+ std::optional<llvm::APInt> constantDim = fir::getIntIfConstant(op.getDim());
+ std::optional<std::int64_t> dim =
+ constantDim ? constantDim->trySExtValue() : std::nullopt;
if (!dim || *dim < 0 || *dim >= createBox.getRank())
return mlir::failure();
@@ -2095,7 +2097,7 @@ mlir::OpFoldResult fir::ConvertOp::fold(FoldAdaptor adaptor) {
matchPattern(getValue(), mlir::m_Op<fir::BitcastOp>())) {
auto bitcast = mlir::cast<fir::BitcastOp>(getValue().getDefiningOp());
if (auto cst = fir::getIntIfConstant(bitcast.getValue()))
- return mlir::IntegerAttr::get(getType(), cst != 0 ? 1 : 0);
+ return mlir::IntegerAttr::get(getType(), cst->isZero() ? 0 : 1);
}
return {};
}
@@ -2110,7 +2112,7 @@ static std::optional<bool> getLogicalConstant(mlir::Value value) {
if (auto convertOp = value.getDefiningOp<fir::ConvertOp>())
maybeConvertInput = convertOp.getValue();
if (auto cst = fir::getIntIfConstant(maybeConvertInput))
- return *cst != 0;
+ return !cst->isZero();
return std::nullopt;
}
@@ -2751,7 +2753,7 @@ static bool isBoxLb(mlir::Value box, std::int64_t dim, mlir::Value lb,
return *dimOperand == dim;
} else if (!mayHaveNonDefaultLowerBounds) {
if (auto constantLb = fir::getIntIfConstant(lb))
- return *constantLb == 1;
+ return constantLb->isOne();
}
return false;
}
@@ -2768,7 +2770,7 @@ static bool isBoxUb(mlir::Value box, std::int64_t dim, mlir::Value ub,
bool mayHaveNonDefaultLowerBounds = true) {
if (auto sub1 = ub.getDefiningOp<mlir::arith::SubIOp>()) {
auto one = fir::getIntIfConstant(sub1.getOperand(1));
- if (!one || *one != 1)
+ if (!one || !one->isOne())
return false;
if (auto add = sub1.getOperand(0).getDefiningOp<mlir::arith::AddIOp>())
if ((isBoxLb(box, dim, add.getOperand(0)) &&
@@ -2831,7 +2833,7 @@ static bool isContiguousArraySlice(fir::SliceOp sliceOp, bool checkWhole = true,
return false;
}
auto constantStep = fir::getIntIfConstant(triples[i + 2]);
- if (!constantStep || *constantStep != 1)
+ if (!constantStep || !constantStep->isOne())
return false;
}
}
@@ -6121,14 +6123,14 @@ bool fir::anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr) {
return false;
}
-std::optional<std::int64_t> fir::getIntIfConstant(mlir::Value value) {
+std::optional<llvm::APInt> fir::getIntIfConstant(mlir::Value value) {
if (auto *definingOp = value.getDefiningOp()) {
if (auto cst = mlir::dyn_cast<mlir::arith::ConstantOp>(definingOp))
if (auto intAttr = mlir::dyn_cast<mlir::IntegerAttr>(cst.getValue()))
- return intAttr.getInt();
+ return intAttr.getValue();
if (auto llConstOp = mlir::dyn_cast<mlir::LLVM::ConstantOp>(definingOp))
if (auto attr = mlir::dyn_cast<mlir::IntegerAttr>(llConstOp.getValue()))
- return attr.getValue().getSExtValue();
+ return attr.getValue();
}
return {};
}
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 9de2d718a9c3a..df2811f70abf2 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -1197,7 +1197,8 @@ void hlfir::SetLengthOp::build(mlir::OpBuilder &builder,
mlir::Value len) {
fir::CharacterType::LenType resultTypeLen = fir::CharacterType::unknownLen();
if (auto cstLen = fir::getIntIfConstant(len))
- resultTypeLen = *cstLen;
+ if (std::optional<std::int64_t> cstLen64 = cstLen->trySExtValue())
+ resultTypeLen = *cstLen64;
unsigned kind = getCharacterKind(string.getType());
auto resultType = hlfir::ExprType::get(
builder.getContext(), hlfir::ExprType::Shape{},
@@ -1568,8 +1569,15 @@ static llvm::LogicalResult verifyArrayShift(Op op) {
int64_t dimVal = -1;
if (!op.getDim())
dimVal = 1;
- else if (auto dim = fir::getIntIfConstant(op.getDim()))
- dimVal = *dim;
+ else if (std::optional<llvm::APInt> dim =
+ fir::getIntIfConstant(op.getDim())) {
+ if (std::optional<std::int64_t> dim64 = dim->trySExtValue())
+ dimVal = *dim64;
+ else if (useStrictIntrinsicVerifier)
+ return op.emitOpError(dim->isNegative()
+ ? "DIM must be >= 1"
+ : "DIM must be <= input array's rank");
+ }
// The DIM argument may be statically invalid (e.g. exceed the
// input array rank) in dead code after constant propagation,
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
index c5bad209ef8db..fdde05e3d880b 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
@@ -594,8 +594,7 @@ static void genBufferDestruction(mlir::Location loc, fir::FirOpBuilder &builder,
/*doFinalize=*/false);
};
if (auto cstMustFree = fir::getIntIfConstant(mustFree)) {
- genFreeOrFinalize(*cstMustFree != 0 ? true : false, deallocComponents,
- mustFinalize);
+ genFreeOrFinalize(!cstMustFree->isZero(), deallocComponents, mustFinalize);
return;
}
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
index c08dd617a4113..dcc40c7b25c5c 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
@@ -1120,7 +1120,9 @@ computeLoopNestIterationNumber(mlir::Location loc, fir::FirOpBuilder &builder,
static std::optional<int64_t> unwrapConstantInt(mlir::Value value) {
while (auto convert = value.getDefiningOp<fir::ConvertOp>())
value = convert.getValue();
- return fir::getIntIfConstant(value);
+ if (std::optional<llvm::APInt> constant = fir::getIntIfConstant(value))
+ return constant->trySExtValue();
+ return std::nullopt;
}
/// Compute the extents and lower bounds of \p loopNest, in the same order as
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
index 3f7b831954f7a..716737bb80ff4 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
@@ -311,7 +311,10 @@ class ReductionAsElementalConverter {
auto constDim = fir::getIntIfConstant(getDim());
if (!constDim)
return rewriter.notifyMatchFailure(op, "Nonconstant DIM");
- dimVal = *constDim;
+ std::optional<std::int64_t> constDim64 = constDim->trySExtValue();
+ if (!constDim64)
+ return rewriter.notifyMatchFailure(op, "DIM does not fit in int64_t");
+ dimVal = *constDim64;
if ((dimVal <= 0 || dimVal > getSourceRank()))
return rewriter.notifyMatchFailure(op,
@@ -1435,7 +1438,11 @@ class ArrayShiftConversion : public mlir::OpRewritePattern<Op> {
if (!constDim)
return rewriter.notifyMatchFailure(
op, "Nonconstant DIM for CSHIFT/EOSHIFT");
- dimVal = *constDim;
+ std::optional<std::int64_t> constDim64 = constDim->trySExtValue();
+ if (!constDim64)
+ return rewriter.notifyMatchFailure(
+ op, "DIM does not fit in int64_t for CSHIFT/EOSHIFT");
+ dimVal = *constDim64;
}
if (dimVal <= 0 || dimVal > arrayRank)
@@ -2505,7 +2512,7 @@ class IndexOpConversion : public mlir::OpRewritePattern<hlfir::IndexOp> {
std::optional<bool> isBack;
if (back) {
if (auto backCst = fir::getIntIfConstant(back))
- isBack = *backCst != 0;
+ isBack = !backCst->isZero();
} else {
isBack = false;
}
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
index 4c4d9d3879fef..e7e522e8e1570 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.cpp
@@ -628,9 +628,10 @@ genDesignateWithTriplets(fir::FirOpBuilder &builder, mlir::Location loc,
fir::SequenceType::Shape resultTypeShape;
bool shapeIsConstant = true;
for (mlir::Value extent : extents) {
- if (std::optional<std::int64_t> cst_extent =
- fir::getIntIfConstant(extent)) {
- resultTypeShape.push_back(*cst_extent);
+ std::optional<llvm::APInt> cstExtent = fir::getIntIfConstant(extent);
+ if (std::optional<std::int64_t> cstExtent64 =
+ cstExtent ? cstExtent->trySExtValue() : std::nullopt) {
+ resultTypeShape.push_back(*cstExtent64);
} else {
resultTypeShape.push_back(fir::SequenceType::getUnknownExtent());
shapeIsConstant = false;
diff --git a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
index 4d3ca59703c67..4417b769fa314 100644
--- a/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
+++ b/flang/lib/Optimizer/OpenACC/Support/FIROpenACCUtils.cpp
@@ -378,10 +378,14 @@ getRecipeBounds(fir::FirOpBuilder &builder, mlir::Location loc,
assert(
dataBound.getLowerbound() && dataBound.getUpperbound() &&
"expect acc bounds for Fortran to always have lower and upper bounds");
- std::optional<std::int64_t> lb =
- fir::getIntIfConstant(dataBound.getLowerbound());
- std::optional<std::int64_t> ub =
- fir::getIntIfConstant(dataBound.getUpperbound());
+ std::optional<std::int64_t> lb;
+ if (std::optional<llvm::APInt> constant =
+ fir::getIntIfConstant(dataBound.getLowerbound()))
+ lb = constant->trySExtValue();
+ std::optional<std::int64_t> ub;
+ if (std::optional<llvm::APInt> constant =
+ fir::getIntIfConstant(dataBound.getUpperbound()))
+ ub = constant->trySExtValue();
assert(lb.has_value() && ub.has_value() &&
"must get constant bounds when there are no bound block arguments");
bounds.push_back(builder.createIntegerConstant(loc, idxTy, *lb));
diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index d45aee26470a7..b6f3b6e1d4d67 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -224,8 +224,11 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertBoxedSequenceType(
mlir::Attribute lowerAttr = nullptr;
// If declaration has a lower bound, use it.
if (declOp && declOp.getShift().size() > index) {
- if (std::optional<std::int64_t> optint =
- getIntIfConstant(declOp.getShift()[index]))
+ std::optional<llvm::APInt> constant =
+ getIntIfConstant(declOp.getShift()[index]);
+ std::optional<std::int64_t> optint =
+ constant ? constant->trySExtValue() : std::nullopt;
+ if (optint)
lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, *optint));
else
lowerAttr = generateArtificialVariable(
@@ -545,8 +548,11 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertSequenceType(
// bound. As an optimization, we don't create a lower bound when shift is a
// constant 1 as that is the default.
if (declOp && declOp.getShift().size() > index) {
- if (std::optional<std::int64_t> optint =
- getIntIfConstant(declOp.getShift()[index])) {
+ std::optional<llvm::APInt> constant =
+ getIntIfConstant(declOp.getShift()[index]);
+ std::optional<std::int64_t> optint =
+ constant ? constant->trySExtValue() : std::nullopt;
+ if (optint) {
if (*optint != 1)
lowerAttr = mlir::IntegerAttr::get(intTy, llvm::APInt(64, *optint));
} else
diff --git a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
index 988f32541da9c..8faafaa1ffeed 100644
--- a/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
+++ b/flang/lib/Optimizer/Transforms/FIRToMemRef.cpp
@@ -201,7 +201,10 @@ class FIRToMemRef : public fir::impl::FIRToMemRefBase<FIRToMemRef> {
auto fields = sliceOp.getFields();
if (fields.empty())
return std::nullopt;
- return fir::getIntIfConstant(fields.front());
+ if (std::optional<llvm::APInt> constant =
+ fir::getIntIfConstant(fields.front()))
+ return constant->trySExtValue();
+ return std::nullopt;
}
unsigned getRankFromEmbox(fir::EmboxOp embox) const {
More information about the flang-commits
mailing list