forked from OSchip/llvm-project
[IROutliner] Adding option to enable outlining from linkonceodr functions
There are functions that the linker is able to automatically deduplicate, we do not outline from these functions by default. This allows for outlining from those functions. Tests: llvm/test/Transforms/IROutliner/outlining-odr.ll Reviewers: jroelofs, paquette Differential Revision: https://reviews.llvm.org/D87309
This commit is contained in:
parent
9c0c123b0b
commit
fe431103b6
|
@ -258,6 +258,10 @@ private:
|
|||
std::vector<Function *> &FuncsToRemove,
|
||||
unsigned &OutlinedFunctionNum);
|
||||
|
||||
/// If true, enables us to outline from functions that have LinkOnceFromODR
|
||||
/// linkages.
|
||||
bool OutlineFromLinkODRs = false;
|
||||
|
||||
/// If false, we do not worry if the cost is greater than the benefit. This
|
||||
/// is for debugging and testing, so that we can test small cases to ensure
|
||||
/// that the outlining is being done correctly.
|
||||
|
|
|
@ -30,6 +30,16 @@
|
|||
using namespace llvm;
|
||||
using namespace IRSimilarity;
|
||||
|
||||
// Set to true if the user wants the ir outliner to run on linkonceodr linkage
|
||||
// functions. This is false by default because the linker can dedupe linkonceodr
|
||||
// functions. Since the outliner is confined to a single module (modulo LTO),
|
||||
// this is off by default. It should, however, be the default behavior in
|
||||
// LTO.
|
||||
static cl::opt<bool> EnableLinkOnceODRIROutlining(
|
||||
"enable-linkonceodr-ir-outlining", cl::Hidden,
|
||||
cl::desc("Enable the IR outliner on linkonceodr functions"),
|
||||
cl::init(false));
|
||||
|
||||
// This is a debug option to test small pieces of code to ensure that outlining
|
||||
// works correctly.
|
||||
static cl::opt<bool> NoCostModel(
|
||||
|
@ -1243,6 +1253,10 @@ void IROutliner::pruneIncompatibleRegions(
|
|||
if (IRSC.getStartBB()->hasAddressTaken())
|
||||
continue;
|
||||
|
||||
if (IRSC.front()->Inst->getFunction()->hasLinkOnceODRLinkage() &&
|
||||
!OutlineFromLinkODRs)
|
||||
continue;
|
||||
|
||||
// Greedily prune out any regions that will overlap with already chosen
|
||||
// regions.
|
||||
if (CurrentEndIdx != 0 && StartIdx <= CurrentEndIdx)
|
||||
|
@ -1659,6 +1673,7 @@ unsigned IROutliner::doOutline(Module &M) {
|
|||
|
||||
bool IROutliner::run(Module &M) {
|
||||
CostModel = !NoCostModel;
|
||||
OutlineFromLinkODRs = EnableLinkOnceODRIROutlining;
|
||||
|
||||
return doOutline(M) > 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -verify -iroutliner --ir-outlining-no-cost < %s | FileCheck %s
|
||||
; RUN: opt -S -verify -iroutliner -enable-linkonceodr-ir-outlining --ir-outlining-no-cost < %s | FileCheck -check-prefix=ODR %s
|
||||
|
||||
; This test looks at the constants in the regions, and if it they are the
|
||||
; same it outlines them as constants rather than elevating them to arguments.
|
||||
|
||||
define linkonce_odr void @outline_odr1() {
|
||||
; ODR-LABEL: @outline_odr1(
|
||||
; ODR-NEXT: entry:
|
||||
; ODR-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: [[B:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: [[C:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]])
|
||||
; ODR-NEXT: ret void
|
||||
; CHECK-LABEL: @outline_odr1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store i32 2, i32* [[A]], align 4
|
||||
; CHECK-NEXT: store i32 3, i32* [[B]], align 4
|
||||
; CHECK-NEXT: store i32 4, i32* [[C]], align 4
|
||||
; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[A]], align 4
|
||||
; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[B]], align 4
|
||||
; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[C]], align 4
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
store i32 2, i32* %a, align 4
|
||||
store i32 3, i32* %b, align 4
|
||||
store i32 4, i32* %c, align 4
|
||||
%al = load i32, i32* %a
|
||||
%bl = load i32, i32* %b
|
||||
%cl = load i32, i32* %c
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @outline_odr2() {
|
||||
; ODR-LABEL: @outline_odr2(
|
||||
; ODR-NEXT: entry:
|
||||
; ODR-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: [[B:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: [[C:%.*]] = alloca i32, align 4
|
||||
; ODR-NEXT: call void @outlined_ir_func_0(i32* [[A]], i32* [[B]], i32* [[C]])
|
||||
; ODR-NEXT: ret void
|
||||
; CHECK-LABEL: @outline_odr2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: store i32 2, i32* [[A]], align 4
|
||||
; CHECK-NEXT: store i32 3, i32* [[B]], align 4
|
||||
; CHECK-NEXT: store i32 4, i32* [[C]], align 4
|
||||
; CHECK-NEXT: [[AL:%.*]] = load i32, i32* [[A]], align 4
|
||||
; CHECK-NEXT: [[BL:%.*]] = load i32, i32* [[B]], align 4
|
||||
; CHECK-NEXT: [[CL:%.*]] = load i32, i32* [[C]], align 4
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
store i32 2, i32* %a, align 4
|
||||
store i32 3, i32* %b, align 4
|
||||
store i32 4, i32* %c, align 4
|
||||
%al = load i32, i32* %a
|
||||
%bl = load i32, i32* %b
|
||||
%cl = load i32, i32* %c
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue