Skip to content

[flang] Add nsw flag to do-variable increment with a new option #91579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2024
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
4 changes: 4 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -6550,6 +6550,10 @@ def flang_deprecated_no_hlfir : Flag<["-"], "flang-deprecated-no-hlfir">,
Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>,
HelpText<"Do not use HLFIR lowering (deprecated)">;

def flang_experimental_integer_overflow : Flag<["-"], "flang-experimental-integer-overflow">,
Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>,
HelpText<"Add nsw flag to internal operations such as do-variable increment (experimental)">;

//===----------------------------------------------------------------------===//
// FLangOption + CoreOption + NoXarchOption
//===----------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ void Flang::addCodegenOptions(const ArgList &Args,

Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir,
options::OPT_flang_deprecated_no_hlfir,
options::OPT_flang_experimental_integer_overflow,
options::OPT_fno_ppc_native_vec_elem_order,
options::OPT_fppc_native_vec_elem_order});
}
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Lower/LoweringOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,9 @@ ENUM_LOWERINGOPT(NoPPCNativeVecElemOrder, unsigned, 1, 0)
/// On by default.
ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)

/// If true, add nsw flags to loop variable increments.
/// Off by default.
ENUM_LOWERINGOPT(NSWOnLoopVarInc, unsigned, 1, 0)

#undef LOWERINGOPT
#undef ENUM_LOWERINGOPT
4 changes: 3 additions & 1 deletion flang/include/flang/Optimizer/Transforms/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace fir {
std::unique_ptr<mlir::Pass> createAffineDemotionPass();
std::unique_ptr<mlir::Pass>
createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {});
std::unique_ptr<mlir::Pass> createCFGConversionPassWithNSW();
std::unique_ptr<mlir::Pass> createExternalNameConversionPass();
std::unique_ptr<mlir::Pass>
createExternalNameConversionPass(bool appendUnderscore);
Expand Down Expand Up @@ -89,7 +90,8 @@ createFunctionAttrPass(FunctionAttrTypes &functionAttr, bool noInfsFPMath,
bool noSignedZerosFPMath, bool unsafeFPMath);

void populateCfgConversionRewrites(mlir::RewritePatternSet &patterns,
bool forceLoopToExecuteOnce = false);
bool forceLoopToExecuteOnce = false,
bool setNSW = false);

// declarative passes
#define GEN_PASS_REGISTRATION
Expand Down
5 changes: 4 additions & 1 deletion flang/include/flang/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,10 @@ def CFGConversion : Pass<"cfg-conversion"> {
let options = [
Option<"forceLoopToExecuteOnce", "always-execute-loop-body", "bool",
/*default=*/"false",
"force the body of a loop to execute at least once">
"force the body of a loop to execute at least once">,
Option<"setNSW", "set-nsw", "bool",
/*default=*/"false",
"set nsw on loop variable increment">
];
}

Expand Down
13 changes: 9 additions & 4 deletions flang/include/flang/Tools/CLOptions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,14 @@ static void addCanonicalizerPassWithoutRegionSimplification(
pm.addPass(mlir::createCanonicalizerPass(config));
}

