Skip to content

Commit d4e99bc

Browse files
bors[bot]vext01
andauthored
44: Add the `yk_unroll_safe` attribute. r=ltratt a=vext01 Co-authored-by: Edd Barrett <[email protected]>
2 parents 78e5e93 + e66a142 commit d4e99bc

File tree

8 files changed

+79
-3
lines changed

8 files changed

+79
-3
lines changed

clang/include/clang/Basic/Attr.td

+7
Original file line numberDiff line numberDiff line change
@@ -4072,3 +4072,10 @@ def YkOutline : InheritableAttr {
40724072
let Documentation = [YkOutlineDocs];
40734073
let SimpleHandler = 1;
40744074
}
4075+
4076+
def YkUnrollSafe : InheritableAttr {
4077+
let Spellings = [GCC<"yk_unroll_safe">, Declspec<"yk_unroll_safe">];
4078+
let Subjects = SubjectList<[Function]>;
4079+
let Documentation = [YkUnrollSafeDocs];
4080+
let SimpleHandler = 1;
4081+
}

clang/include/clang/Basic/AttrDocs.td

+9
Original file line numberDiff line numberDiff line change
@@ -6667,3 +6667,12 @@ def YkOutlineDocs : Documentation {
66676667
to the annotated function.
66686668
}];
66696669
}
6670+
6671+
def YkUnrollSafeDocs : Documentation {
6672+
let Category = DocCatFunction;
6673+
let Content = [{
6674+
The ``yk_unroll_safe`` attribute tells the Yk JIT that during tracing, calls
6675+
to the annotated function can be inlined, even if it contains loops. By
6676+
default only calls to functions that contain no loops are inlined.
6677+
}];
6678+
}

clang/include/clang/Basic/CodeGenOptions.def

+2
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,8 @@ CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information
333333
CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
334334
///< external references to a PCH or module.
335335

336+
CODEGENOPT(YkNoinlineFuncsWithLoops, 1, 0) ///< Yk JIT: by default don't inline functions
337+
///< containing loops.
336338
CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
337339
///< contain explicit imports for
338340
///< anonymous namespaces

clang/include/clang/Driver/Options.td

+5
Original file line numberDiff line numberDiff line change
@@ -4739,6 +4739,11 @@ def finline_limit_EQ : Joined<["-"], "finline-limit=">, Group<clang_ignored_gcc_
47394739
defm finline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_gcc_optimization_f_Group>;
47404740
defm inline_small_functions : BooleanFFlag<"inline-small-functions">,
47414741
Group<clang_ignored_gcc_optimization_f_Group>;
4742+
defm yk_noinline_funcs_with_loops : BoolOption<"f", "yk-noinline-funcs-with-loops",
4743+
CodeGenOpts<"YkNoinlineFuncsWithLoops">, DefaultFalse,
4744+
NegFlag<SetFalse, []>,
4745+
PosFlag<SetTrue, [], "Don't inline functions containing loops by default (used for the Yk JIT).">,
4746+
BothFlags<[CC1Option, CoreOption]>>;
47424747
defm ipa_cp : BooleanFFlag<"ipa-cp">,
47434748
Group<clang_ignored_gcc_optimization_f_Group>;
47444749
defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;

clang/lib/CodeGen/CodeGenModule.cpp

+36-3
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@
4949
#include "clang/Frontend/FrontendDiagnostic.h"
5050
#include "llvm/ADT/StringSwitch.h"
5151
#include "llvm/ADT/Triple.h"
52+
#include "llvm/Analysis/LoopInfo.h"
5253
#include "llvm/Analysis/TargetLibraryInfo.h"
5354
#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
5455
#include "llvm/IR/CallingConv.h"
5556
#include "llvm/IR/DataLayout.h"
57+
#include "llvm/IR/Dominators.h"
5658
#include "llvm/IR/Intrinsics.h"
5759
#include "llvm/IR/LLVMContext.h"
5860
#include "llvm/IR/Module.h"
@@ -2049,10 +2051,41 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
20492051
}
20502052

