Author: Kaviya Rajendiran Date: 2026-09-17T14:07:46+05:30 New Revision: 9a3d449079fc97194c1aadcd9c8c999da6fe0a69
URL: https://github.com/llvm/llvm-project/commit/9a3d449079fc97194c1aadcd9c8c999da6fe0a69 DIFF: https://github.com/llvm/llvm-project/commit/9a3d449079fc97194c1aadcd9c8c999da6fe0a69.diff LOG: [Flang][Driver]Implemented the support for option -f[no-]optimize-sibling-calls in Flang (#216650) Added support for -foptimize-sibling-calls and -fno-optimize-sibling-calls in Flang. - Sibling call optimization is on by default and the driver pass the option `-f[no-]optimize-sibling-calls` to flang -fc1. - When `-fno-optimize-sibling-calls` flag is passed, it sets boolen `DisableTailCalls` and this results in adding the LLVM IR attribute `"disable-tail-calls"="true"` which disables sibling call optimization. Added: flang/test/Driver/fno-optimize-sibling-calls.f90 flang/test/Transforms/function-attr-disable-tail-calls.fir mlir/test/Target/LLVMIR/Import/disable-tail-calls.ll mlir/test/Target/LLVMIR/disable-tail-calls.mlir Modified: clang/include/clang/Options/Options.td clang/lib/Driver/ToolChains/Flang.cpp flang/include/flang/Frontend/CodeGenOptions.def flang/include/flang/Optimizer/Transforms/Passes.td flang/include/flang/Tools/CrossToolHelpers.h flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Optimizer/Passes/Pipelines.cpp flang/lib/Optimizer/Transforms/FunctionAttr.cpp mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td mlir/lib/Target/LLVMIR/ModuleImport.cpp mlir/lib/Target/LLVMIR/ModuleTranslation.cpp mlir/test/Target/LLVMIR/Import/import-failure.ll Removed: ################################################################################ diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 06461acdf216e..c4c49df73c15a 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -4395,11 +4395,12 @@ def fopenmp_new_driver : Flag<["-"], "fopenmp-new-driver">, Flags<[HelpHidden]>, Alias<offload_new_driver>; def fno_openmp_new_driver : Flag<["-"], "fno-openmp-new-driver">, Flags<[HelpHidden]>, Alias<no_offload_new_driver>; -def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>, - Visibility<[ClangOption, CC1Option]>, +def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, + Group<f_Group>, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Disable tail call optimization, keeping the call stack accurate">, MarshallingInfoFlag<CodeGenOpts<"DisableTailCalls">>; -def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; +def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, + Group<f_Group>, Visibility<[ClangOption, FlangOption]>; defm escaping_block_tail_calls : BoolFOption<"escaping-block-tail-calls", CodeGenOpts<"NoEscapingBlockTailCalls">, DefaultFalse, NegFlag<SetTrue, [], [ClangOption, CC1Option]>, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index dc1dd71526511..95a11eb36be08 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -385,6 +385,9 @@ void Flang::addCodegenOptions(const ArgList &Args, options::OPT_funroll_loops, options::OPT_fno_unroll_loops, options::OPT_relaxed_c_loc}); + Args.addOptOutFlag(CmdArgs, options::OPT_foptimize_sibling_calls, + options::OPT_fno_optimize_sibling_calls); + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); addSeparateSectionFlags(Triple, Args, CmdArgs); diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index d49a7f3647eec..a036311829e28 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -32,6 +32,7 @@ ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::Pro CODEGENOPT(InstrumentFunctions, 1, 0) ///< Set when -finstrument_functions is ///< enabled on the compile step. +CODEGENOPT(DisableTailCalls, 1, 0) ///< Do not emit tail calls CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index d7e271e1ed7b3..be2cbe31811e8 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -523,6 +523,10 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> { /*default=*/"false", "Set the use-sample-profile attribute on functions in the " "module.">, + Option<"disableTailCalls", "disable-tail-calls", "bool", + /*default=*/"false", + "Set the disable-tail-calls attribute on functions to prevent " + "tail call optimization.">, Option<"tuneCPU", "tune-cpu", "std::string", /*default=*/"", "Set the tune-cpu attribute on functions in the module.">, Option<"setNoCapture", "set-nocapture", "bool", /*default=*/"false", diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index 6c980c32c08c2..692b7fd7129f2 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -143,6 +143,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { InstrumentFunctionEntry = "__cyg_profile_func_enter"; InstrumentFunctionExit = "__cyg_profile_func_exit"; } + DisableTailCalls = opts.DisableTailCalls; DwarfVersion = opts.DwarfVersion; SplitDwarfFile = opts.SplitDwarfFile; DwarfDebugFlags = opts.DwarfDebugFlags; @@ -178,6 +179,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { false; ///< Compiling for an OpenMP target device. bool UseSampleProfile = false; ///< Enable sample based profiling bool DebugInfoForProfiling = false; ///< Enable extra debugging info + bool DisableTailCalls = false; ///< Disable tail call optimization bool EnableOpenMPSimd = false; ///< Enable OpenMP simd-only mode. bool SkipConvertComplexPow = false; ///< Do not run complex pow conversion. std::string InstrumentFunctionEntry = diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 9d333d473cb7c..85e5f477dcb8c 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -380,6 +380,9 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, if (args.hasArg(clang::options::OPT_finstrument_functions)) opts.InstrumentFunctions = 1; + if (args.hasArg(clang::options::OPT_fno_optimize_sibling_calls)) + opts.DisableTailCalls = 1; + // -fno-integrated-as: emit GNU Assembler compatible assembly. if (!args.hasFlag(clang::options::OPT_fintegrated_as, clang::options::OPT_fno_integrated_as, true)) diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 2b8c0fa7f2e8f..b73a1ce4a47c6 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -464,7 +464,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, config.InstrumentFunctionExit, config.NoInfsFPMath, config.NoNaNsFPMath, config.ApproxFuncFPMath, config.NoSignedZerosFPMath, config.UnsafeFPMath, config.Reciprocals, config.PreferVectorWidth, config.UseSampleProfile, - /*tuneCPU=*/"", setNoCapture, setNoAlias, setReadOnly})); + config.DisableTailCalls, /*tuneCPU=*/"", setNoCapture, setNoAlias, + setReadOnly})); if (config.EnableOpenMP) { pm.addNestedPass<mlir::func::FuncOp>( diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp index 45b32d13ad62e..1aadd16fe1cf4 100644 --- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp +++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp @@ -145,5 +145,12 @@ void FunctionAttrPass::runOnOperation() { llvmFuncOpName)), mlir::BoolAttr::get(context, true)); + if (disableTailCalls) + func->setAttr( + getLlvmFuncPropertyAttrName( + context, mlir::LLVM::LLVMFuncOp::getDisableTailCallsAttrName( + llvmFuncOpName)), + mlir::BoolAttr::get(context, true)); + LLVM_DEBUG(llvm::dbgs() << "=== End " DEBUG_TYPE " ===\n"); } diff --git a/flang/test/Driver/fno-optimize-sibling-calls.f90 b/flang/test/Driver/fno-optimize-sibling-calls.f90 new file mode 100644 index 0000000000000..6603e59c57875 --- /dev/null +++ b/flang/test/Driver/fno-optimize-sibling-calls.f90 @@ -0,0 +1,11 @@ +! Test -f[no-]optimize-sibling-calls driver forwarding to flang -fc1. + +! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefixes=FC1,OPTIMIZE-SIBLING +! RUN: %flang -### -foptimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefixes=FC1,OPTIMIZE-SIBLING +! RUN: %flang -### -fno-optimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefixes=FC1,NO-OPTIMIZE-SIBLING +! RUN: %flang -### -fno-optimize-sibling-calls -foptimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefixes=FC1,OPTIMIZE-SIBLING +! RUN: %flang -### -foptimize-sibling-calls -fno-optimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefixes=FC1,NO-OPTIMIZE-SIBLING + +! FC1: "-fc1" +! OPTIMIZE-SIBLING-NOT: "-fno-optimize-sibling-calls" +! NO-OPTIMIZE-SIBLING-SAME: "-fno-optimize-sibling-calls" diff --git a/flang/test/Transforms/function-attr-disable-tail-calls.fir b/flang/test/Transforms/function-attr-disable-tail-calls.fir new file mode 100644 index 0000000000000..d8657a1294d30 --- /dev/null +++ b/flang/test/Transforms/function-attr-disable-tail-calls.fir @@ -0,0 +1,11 @@ +// RUN: fir-opt --function-attr="disable-tail-calls=true" %s | FileCheck %s --check-prefix=ENABLED +// RUN: fir-opt --function-attr="disable-tail-calls=false" %s | FileCheck %s --check-prefix=DISABLED + +func.func @_QPf() { + return +} + +// ENABLED: func.func @_QPf() attributes {llvm.disable_tail_calls = true} + +// DISABLED: func.func @_QPf() +// DISABLED-NOT: llvm.disable_tail_calls diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index edd52db2a4a5b..5998bd01f9bdf 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -2159,7 +2159,8 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [ OptionalAttr<I32Attr>:$intel_reqd_sub_group_size, OptionalAttr<LLVM_FunctionMetadataArrayAttr>:$function_metadata, OptionalAttr<UWTableKindAttr>:$uwtable_kind, - OptionalAttr<BoolAttr>:$use_sample_profile + OptionalAttr<BoolAttr>:$use_sample_profile, + OptionalAttr<BoolAttr>:$disable_tail_calls ); let regions = (region AnyRegion:$body); diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index fa40b51c22f05..bfecde8b664a9 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -2903,6 +2903,7 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{ StringLiteral("alwaysinline"), StringLiteral("cold"), StringLiteral("convergent"), + StringLiteral("disable-tail-calls"), StringLiteral("fp-contract"), StringLiteral("frame-pointer"), StringLiteral("hot"), @@ -3093,6 +3094,16 @@ void ModuleImport::processFunctionAttributes(llvm::Function *func, if (func->hasFnAttribute("use-sample-profile")) funcOp.setUseSampleProfile(true); + if (llvm::Attribute attr = func->getFnAttribute("disable-tail-calls"); + attr.isStringAttribute()) { + StringRef val = attr.getValueAsString(); + if (val == "true") + funcOp.setDisableTailCalls(true); + else if (val != "false") + emitError(funcOp.getLoc()) + << "unknown value '" << val << "' for 'disable-tail-calls' attribute"; + } + if (llvm::Attribute attr = func->getFnAttribute("target-cpu"); attr.isStringAttribute()) funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString())); diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index ee088aefcb2c4..50365b5a5b3a1 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -1742,6 +1742,10 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) { if (func.getUseSampleProfile()) llvmFunc->addFnAttr("use-sample-profile"); + if (auto disableTailCalls = func.getDisableTailCalls()) + llvmFunc->addFnAttr("disable-tail-calls", + llvm::toStringRef(*disableTailCalls)); + if (auto attr = func.getVscaleRange()) llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs( getLLVMContext(), attr->getMinRange().getInt(), diff --git a/mlir/test/Target/LLVMIR/Import/disable-tail-calls.ll b/mlir/test/Target/LLVMIR/Import/disable-tail-calls.ll new file mode 100644 index 0000000000000..33822291e1c45 --- /dev/null +++ b/mlir/test/Target/LLVMIR/Import/disable-tail-calls.ll @@ -0,0 +1,16 @@ +; RUN: mlir-translate -import-llvm -split-input-file %s 2>&1 | FileCheck %s + +; CHECK-LABEL: llvm.func @disable_tail_calls() +; CHECK-SAME: disable_tail_calls = true +define void @disable_tail_calls() #0 { + ret void +} + +; CHECK-LABEL: llvm.func @disable_tail_calls_false() +; CHECK-NOT: disable_tail_calls +define void @disable_tail_calls_false() #1 { + ret void +} + +attributes #0 = { "disable-tail-calls"="true" } +attributes #1 = { "disable-tail-calls"="false" } diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll index 9015eff87a8c7..5bf45ccfbec55 100644 --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -567,3 +567,10 @@ define i32 @metadata_ref_global_dtors() { !9 = !{!"DetailedSummary", !10} !10 = !{!11} !11 = !{i32 10000, i64 1, i32 1} + +; CHECK: error: unknown value 'invalid' for 'disable-tail-calls' attribute +define void @disable_tail_calls_invalid() #0 { + ret void +} + +attributes #0 = { "disable-tail-calls"="invalid" } diff --git a/mlir/test/Target/LLVMIR/disable-tail-calls.mlir b/mlir/test/Target/LLVMIR/disable-tail-calls.mlir new file mode 100644 index 0000000000000..fc7ecd185b492 --- /dev/null +++ b/mlir/test/Target/LLVMIR/disable-tail-calls.mlir @@ -0,0 +1,14 @@ +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s + +// CHECK: define void @disable_tail_calls() #[[ATTRS_TRUE:.*]] { +llvm.func @disable_tail_calls() attributes {disable_tail_calls = true} { + llvm.return +} + +// CHECK: define void @disable_tail_calls_false() #[[ATTRS_FALSE:.*]] { +llvm.func @disable_tail_calls_false() attributes {disable_tail_calls = false} { + llvm.return +} + +// CHECK: attributes #[[ATTRS_TRUE]] = { "disable-tail-calls"="true" } +// CHECK: attributes #[[ATTRS_FALSE]] = { "disable-tail-calls"="false" } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