inline void addCfgConversionPass(mlir::PassManager &pm) {
addNestedPassToAllTopLevelOperationsConditionally(
pm, disableCfgConversion, fir::createCFGConversion);
inline void addCfgConversionPass(
mlir::PassManager &pm, const MLIRToLLVMPassPipelineConfig &config) {
if (config.NSWOnLoopVarInc)
addNestedPassToAllTopLevelOperationsConditionally(
pm, disableCfgConversion, fir::createCFGConversionPassWithNSW);
else
addNestedPassToAllTopLevelOperationsConditionally(
pm, disableCfgConversion, fir::createCFGConversion);
}

inline void addAVC(
Expand Down Expand Up @@ -290,7 +295,7 @@ inline void createDefaultFIROptimizerPassPipeline(
pm.addPass(fir::createAliasTagsPass());

// convert control flow to CFG form
fir::addCfgConversionPass(pm);
fir::addCfgConversionPass(pm, pc);
pm.addPass(mlir::createConvertSCFToCFPass());

pm.addPass(mlir::createCanonicalizerPass(config));
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
bool NoSignedZerosFPMath =
false; ///< Set no-signed-zeros-fp-math attribute for functions.
bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions.
bool NSWOnLoopVarInc = false; ///< Add nsw flag to loop variable increments.
};

struct OffloadModuleOpts {
Expand Down
6 changes: 6 additions & 0 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,12 @@ bool CompilerInvocation::createFromArgs(
invoc.loweringOpts.setNoPPCNativeVecElemOrder(true);
}

// -flang-experimental-integer-overflow
if (args.hasArg(
clang::driver::options::OPT_flang_experimental_integer_overflow)) {
invoc.loweringOpts.setNSWOnLoopVarInc(true);
}

// Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
// -Rpass-analysis. This will be used later when processing and outputting the
// remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,9 @@ void CodeGenAction::generateLLVMIR() {
config.VScaleMax = vsr->second;
}

if (ci.getInvocation().getLoweringOpts().getNSWOnLoopVarInc())
config.NSWOnLoopVarInc = true;

// Create the pass pipeline
fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile());
(void)mlir::applyPassManagerCLOptions(pm);
Expand Down
12 changes: 9 additions & 3 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,11 @@ class FirConverter : public Fortran::lower::AbstractConverter {
void genFIRIncrementLoopEnd(IncrementLoopNestInfo &incrementLoopNestInfo) {
assert(!incrementLoopNestInfo.empty() && "empty loop nest");
mlir::Location loc = toLocation();
mlir::arith::IntegerOverflowFlags flags{};
if (getLoweringOptions().getNSWOnLoopVarInc())
flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw);
auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get(
builder->getContext(), flags);
for (auto it = incrementLoopNestInfo.rbegin(),
rend = incrementLoopNestInfo.rend();
it != rend; ++it) {
Expand All @@ -2021,15 +2026,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
builder->setInsertionPointToEnd(info.doLoop.getBody());
llvm::SmallVector<mlir::Value, 2> results;
results.push_back(builder->create<mlir::arith::AddIOp>(
loc, info.doLoop.getInductionVar(), info.doLoop.getStep()));
loc, info.doLoop.getInductionVar(), info.doLoop.getStep(),
iofAttr));
// Step loopVariable to help optimizations such as vectorization.
// Induction variable elimination will clean up as necessary.
mlir::Value step = builder->createConvert(
loc, info.getLoopVariableType(), info.doLoop.getStep());
mlir::Value loopVar =
builder->create<fir::LoadOp>(loc, info.loopVariable);
results.push_back(
builder->create<mlir::arith::AddIOp>(loc, loopVar, step));
builder->create<mlir::arith::AddIOp>(loc, loopVar, step, iofAttr));
builder->create<fir::ResultOp>(loc, results);
builder->setInsertionPointAfter(info.doLoop);
// The loop control variable may be used after the loop.
Expand All @@ -2054,7 +2060,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
if (info.hasRealControl)
value = builder->create<mlir::arith::AddFOp>(loc, value, step);
else
value = builder->create<mlir::arith::AddIOp>(loc, value, step);
value = builder->create<mlir::arith::AddIOp>(loc, value, step, iofAttr);
builder->create<fir::StoreOp>(loc, value, info.loopVariable);

