[Flang][Driver]Implemented the support for option -f[no-]optimize-sibling-calls in Flang - #216650
[Flang][Driver]Implemented the support for option -f[no-]optimize-sibling-calls in Flang#216650kaviya2510 wants to merge 1 commit into
Conversation
|
@llvm/pr-subscribers-flang-fir-hlfir @llvm/pr-subscribers-clang-driver Author: Kaviya Rajendiran (kaviya2510) ChangesAdded support for -foptimize-sibling-calls and -fno-optimize-sibling-calls in Flang.
Full diff: https://github.com/llvm/llvm-project/pull/216650.diff 15 Files Affected:
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index adc4224dd561c..71504c806d886 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4342,11 +4342,15 @@ def fopenmp_new_driver : Flag<["-"], "fopenmp-new-driver">, Flags<[HelpHidden]>,
def fno_openmp_new_driver : Flag<["-"], "fno-openmp-new-driver">,
Flags<[HelpHidden]>,
HelpText<"Don't use the new driver for OpenMP offloading.">;
-def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>,
- Visibility<[ClangOption, CC1Option]>,
- 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 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>, Visibility<[ClangOption, FlangOption, FC1Option]>;
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 a48e41159f367..0c74f2b8365db 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -367,6 +367,10 @@ void Flang::addCodegenOptions(const ArgList &Args,
options::OPT_funroll_loops, options::OPT_fno_unroll_loops,
options::OPT_relaxed_c_loc});
+ if (Arg *A = Args.getLastArg(options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls))
+ A->render(Args, CmdArgs);
+
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..537a54f917d16 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 e7bb8ae9bb9bf..e770144dfc69e 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -489,6 +489,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 fb8007637b114..3b49354a8ff96 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;
@@ -177,6 +178,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 b57bc4583be38..b20ecc3000cfd 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -376,6 +376,12 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
if (args.hasArg(clang::options::OPT_finstrument_functions))
opts.InstrumentFunctions = 1;
+ if (const llvm::opt::Arg *a = args.getLastArg(
+ clang::options::OPT_foptimize_sibling_calls,
+ clang::options::OPT_fno_optimize_sibling_calls))
+ opts.DisableTailCalls =
+ a->getOption().matches(clang::options::OPT_fno_optimize_sibling_calls);
+
// -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 15a342e10fc7f..98b7574d0849a 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -441,7 +441,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..163803fdff759
--- /dev/null
+++ b/flang/test/Driver/fno-optimize-sibling-calls.f90
@@ -0,0 +1,20 @@
+! Test -f[no-]optimize-sibling-calls driver forwarding to flang -fc1.
+
+! RUN: %flang -### %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPTIMIZE-SIBLING
+! RUN: %flang -### -foptimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPTIMIZE-SIBLING-FORWARD
+! RUN: %flang -### -fno-optimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPTIMIZE-NOSIBLING
+! RUN: %flang -### -fno-optimize-sibling-calls -foptimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPTIMIZE-SIBLING-FORWARD
+! RUN: %flang -### -foptimize-sibling-calls -fno-optimize-sibling-calls %s 2>&1 | FileCheck %s --check-prefix=CHECK-OPTIMIZE-NOSIBLING
+
+! CHECK-OPTIMIZE-SIBLING: "-fc1"
+! CHECK-OPTIMIZE-SIBLING-NOT: "-fno-optimize-sibling-calls"
+! CHECK-OPTIMIZE-SIBLING-NOT: "-foptimize-sibling-calls"
+
+! CHECK-OPTIMIZE-SIBLING-FORWARD: "-fc1"{{.*}}"-foptimize-sibling-calls"
+! CHECK-OPTIMIZE-SIBLING-FORWARD-NOT: "-fno-optimize-sibling-calls"
+
+! CHECK-OPTIMIZE-NOSIBLING: "-fc1"{{.*}}"-fno-optimize-sibling-calls"
+! CHECK-OPTIMIZE-NOSIBLING-NOT: "-foptimize-sibling-calls"
+
+subroutine test
+end subroutine test
diff --git a/flang/test/Integration/disable-tail-calls.f90 b/flang/test/Integration/disable-tail-calls.f90
new file mode 100644
index 0000000000000..117512bc7739c
--- /dev/null
+++ b/flang/test/Integration/disable-tail-calls.f90
@@ -0,0 +1,12 @@
+! test -fno-optimize-sibling-calls flag disables tail call optimization
+
+! RUN: %flang_fc1 -emit-llvm -O2 -fno-optimize-sibling-calls -o - %s | FileCheck %s
+
+recursive subroutine f(n)
+ integer, intent(in) :: n
+ if (n > 0) call f(n - 1)
+end subroutine f
+
+! CHECK: define void @f_{{.*}}#[[ATTRS:[0-9]+]]
+! CHECK: call void @f_
+! CHECK: attributes #[[ATTRS]]{{.*}}"disable-tail-calls"="true"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index e670e6699e57d..e578d5c22d36c 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2106,7 +2106,8 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
OptionalAttr<DenseI32ArrayAttr>:$reqd_work_group_size,
OptionalAttr<I32Attr>:$intel_reqd_sub_group_size,
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 2ab4529ddef53..d061397d38edc 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2833,6 +2833,7 @@ static constexpr std::array kExplicitLLVMFuncOpAttributes{
StringLiteral("alwaysinline"),
StringLiteral("cold"),
StringLiteral("convergent"),
+ StringLiteral("disable-tail-calls"),
StringLiteral("fp-contract"),
StringLiteral("frame-pointer"),
StringLiteral("hot"),
@@ -3020,6 +3021,10 @@ 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())
+ funcOp.setDisableTailCalls(attr.getValueAsString() == "true");
+
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 b87a581a5185e..c5fd545bbbaae 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1706,6 +1706,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..3b1b894532d99
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/disable-tail-calls.ll
@@ -0,0 +1,9 @@
+; RUN: mlir-translate -import-llvm %s | FileCheck %s
+
+; CHECK-LABEL: llvm.func @disable_tail_calls()
+; CHECK-SAME: disable_tail_calls = true
+define void @disable_tail_calls() #0 {
+ ret void
+}
+
+attributes #0 = { "disable-tail-calls"="true" }
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..c28f248443c42
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/disable-tail-calls.mlir
@@ -0,0 +1,7 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK: define void @disable_tail_calls() #[[ATTRS:.*]] {
+// CHECK: attributes #[[ATTRS]] = { "disable-tail-calls"="true" }
+llvm.func @disable_tail_calls() attributes {disable_tail_calls = true} {
+ llvm.return
+}
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
…ing-calls in Flang
45f4e1c to
aac8799
Compare
|
|
||
| CODEGENOPT(InstrumentFunctions, 1, 0) ///< Set when -finstrument_functions is | ||
| ///< enabled on the compile step. | ||
| CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls |
|
|
||
| if (llvm::Attribute attr = func->getFnAttribute("disable-tail-calls"); | ||
| attr.isStringAttribute()) | ||
| funcOp.setDisableTailCalls(attr.getValueAsString() == "true"); |
There was a problem hiding this comment.
nit: maybe this should generate an error for values which are neither "true" nor "false"
| if (const llvm::opt::Arg *a = | ||
| args.getLastArg(clang::options::OPT_foptimize_sibling_calls, | ||
| clang::options::OPT_fno_optimize_sibling_calls)) | ||
| opts.DisableTailCalls = | ||
| a->getOption().matches(clang::options::OPT_fno_optimize_sibling_calls); | ||
|
|
There was a problem hiding this comment.
Can you please use the established code pattern that uses arg.hasFlag(true-flag, false-flag, /*Default=*/true)?
| @@ -0,0 +1,12 @@ | |||
| ! test -fno-optimize-sibling-calls flag disables tail call optimization | |||
|
|
|||
| ! RUN: %flang_fc1 -emit-llvm -O2 -fno-optimize-sibling-calls -o - %s | FileCheck %s | |||
There was a problem hiding this comment.
Can you please add more cases, e.g. no option, combinations of true/false flags?
Added support for -foptimize-sibling-calls and -fno-optimize-sibling-calls in Flang.
-f[no-]optimize-sibling-callsto flang -fc1.-fno-optimize-sibling-callsflag is passed, it sets boolenDisableTailCallsand this results in adding the LLVM IR attribute"disable-tail-calls"="true"which disables sibling call optimization.