Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -2240,6 +2240,9 @@ Backends are free to ignore the attribute if they don't need to support different maximum legal vector types or such information can be inferred by other attributes. + ``"nooutline"`` + This attribute indicates that outlining passes should not modify the + function. Call Site Attributes ---------------------- Index: llvm/lib/CodeGen/MachineOutliner.cpp =================================================================== --- llvm/lib/CodeGen/MachineOutliner.cpp +++ llvm/lib/CodeGen/MachineOutliner.cpp @@ -880,10 +880,13 @@ // iterating over each Function in M. for (Function &F : M) { - // If there's nothing in F, then there's no reason to try and outline from - // it. - if (F.empty()) + if (F.hasFnAttribute("nooutline")) { + LLVM_DEBUG({ + dbgs() << "... Skipping function with nooutline attribute: " + << F.getName() << "\n"; + }); continue; + } // There's something in F. Check if it has a MachineFunction associated with // it. Index: llvm/lib/Transforms/IPO/IROutliner.cpp =================================================================== --- llvm/lib/Transforms/IPO/IROutliner.cpp +++ llvm/lib/Transforms/IPO/IROutliner.cpp @@ -2426,6 +2426,7 @@ PreviouslyOutlined = false; unsigned StartIdx = IRSC.getStartIdx(); unsigned EndIdx = IRSC.getEndIdx(); + const Function &FnForCurrCand = *IRSC.getFunction(); for (unsigned Idx = StartIdx; Idx <= EndIdx; Idx++) if (Outlined.contains(Idx)) { @@ -2445,9 +2446,17 @@ if (BBHasAddressTaken) continue; - if (IRSC.getFunction()->hasOptNone()) + if (FnForCurrCand.hasOptNone()) continue; + if (FnForCurrCand.hasFnAttribute("nooutline")) { + LLVM_DEBUG({ + dbgs() << "... Skipping function with nooutline attribute: " + << FnForCurrCand.getName() << "\n"; + }); + continue; + } + if (IRSC.front()->Inst->getFunction()->hasLinkOnceODRLinkage() && !OutlineFromLinkODRs) continue; Index: llvm/test/CodeGen/AArch64/machine-outliner-nooutline-attribute.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/machine-outliner-nooutline-attribute.mir @@ -0,0 +1,42 @@ +# RUN: llc -mtriple=aarch64 -debug-only=machine-outliner -run-pass=machine-outliner -verify-machineinstrs %s -o - 2>&1 | FileCheck %s +# REQUIRES: asserts + +# CHECK: ... Skipping function with nooutline attribute: no_outline +# CHECK-NOT: ... Skipping function with nooutline attribute: baz +# CHECK-NOT: OUTLINED + +--- | + define void @no_outline() #0 { unreachable } + define void @baz() { unreachable } + attributes #0 = { noredzone "nooutline" } +... +--- + +name: no_outline +tracksRegLiveness: true +body: | + bb.0: + liveins: $w0, $lr, $w8 + $sp = frame-setup SUBXri $sp, 32, 0 + $fp = frame-setup ADDXri $sp, 16, 0 + bb.1: + BL @baz, implicit-def dead $lr, implicit $sp + $w17 = ORRWri $wzr, 1 + $w17 = ORRWri $wzr, 1 + $w0 = ORRWri $wzr, 4 + BL @baz, implicit-def dead $lr, implicit $sp + $w17 = ORRWri $wzr, 1 + $w17 = ORRWri $wzr, 1 + $w0 = ORRWri $wzr, 3 + BL @baz, implicit-def dead $lr, implicit $sp + $w17 = ORRWri $wzr, 1 + $w17 = ORRWri $wzr, 1 + $w0 = ORRWri $wzr, 2 + BL @baz, implicit-def dead $lr, implicit $sp + $w17 = ORRWri $wzr, 1 + $w17 = ORRWri $wzr, 1 + $w0 = ORRWri $wzr, 1 + bb.2: + $fp, $lr = LDPXi $sp, 2 + RET undef $lr + Index: llvm/test/Transforms/IROutliner/nooutline-attribute.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/IROutliner/nooutline-attribute.ll @@ -0,0 +1,30 @@ +; RUN: opt -S -verify -debug-only=iroutliner -iroutliner -ir-outlining-no-cost %s -o - 2>&1 | FileCheck %s +; REQUIRES: asserts + +; CHECK-NOT: ... Skipping function with nooutline attribute: outlinable +; CHECK-NOT: @outlined_ir_func +; CHECK: ... Skipping function with nooutline attribute: nooutline1 +; CHECK: ... Skipping function with nooutline attribute: nooutline2 + +define void @outlinable() { ret void } + +define i8 @nooutline1(ptr noalias %s, ptr noalias %d, i64 %len) "nooutline" { + %a = load i8, ptr %s + %b = load i8, ptr %d + call void @llvm.memcpy.p0i8.p0i8.i64(ptr %d, ptr %s, i64 %len, i1 false) + %c = add i8 %a, %b + %ret = load i8, ptr %s + ret i8 %ret +} + +define i8 @nooutline2(ptr noalias %s, ptr noalias %d, i64 %len) "nooutline" { + %a = load i8, ptr %s + %b = load i8, ptr %d + call void @llvm.memcpy.p0i8.p0i8.i64(ptr %d, ptr %s, i64 %len, i1 false) + %c = add i8 %a, %b + %ret = load i8, ptr %s + ret i8 %ret +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1) +