genBranch(info.headerBlock);
Expand Down
9 changes: 7 additions & 2 deletions flang/lib/Lower/IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,11 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext stmtCtx;
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
mlir::Location loc = converter.getCurrentLocation();
mlir::arith::IntegerOverflowFlags flags{};
if (converter.getLoweringOptions().getNSWOnLoopVarInc())
flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw);
auto iofAttr =
mlir::arith::IntegerOverflowFlagsAttr::get(builder.getContext(), flags);
makeNextConditionalOn(builder, loc, checkResult, ok, inLoop);
const auto &itemList = std::get<0>(ioImpliedDo.t);
const auto &control = std::get<1>(ioImpliedDo.t);
Expand Down Expand Up @@ -965,7 +970,7 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter,
genItemList(ioImpliedDo);
builder.setInsertionPointToEnd(doLoopOp.getBody());
mlir::Value result = builder.create<mlir::arith::AddIOp>(
loc, doLoopOp.getInductionVar(), doLoopOp.getStep());
loc, doLoopOp.getInductionVar(), doLoopOp.getStep(), iofAttr);
builder.create<fir::ResultOp>(loc, result);
builder.setInsertionPointAfter(doLoopOp);
// The loop control variable may be used after the loop.
Expand Down Expand Up @@ -1007,7 +1012,7 @@ static void genIoLoop(Fortran::lower::AbstractConverter &converter,
mlir::OpResult iterateResult = builder.getBlock()->back().getResult(0);
mlir::Value inductionResult0 = iterWhileOp.getInductionVar();
auto inductionResult1 = builder.create<mlir::arith::AddIOp>(
loc, inductionResult0, iterWhileOp.getStep());
loc, inductionResult0, iterWhileOp.getStep(), iofAttr);
auto inductionResult = builder.create<mlir::arith::SelectOp>(
loc, iterateResult, inductionResult1, inductionResult0);
llvm::SmallVector<mlir::Value> results = {inductionResult, iterateResult};
Expand Down
44 changes: 34 additions & 10 deletions flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,19 @@ class CfgLoopConv : public mlir::OpRewritePattern<fir::DoLoopOp> {
public:
using OpRewritePattern::OpRewritePattern;

CfgLoopConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce)
CfgLoopConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW)
: mlir::OpRewritePattern<fir::DoLoopOp>(ctx),
forceLoopToExecuteOnce(forceLoopToExecuteOnce) {}
forceLoopToExecuteOnce(forceLoopToExecuteOnce), setNSW(setNSW) {}

mlir::LogicalResult
matchAndRewrite(DoLoopOp loop,
mlir::PatternRewriter &rewriter) const override {
auto loc = loop.getLoc();
mlir::arith::IntegerOverflowFlags flags{};
if (setNSW)
flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw);
auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get(
rewriter.getContext(), flags);

// Create the start and end blocks that will wrap the DoLoopOp with an
// initalizer and an end point
Expand Down Expand Up @@ -104,7 +109,7 @@ class CfgLoopConv : public mlir::OpRewritePattern<fir::DoLoopOp> {
rewriter.setInsertionPointToEnd(lastBlock);
auto iv = conditionalBlock->getArgument(0);
mlir::Value steppedIndex =
rewriter.create<mlir::arith::AddIOp>(loc, iv, step);
rewriter.create<mlir::arith::AddIOp>(loc, iv, step, iofAttr);
assert(steppedIndex && "must be a Value");
auto lastArg = conditionalBlock->getNumArguments() - 1;
auto itersLeft = conditionalBlock->getArgument(lastArg);
Expand Down Expand Up @@ -142,14 +147,15 @@ class CfgLoopConv : public mlir::OpRewritePattern<fir::DoLoopOp> {

private:
bool forceLoopToExecuteOnce;
bool setNSW;
};

/// Convert `fir.if` to control-flow
class CfgIfConv : public mlir::OpRewritePattern<fir::IfOp> {
public:
using OpRewritePattern::OpRewritePattern;

CfgIfConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce)
CfgIfConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW)
: mlir::OpRewritePattern<fir::IfOp>(ctx) {}