20512053
if (D->hasAttr<YkOutlineAttr>()) {
2052-
// Prevent the Yk trace compiler from inlining the call.
2053-
B.addAttribute("yk_outline");
2054-
// Prevent LLVM from inlining the call when optimising the trace.
20552054
B.addAttribute(llvm::Attribute::NoInline);
2055+
B.addAttribute("yk_outline");
2056+
}
2057+
2058+
// Mark all functions containing loops with `yk_outline` unless the function
2059+
// was annotated `yk_unroll_safe`.
2060+
//
2061+
// This needs to be gated so that we don't impact the normal clang and LLVM
2062+
// tests.
2063+
//
2064+
// If `F->empty()` then this is merely a function declaration for which we
2065+
// have no IR. In this case the JIT will be unable to inline calls to this
2066+
// function anyway, so there's no need to conservatively add `yk_outline`.
2067+
if (CodeGenOpts.YkNoinlineFuncsWithLoops && !F->empty()) {
2068+
llvm::DominatorTree DT(*F);
2069+
llvm::LoopInfo LI(DT);
2070+
if (!LI.empty()) {
2071+
if (!D->hasAttr<YkUnrollSafeAttr>())
2072+
B.addAttribute("yk_outline");
2073+
2074+
// Note that we still mark the loopy function `F` with `noinline` (to
2075+
// block it being inlined during AOT compilation) regardless of if it can
2076+
// be inlined into the trace or not, because:
2077+
//
2078+
// * if `F` is to be inlined into a trace and we don't block AOT inlining
2079+
// then `F` may get AOT inlined into a parent function which contains
2080+
// loops but isn't marked `yk_unroll_safe`. The trace would have to call
2081+
// the parent, meaning that `F` would not be inlined into the trace!
2082+
//
2083+
// * if `F` is to be outlined in a trace and we don't block AOT inlining,
2084+
// then `F` may be inlined into a parent function and tracing the parent
2085+
// function would give a trace where `F` was actually inlined instead of
2086+
// outlined.
2087+
B.addAttribute(llvm::Attribute::NoInline);
2088+
}
20562089
}
20572090

20582091
F->addFnAttrs(B);

clang/lib/Driver/ToolChains/Clang.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -5399,6 +5399,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
53995399
else if (UnwindTables)
54005400
CmdArgs.push_back("-funwind-tables=1");
54015401

5402+
if (Args.hasFlag(options::OPT_fyk_noinline_funcs_with_loops,
5403+
options::OPT_fno_yk_noinline_funcs_with_loops, false))
5404+
CmdArgs.push_back("-fyk-noinline-funcs-with-loops");
5405+
54025406
// Prepare `-aux-target-cpu` and `-aux-target-feature` unless
54035407
// `--gpu-use-aux-triple-only` is specified.
54045408
if (!Args.getLastArg(options::OPT_gpu_use_aux_triple_only) &&

clang/test/Misc/pragma-attribute-supported-attributes-list.test

+1
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,6 @@
197197
// CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method)
198198
// CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function, SubjectMatchRule_objc_method)
199199
// CHECK-NEXT: YkOutline (SubjectMatchRule_function)
200+
// CHECK-NEXT: YkUnrollSafe (SubjectMatchRule_function)
200201
// CHECK-NEXT: ZeroCallUsedRegs (SubjectMatchRule_function)
201202
// CHECK-NEXT: End of supported attributes.
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang -emit-llvm -fyk-noinline-funcs-with-loops -c -O0 -o - %s | llvm-dis | grep "call .*@never_aot_inline("
2+
// RUN: %clang -emit-llvm -fyk-noinline-funcs-with-loops -c -O1 -o - %s | llvm-dis | grep "call .*@never_aot_inline("
3+
// RUN: %clang -emit-llvm -fyk-noinline-funcs-with-loops -c -O2 -o - %s | llvm-dis | grep "call .*@never_aot_inline("
4+
// RUN: %clang -emit-llvm -fyk-noinline-funcs-with-loops -c -O3 -o - %s | llvm-dis | grep "call .*@never_aot_inline("
5+
6+
#include <stdio.h>
7+
8+
static void never_aot_inline(int i) {
9+
while (i--)
10+
putchar('.');
11+
}
12+
13+
int main(int argc, char **argv) {
14+
never_aot_inline(argc);
15+
}

0 commit comments

Comments
 (0)