mlir::LogicalResult
Expand Down Expand Up @@ -214,13 +220,19 @@ class CfgIterWhileConv : public mlir::OpRewritePattern<fir::IterWhileOp> {
public:
using OpRewritePattern::OpRewritePattern;

CfgIterWhileConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce)
: mlir::OpRewritePattern<fir::IterWhileOp>(ctx) {}
CfgIterWhileConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce,
bool setNSW)
: mlir::OpRewritePattern<fir::IterWhileOp>(ctx), setNSW(setNSW) {}

mlir::LogicalResult
matchAndRewrite(fir::IterWhileOp whileOp,
mlir::PatternRewriter &rewriter) const override {
auto loc = whileOp.getLoc();
mlir::arith::IntegerOverflowFlags flags{};
if (setNSW)
flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw);
auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get(
rewriter.getContext(), flags);

// Start by splitting the block containing the 'fir.do_loop' into two parts.
// The part before will get the init code, the part after will be the end
Expand Down Expand Up @@ -248,7 +260,8 @@ class CfgIterWhileConv : public mlir::OpRewritePattern<fir::IterWhileOp> {
auto *terminator = lastBodyBlock->getTerminator();
rewriter.setInsertionPointToEnd(lastBodyBlock);
auto step = whileOp.getStep();
mlir::Value stepped = rewriter.create<mlir::arith::AddIOp>(loc, iv, step);
mlir::Value stepped =
rewriter.create<mlir::arith::AddIOp>(loc, iv, step, iofAttr);
assert(stepped && "must be a Value");

llvm::SmallVector<mlir::Value> loopCarried;
Expand Down Expand Up @@ -305,17 +318,23 @@ class CfgIterWhileConv : public mlir::OpRewritePattern<fir::IterWhileOp> {
rewriter.replaceOp(whileOp, args);
return success();
}

private:
bool setNSW;
};

/// Convert FIR structured control flow ops to CFG ops.
class CfgConversion : public fir::impl::CFGConversionBase<CfgConversion> {
public:
using CFGConversionBase<CfgConversion>::CFGConversionBase;

CfgConversion(bool setNSW) { this->setNSW = setNSW; }

void runOnOperation() override {
auto *context = &this->getContext();
mlir::RewritePatternSet patterns(context);
fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce);
fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce,
this->setNSW);
mlir::ConversionTarget target(*context);
target.addLegalDialect<mlir::affine::AffineDialect,
mlir::cf::ControlFlowDialect, FIROpsDialect,
Expand All @@ -337,7 +356,12 @@ class CfgConversion : public fir::impl::CFGConversionBase<CfgConversion> {

/// Expose conversion rewriters to other passes
void fir::populateCfgConversionRewrites(mlir::RewritePatternSet &patterns,
bool forceLoopToExecuteOnce) {
bool forceLoopToExecuteOnce,
bool setNSW) {
patterns.insert<CfgLoopConv, CfgIfConv, CfgIterWhileConv>(
patterns.getContext(), forceLoopToExecuteOnce);
patterns.getContext(), forceLoopToExecuteOnce, setNSW);
}

std::unique_ptr<mlir::Pass> fir::createCFGConversionPassWithNSW() {
return std::make_unique<CfgConversion>(true);
}
2 changes: 2 additions & 0 deletions flang/test/Driver/frontend-forwarding.f90
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
! RUN: -fversion-loops-for-stride \
! RUN: -flang-experimental-hlfir \
! RUN: -flang-deprecated-no-hlfir \
! RUN: -flang-experimental-integer-overflow \
! RUN: -fno-ppc-native-vector-element-order \
! RUN: -fppc-native-vector-element-order \
! RUN: -mllvm -print-before-all \
Expand Down Expand Up @@ -50,6 +51,7 @@
! CHECK: "-fversion-loops-for-stride"
! CHECK: "-flang-experimental-hlfir"
! CHECK: "-flang-deprecated-no-hlfir"
! CHECK: "-flang-experimental-integer-overflow"
! CHECK: "-fno-ppc-native-vector-element-order"
! CHECK: "-fppc-native-vector-element-order"
! CHECK: "-Rpass"
Expand Down
Loading
Loading