summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/CodeExtractor
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/CodeExtractor')
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-13-LoopExtractorCrash.ll75
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-14-DominanceProblem.ll33
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-14-NoSwitchSupport.ll28
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-17-MissedLiveIns.ll47
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-17-UpdatePHIsOutsideRegion.ll23
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll198
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-08-12-BlockExtractPHI.ll26
-rw-r--r--llvm/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll18
-rw-r--r--llvm/test/Transforms/CodeExtractor/BlockAddressReference.ll36
-rw-r--r--llvm/test/Transforms/CodeExtractor/BlockAddressSelfReference.ll50
-rw-r--r--llvm/test/Transforms/CodeExtractor/ExtractedFnEntryCount.ll33
-rw-r--r--llvm/test/Transforms/CodeExtractor/MultipleExitBranchProb.ll34
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAlloca.ll68
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAlloca2.ll65
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAlloca4.ll70
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAlloca5.ll66
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAnd.ll56
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAndOr.ll63
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll85
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineCallRef.ll56
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineDebug.ll106
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineEntryPHICost.ll40
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineEntryUpdate.ll41
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineHighCost.ll107
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll51
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineLiveAcross.ll61
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineNoInline.ll45
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineNoLiveOut.ll62
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineNotViable.ll63
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineORECrash.ll170
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll138
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineOr.ll97
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineOrAnd.ll71
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll169
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlinePGORegion.ll120
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineVarArg.ll107
-rw-r--r--llvm/test/Transforms/CodeExtractor/PartialInlineVarArgsDebug.ll68
-rw-r--r--llvm/test/Transforms/CodeExtractor/SingleCondition.ll23
-rw-r--r--llvm/test/Transforms/CodeExtractor/X86/InheritTargetAttributes.ll40
-rw-r--r--llvm/test/Transforms/CodeExtractor/X86/lit.local.cfg3
-rw-r--r--llvm/test/Transforms/CodeExtractor/cost.ll64
-rw-r--r--llvm/test/Transforms/CodeExtractor/cost_meta.ll41
-rw-r--r--llvm/test/Transforms/CodeExtractor/extract-assume.ll29
-rw-r--r--llvm/test/Transforms/CodeExtractor/inline_eh.ll52
-rw-r--r--llvm/test/Transforms/CodeExtractor/inline_eh_1.ll56
-rw-r--r--llvm/test/Transforms/CodeExtractor/live_shrink.ll67
-rw-r--r--llvm/test/Transforms/CodeExtractor/live_shrink_gep.ll66
-rw-r--r--llvm/test/Transforms/CodeExtractor/live_shrink_hoist.ll70
-rw-r--r--llvm/test/Transforms/CodeExtractor/live_shrink_multiple.ll66
-rw-r--r--llvm/test/Transforms/CodeExtractor/live_shrink_unsafe.ll94
-rw-r--r--llvm/test/Transforms/CodeExtractor/unreachable-block.ll36
51 files changed, 3353 insertions, 0 deletions
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-13-LoopExtractorCrash.ll b/llvm/test/Transforms/CodeExtractor/2004-03-13-LoopExtractorCrash.ll
new file mode 100644
index 00000000000..3d0339bc2db
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-13-LoopExtractorCrash.ll
@@ -0,0 +1,75 @@
+; RUN: opt < %s -loop-extract -disable-output
+
+define void @solve() {
+entry:
+ br label %loopentry.0
+
+loopentry.0: ; preds = %endif.0, %entry
+ br i1 false, label %no_exit.0, label %loopexit.0
+
+no_exit.0: ; preds = %loopentry.0
+ br i1 false, label %then.0, label %endif.0
+
+then.0: ; preds = %no_exit.0
+ br i1 false, label %shortcirc_done, label %shortcirc_next
+
+shortcirc_next: ; preds = %then.0
+ br label %shortcirc_done
+
+shortcirc_done: ; preds = %shortcirc_next, %then.0
+ br i1 false, label %then.1, label %endif.1
+
+then.1: ; preds = %shortcirc_done
+ br i1 false, label %cond_true, label %cond_false
+
+cond_true: ; preds = %then.1
+ br label %cond_continue
+
+cond_false: ; preds = %then.1
+ br label %cond_continue
+
+cond_continue: ; preds = %cond_false, %cond_true
+ br label %return
+
+after_ret.0: ; No predecessors!
+ br label %endif.1
+
+endif.1: ; preds = %after_ret.0, %shortcirc_done
+ br label %endif.0
+
+endif.0: ; preds = %endif.1, %no_exit.0
+ br label %loopentry.0
+
+loopexit.0: ; preds = %loopentry.0
+ br i1 false, label %then.2, label %endif.2
+
+then.2: ; preds = %loopexit.0
+ br i1 false, label %then.3, label %endif.3
+
+then.3: ; preds = %then.2
+ br label %return
+
+after_ret.1: ; No predecessors!
+ br label %endif.3
+
+endif.3: ; preds = %after_ret.1, %then.2
+ br label %endif.2
+
+endif.2: ; preds = %endif.3, %loopexit.0
+ br label %loopentry.1
+
+loopentry.1: ; preds = %no_exit.1, %endif.2
+ br i1 false, label %no_exit.1, label %loopexit.1
+
+no_exit.1: ; preds = %loopentry.1
+ br label %loopentry.1
+
+loopexit.1: ; preds = %loopentry.1
+ br label %return
+
+after_ret.2: ; No predecessors!
+ br label %return
+
+return: ; preds = %after_ret.2, %loopexit.1, %then.3, %cond_continue
+ ret void
+}
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-14-DominanceProblem.ll b/llvm/test/Transforms/CodeExtractor/2004-03-14-DominanceProblem.ll
new file mode 100644
index 00000000000..2f9c0c7371c
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-14-DominanceProblem.ll
@@ -0,0 +1,33 @@
+; RUN: opt < %s -loop-extract -disable-output
+; This testcase is failing the loop extractor because not all exit blocks
+; are dominated by all of the live-outs.
+
+define i32 @ab(i32 %alpha, i32 %beta) {
+entry:
+ br label %loopentry.1.preheader
+
+loopentry.1.preheader: ; preds = %entry
+ br label %loopentry.1
+
+loopentry.1: ; preds = %no_exit.1, %loopentry.1.preheader
+ br i1 false, label %no_exit.1, label %loopexit.0.loopexit1
+
+no_exit.1: ; preds = %loopentry.1
+ %tmp.53 = load i32, i32* null ; <i32> [#uses=1]
+ br i1 false, label %shortcirc_next.2, label %loopentry.1
+
+shortcirc_next.2: ; preds = %no_exit.1
+ %tmp.563 = call i32 @wins( i32 0, i32 %tmp.53, i32 3 ) ; <i32> [#uses=0]
+ ret i32 0
+
+loopexit.0.loopexit1: ; preds = %loopentry.1
+ br label %loopexit.0
+
+loopexit.0: ; preds = %loopexit.0.loopexit1
+ ret i32 0
+}
+
+declare i32 @wins(i32, i32, i32)
+
+declare i16 @ab_code()
+
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-14-NoSwitchSupport.ll b/llvm/test/Transforms/CodeExtractor/2004-03-14-NoSwitchSupport.ll
new file mode 100644
index 00000000000..7cd72797a67
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-14-NoSwitchSupport.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -loop-extract-single -disable-output
+
+define void @ab() {
+entry:
+ br label %codeReplTail
+
+then.1: ; preds = %codeReplTail
+ br label %loopentry.1
+
+loopentry.1: ; preds = %no_exit.1, %then.1
+ br i1 false, label %no_exit.1, label %loopexit.0.loopexit1
+
+no_exit.1: ; preds = %loopentry.1
+ br label %loopentry.1
+
+loopexit.0.loopexit: ; preds = %codeReplTail
+ ret void
+
+loopexit.0.loopexit1: ; preds = %loopentry.1
+ ret void
+
+codeReplTail: ; preds = %codeReplTail, %entry
+ switch i16 0, label %codeReplTail [
+ i16 0, label %loopexit.0.loopexit
+ i16 1, label %then.1
+ ]
+}
+
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-17-MissedLiveIns.ll b/llvm/test/Transforms/CodeExtractor/2004-03-17-MissedLiveIns.ll
new file mode 100644
index 00000000000..01fe54be29a
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-17-MissedLiveIns.ll
@@ -0,0 +1,47 @@
+; RUN: opt < %s -loop-extract -disable-output
+
+define void @sendMTFValues() {
+entry:
+ br i1 false, label %then.1, label %endif.1
+
+then.1: ; preds = %entry
+ br i1 false, label %loopentry.6.preheader, label %else.0
+
+endif.1: ; preds = %entry
+ ret void
+
+else.0: ; preds = %then.1
+ ret void
+
+loopentry.6.preheader: ; preds = %then.1
+ br i1 false, label %endif.7.preheader, label %loopexit.9
+
+endif.7.preheader: ; preds = %loopentry.6.preheader
+ %tmp.183 = add i32 0, -1 ; <i32> [#uses=1]
+ br label %endif.7
+
+endif.7: ; preds = %loopexit.15, %endif.7.preheader
+ br i1 false, label %loopentry.10, label %loopentry.12
+
+loopentry.10: ; preds = %endif.7
+ br label %loopentry.12
+
+loopentry.12: ; preds = %loopentry.10, %endif.7
+ %ge.2.1 = phi i32 [ 0, %loopentry.10 ], [ %tmp.183, %endif.7 ] ; <i32> [#uses=0]
+ br i1 false, label %loopexit.14, label %no_exit.11
+
+no_exit.11: ; preds = %loopentry.12
+ ret void
+
+loopexit.14: ; preds = %loopentry.12
+ br i1 false, label %loopexit.15, label %no_exit.14
+
+no_exit.14: ; preds = %loopexit.14
+ ret void
+
+loopexit.15: ; preds = %loopexit.14
+ br i1 false, label %endif.7, label %loopexit.9
+
+loopexit.9: ; preds = %loopexit.15, %loopentry.6.preheader
+ ret void
+}
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-17-UpdatePHIsOutsideRegion.ll b/llvm/test/Transforms/CodeExtractor/2004-03-17-UpdatePHIsOutsideRegion.ll
new file mode 100644
index 00000000000..6b306d232e0
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-17-UpdatePHIsOutsideRegion.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -loop-extract -disable-output
+
+define void @maketree() {
+entry:
+ br i1 false, label %no_exit.1, label %loopexit.0
+
+no_exit.1: ; preds = %endif, %expandbox.entry, %entry
+ br i1 false, label %endif, label %expandbox.entry
+
+expandbox.entry: ; preds = %no_exit.1
+ br i1 false, label %loopexit.1, label %no_exit.1
+
+endif: ; preds = %no_exit.1
+ br i1 false, label %loopexit.1, label %no_exit.1
+
+loopexit.1: ; preds = %endif, %expandbox.entry
+ %ic.i.0.0.4 = phi i32 [ 0, %expandbox.entry ], [ 0, %endif ] ; <i32> [#uses=0]
+ ret void
+
+loopexit.0: ; preds = %entry
+ ret void
+}
+
diff --git a/llvm/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll b/llvm/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll
new file mode 100644
index 00000000000..fd9814c545f
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll
@@ -0,0 +1,198 @@
+; RUN: opt < %s -loop-extract -disable-output
+
+declare i32 @_IO_getc()
+
+declare void @__errno_location()
+
+define void @yylex() personality i32 (...)* @__gcc_personality_v0 {
+entry:
+ switch i32 0, label %label.126 [
+ i32 0, label %return
+ i32 61, label %combine
+ i32 33, label %combine
+ i32 94, label %combine
+ i32 37, label %combine
+ i32 47, label %combine
+ i32 42, label %combine
+ i32 62, label %combine
+ i32 60, label %combine
+ i32 58, label %combine
+ i32 124, label %combine
+ i32 38, label %combine
+ i32 45, label %combine
+ i32 43, label %combine
+ i32 34, label %string_constant
+ i32 39, label %char_constant
+ i32 46, label %loopexit.2
+ i32 57, label %loopexit.2
+ i32 56, label %loopexit.2
+ i32 55, label %loopexit.2
+ i32 54, label %loopexit.2
+ i32 53, label %loopexit.2
+ i32 52, label %loopexit.2
+ i32 51, label %loopexit.2
+ i32 50, label %loopexit.2
+ i32 49, label %loopexit.2
+ i32 48, label %loopexit.2
+ i32 95, label %letter
+ i32 122, label %letter
+ i32 121, label %letter
+ i32 120, label %letter
+ i32 119, label %letter
+ i32 118, label %letter
+ i32 117, label %letter
+ i32 116, label %letter
+ i32 115, label %letter
+ i32 114, label %letter
+ i32 113, label %letter
+ i32 112, label %letter
+ i32 111, label %letter
+ i32 110, label %letter
+ i32 109, label %letter
+ i32 108, label %letter
+ i32 107, label %letter
+ i32 106, label %letter
+ i32 105, label %letter
+ i32 104, label %letter
+ i32 103, label %letter
+ i32 102, label %letter
+ i32 101, label %letter
+ i32 100, label %letter
+ i32 99, label %letter
+ i32 98, label %letter
+ i32 97, label %letter
+ i32 90, label %letter
+ i32 89, label %letter
+ i32 88, label %letter
+ i32 87, label %letter
+ i32 86, label %letter
+ i32 85, label %letter
+ i32 84, label %letter
+ i32 83, label %letter
+ i32 82, label %letter
+ i32 81, label %letter
+ i32 80, label %letter
+ i32 79, label %letter
+ i32 78, label %letter
+ i32 77, label %letter
+ i32 75, label %letter
+ i32 74, label %letter
+ i32 73, label %letter
+ i32 72, label %letter
+ i32 71, label %letter
+ i32 70, label %letter
+ i32 69, label %letter
+ i32 68, label %letter
+ i32 67, label %letter
+ i32 66, label %letter
+ i32 65, label %letter
+ i32 64, label %label.13
+ i32 76, label %label.12
+ i32 36, label %label.11
+ i32 -1, label %label.10
+ ]
+
+label.10: ; preds = %entry
+ ret void
+
+label.11: ; preds = %entry
+ ret void
+
+label.12: ; preds = %entry
+ ret void
+
+label.13: ; preds = %entry
+ ret void
+
+letter: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry
+ ret void
+
+loopexit.2: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry
+ switch i32 0, label %shortcirc_next.14 [
+ i32 48, label %then.20
+ i32 46, label %endif.38
+ ]
+
+then.20: ; preds = %loopexit.2
+ switch i32 0, label %else.4 [
+ i32 120, label %then.21
+ i32 88, label %then.21
+ ]
+
+then.21: ; preds = %then.20, %then.20
+ ret void
+
+else.4: ; preds = %then.20
+ ret void
+
+shortcirc_next.14: ; preds = %loopexit.2
+ ret void
+
+endif.38: ; preds = %loopexit.2
+ br i1 false, label %then.40, label %then.39
+
+then.39: ; preds = %endif.38
+ ret void
+
+then.40: ; preds = %endif.38
+ invoke void @__errno_location( )
+ to label %switchexit.2 unwind label %LongJmpBlkPre
+
+loopentry.6: ; preds = %endif.52
+ switch i32 0, label %switchexit.2 [
+ i32 73, label %label.82
+ i32 105, label %label.82
+ i32 76, label %label.80
+ i32 108, label %label.80
+ i32 70, label %label.78
+ i32 102, label %label.78
+ ]
+
+label.78: ; preds = %loopentry.6, %loopentry.6
+ ret void
+
+label.80: ; preds = %loopentry.6, %loopentry.6
+ ret void
+
+label.82: ; preds = %loopentry.6, %loopentry.6
+ %c.0.15.5 = phi i32 [ %tmp.79417, %loopentry.6 ], [ %tmp.79417, %loopentry.6 ] ; <i32> [#uses=0]
+ ret void
+
+switchexit.2: ; preds = %loopentry.6, %then.40
+ br i1 false, label %endif.51, label %loopexit.6
+
+endif.51: ; preds = %switchexit.2
+ br i1 false, label %endif.52, label %then.52
+
+then.52: ; preds = %endif.51
+ ret void
+
+endif.52: ; preds = %endif.51
+ %tmp.79417 = invoke i32 @_IO_getc( )
+ to label %loopentry.6 unwind label %LongJmpBlkPre ; <i32> [#uses=2]
+
+loopexit.6: ; preds = %switchexit.2
+ ret void
+
+char_constant: ; preds = %entry
+ ret void
+
+string_constant: ; preds = %entry
+ ret void
+
+combine: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry
+ ret void
+
+label.126: ; preds = %entry
+ ret void
+
+return: ; preds = %entry
+ ret void
+
+LongJmpBlkPre: ; preds = %endif.52, %then.40
+ %exn = landingpad { i8*, i32 }
+ catch i8* null
+ ret void
+}
+
+declare i32 @__gcc_personality_v0(...)
diff --git a/llvm/test/Transforms/CodeExtractor/2004-08-12-BlockExtractPHI.ll b/llvm/test/Transforms/CodeExtractor/2004-08-12-BlockExtractPHI.ll
new file mode 100644
index 00000000000..9f70bdc71b1
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-08-12-BlockExtractPHI.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s -extract-blocks -disable-output
+
+define void @test1() {
+no_exit.0.i:
+ br i1 false, label %yylex.entry, label %yylex.entry
+
+yylex.entry: ; preds = %no_exit.0.i, %no_exit.0.i
+ %tmp.1027 = phi i32 [ 0, %no_exit.0.i ], [ 0, %no_exit.0.i ] ; <i32> [#uses=0]
+ ret void
+}
+
+define void @test2() {
+no_exit.0.i:
+ switch i32 0, label %yylex.entry [
+ i32 0, label %yylex.entry
+ i32 1, label %foo
+ ]
+
+yylex.entry: ; preds = %no_exit.0.i, %no_exit.0.i
+ %tmp.1027 = phi i32 [ 0, %no_exit.0.i ], [ 0, %no_exit.0.i ] ; <i32> [#uses=0]
+ ret void
+
+foo: ; preds = %no_exit.0.i
+ ret void
+}
+
diff --git a/llvm/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll b/llvm/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll
new file mode 100644
index 00000000000..0a83681a071
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll
@@ -0,0 +1,18 @@
+; RUN: opt < %s -extract-blocks -disable-output
+define i32 @foo() personality i32 (...)* @__gcc_personality_v0 {
+ br label %EB
+
+EB: ; preds = %0
+ %V = invoke i32 @foo( )
+ to label %Cont unwind label %Unw ; <i32> [#uses=1]
+
+Cont: ; preds = %EB
+ ret i32 %V
+
+Unw: ; preds = %EB
+ %exn = landingpad { i8*, i32 }
+ catch i8* null
+ resume { i8*, i32 } %exn
+}
+
+declare i32 @__gcc_personality_v0(...)
diff --git a/llvm/test/Transforms/CodeExtractor/BlockAddressReference.ll b/llvm/test/Transforms/CodeExtractor/BlockAddressReference.ll
new file mode 100644
index 00000000000..91f85bf3ed8
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/BlockAddressReference.ll
@@ -0,0 +1,36 @@
+; RUN: opt < %s -loop-extract -S | FileCheck %s
+
+@label = common local_unnamed_addr global i8* null
+
+; CHECK: define
+; no outlined function
+; CHECK-NOT: define
+define i32 @sterix(i32 %n) {
+entry:
+ %tobool = icmp ne i32 %n, 0
+ ; this blockaddress references a basic block that goes in the extracted loop
+ %cond = select i1 %tobool, i8* blockaddress(@sterix, %for.cond), i8* blockaddress(@sterix, %exit)
+ store i8* %cond, i8** @label
+ %cmp5 = icmp sgt i32 %n, 0
+ br i1 %cmp5, label %for.body, label %exit
+
+for.cond:
+ %mul = shl nsw i32 %s.06, 1
+ %exitcond = icmp eq i32 %inc, %n
+ br i1 %exitcond, label %exit.loopexit, label %for.body
+
+for.body:
+ %i.07 = phi i32 [ %inc, %for.cond ], [ 0, %entry ]
+ %s.06 = phi i32 [ %mul, %for.cond ], [ 1, %entry ]
+ %inc = add nuw nsw i32 %i.07, 1
+ br label %for.cond
+
+exit.loopexit:
+ %phitmp = icmp ne i32 %s.06, 2
+ %phitmp8 = zext i1 %phitmp to i32
+ br label %exit
+
+exit:
+ %s.1 = phi i32 [ 1, %entry ], [ %phitmp8, %exit.loopexit ]
+ ret i32 %s.1
+}
diff --git a/llvm/test/Transforms/CodeExtractor/BlockAddressSelfReference.ll b/llvm/test/Transforms/CodeExtractor/BlockAddressSelfReference.ll
new file mode 100644
index 00000000000..7d5a827a358
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/BlockAddressSelfReference.ll
@@ -0,0 +1,50 @@
+; RUN: opt < %s -loop-extract -S | FileCheck %s
+
+@choum.addr = internal unnamed_addr constant [3 x i8*] [i8* blockaddress(@choum, %bb10), i8* blockaddress(@choum, %bb14), i8* blockaddress(@choum, %bb18)]
+
+; CHECK: define
+; no outlined function
+; CHECK-NOT: define
+
+define void @choum(i32 %arg, i32* nocapture %arg1, i32 %arg2) {
+bb:
+ %tmp = icmp sgt i32 %arg, 0
+ br i1 %tmp, label %bb3, label %bb24
+
+bb3: ; preds = %bb
+ %tmp4 = sext i32 %arg2 to i64
+ %tmp5 = getelementptr inbounds [3 x i8*], [3 x i8*]* @choum.addr, i64 0, i64 %tmp4
+ %tmp6 = load i8*, i8** %tmp5
+ %tmp7 = zext i32 %arg to i64
+ br label %bb8
+
+bb8: ; preds = %bb18, %bb3
+ %tmp9 = phi i64 [ 0, %bb3 ], [ %tmp22, %bb18 ]
+ indirectbr i8* %tmp6, [label %bb10, label %bb14, label %bb18]
+
+bb10: ; preds = %bb8
+ %tmp11 = getelementptr inbounds i32, i32* %arg1, i64 %tmp9
+ %tmp12 = load i32, i32* %tmp11
+ %tmp13 = add nsw i32 %tmp12, 1
+ store i32 %tmp13, i32* %tmp11
+ br label %bb14
+
+bb14: ; preds = %bb10, %bb8
+ %tmp15 = getelementptr inbounds i32, i32* %arg1, i64 %tmp9
+ %tmp16 = load i32, i32* %tmp15
+ %tmp17 = shl nsw i32 %tmp16, 1
+ store i32 %tmp17, i32* %tmp15
+ br label %bb18
+
+bb18: ; preds = %bb14, %bb8
+ %tmp19 = getelementptr inbounds i32, i32* %arg1, i64 %tmp9
+ %tmp20 = load i32, i32* %tmp19
+ %tmp21 = add nsw i32 %tmp20, -3
+ store i32 %tmp21, i32* %tmp19
+ %tmp22 = add nuw nsw i64 %tmp9, 1
+ %tmp23 = icmp eq i64 %tmp22, %tmp7
+ br i1 %tmp23, label %bb24, label %bb8
+
+bb24: ; preds = %bb18, %bb
+ ret void
+}
diff --git a/llvm/test/Transforms/CodeExtractor/ExtractedFnEntryCount.ll b/llvm/test/Transforms/CodeExtractor/ExtractedFnEntryCount.ll
new file mode 100644
index 00000000000..55c44e1e832
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/ExtractedFnEntryCount.ll
@@ -0,0 +1,33 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+; This test checks to make sure that the CodeExtractor
+; properly sets the entry count for the function that is
+; extracted based on the root block being extracted and also
+; takes into consideration if the block has edges coming from
+; a block that is also being extracted.
+
+define i32 @inlinedFunc(i1 %cond) !prof !1 {
+entry:
+ br i1 %cond, label %if.then, label %return, !prof !2
+if.then:
+ br i1 %cond, label %if.then, label %return, !prof !3
+return: ; preds = %entry
+ ret i32 0
+}
+
+
+define internal i32 @dummyCaller(i1 %cond) !prof !1 {
+entry:
+ %val = call i32 @inlinedFunc(i1 %cond)
+ ret i32 %val
+}
+
+; CHECK: @inlinedFunc.1.if.then(i1 %cond) !prof [[COUNT1:![0-9]+]]
+
+
+!llvm.module.flags = !{!0}
+; CHECK: [[COUNT1]] = !{!"function_entry_count", i64 250}
+!0 = !{i32 1, !"MaxFunctionCount", i32 1000}
+!1 = !{!"function_entry_count", i64 1000}
+!2 = !{!"branch_weights", i32 250, i32 750}
+!3 = !{!"branch_weights", i32 125, i32 125}
diff --git a/llvm/test/Transforms/CodeExtractor/MultipleExitBranchProb.ll b/llvm/test/Transforms/CodeExtractor/MultipleExitBranchProb.ll
new file mode 100644
index 00000000000..8e362080dc4
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/MultipleExitBranchProb.ll
@@ -0,0 +1,34 @@
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+; This test checks to make sure that CodeExtractor updates
+; the exit branch probabilities for multiple exit blocks.
+
+define i32 @inlinedFunc(i1 %cond) !prof !1 {
+entry:
+ br i1 %cond, label %if.then, label %return, !prof !2
+if.then:
+ br i1 %cond, label %return, label %return.2, !prof !3
+return.2:
+ ret i32 10
+return: ; preds = %entry
+ ret i32 0
+}
+
+
+define internal i32 @dummyCaller(i1 %cond) !prof !1 {
+entry:
+%val = call i32 @inlinedFunc(i1 %cond)
+ret i32 %val
+
+; CHECK-LABEL: @dummyCaller
+; CHECK: call
+; CHECK-NEXT: br i1 {{.*}}return.i{{.*}}return.2{{.*}}!prof [[COUNT1:![0-9]+]]
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"MaxFunctionCount", i32 10000}
+!1 = !{!"function_entry_count", i64 10000}
+!2 = !{!"branch_weights", i32 5, i32 5}
+!3 = !{!"branch_weights", i32 4, i32 1}
+
+; CHECK: [[COUNT1]] = !{!"branch_weights", i32 31, i32 8}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca.ll
new file mode 100644
index 00000000000..48db0b61a31
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca.ll
@@ -0,0 +1,68 @@
+
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+ ; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+%"class.base" = type { %"struct.base"* }
+%"struct.base" = type opaque
+
+@g = external local_unnamed_addr global i32, align 4
+
+; Function Attrs: nounwind uwtable
+define i32 @callee_sinkable_bitcast(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL:define{{.*}}@callee_sinkable_bitcast.{{[0-9]}}
+; CHECK: alloca
+; CHECK-NEXT: bitcast
+; CHECK: call void @llvm.lifetime
+bb:
+ %tmp = alloca %"class.base", align 4
+ %tmp1 = bitcast %"class.base"* %tmp to i8*
+ %tmp2 = load i32, i32* @g, align 4, !tbaa !2
+ %tmp3 = add nsw i32 %tmp2, 1
+ %tmp4 = icmp slt i32 %arg, 0
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) #2
+ %tmp11 = bitcast %"class.base"* %tmp to i32*
+ store i32 %tmp3, i32* %tmp11, align 4, !tbaa !2
+ store i32 %tmp3, i32* @g, align 4, !tbaa !2
+ call void @bar(i32* nonnull %tmp11) #2
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) #2
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb
+ %tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ]
+ ret i32 %tmp7
+}
+
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+declare void @bar(i32*) local_unnamed_addr #2
+declare void @bar2(i32*, i32*) local_unnamed_addr #1
+
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 @callee_sinkable_bitcast(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind uwtable}
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca2.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca2.ll
new file mode 100644
index 00000000000..4ca418389e5
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca2.ll
@@ -0,0 +1,65 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+%"class.base" = type { %"struct.base"* }
+%"struct.base" = type opaque
+
+@g = external local_unnamed_addr global i32, align 4
+
+define i32 @callee_no_bitcast(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL:define{{.*}}@callee_no_bitcast.{{[0-9]}}
+; CHECK: alloca
+; CHECK: call void @llvm.lifetime
+bb:
+ %tmp = alloca i8, align 4
+ %tmp2 = load i32, i32* @g, align 4, !tbaa !2
+ %tmp3 = add nsw i32 %tmp2, 1
+ %tmp4 = icmp slt i32 %arg, 0
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp) #2
+ store i32 %tmp3, i32* @g, align 4, !tbaa !2
+ %tmp11 = bitcast i8 * %tmp to i32*
+ call void @bar(i32* nonnull %tmp11) #2
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp) #2
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb
+ %tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ]
+ ret i32 %tmp7
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+declare void @bar(i32*) local_unnamed_addr #2
+declare void @bar2(i32*, i32*) local_unnamed_addr #1
+
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 @callee_no_bitcast(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind uwtable}
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+
+
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca4.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca4.ll
new file mode 100644
index 00000000000..5112135b166
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca4.ll
@@ -0,0 +1,70 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+%"class.base" = type { %"struct.base"* }
+%"struct.base" = type opaque
+
+@g = external local_unnamed_addr global i32, align 4
+
+; CHECK-LABEL: define{{.*}}@caller(
+; CHECK: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %tmp.i)
+; CHECK-NEXT: call void @callee_unknown_use1.{{.*}}(i8* %tmp.i
+
+define i32 @callee_unknown_use1(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL:define{{.*}}@callee_unknown_use1.{{[0-9]}}
+; CHECK-NOT: alloca
+bb:
+ %tmp = alloca i8, align 4
+ %tmp2 = load i32, i32* @g, align 4, !tbaa !2
+ %tmp3 = add nsw i32 %tmp2, 1
+ %tmp4 = icmp slt i32 %arg, 0
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp) #2
+ store i32 %tmp3, i32* @g, align 4, !tbaa !2
+ %tmp11 = bitcast i8* %tmp to i32*
+ call void @bar(i32* nonnull %tmp11) #2
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp) #2
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb
+ %tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ]
+ %tmp1 = bitcast i8* %tmp to i32*
+ ret i32 %tmp7
+}
+
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+declare void @bar(i32*) local_unnamed_addr #2
+declare void @bar2(i32*, i32*) local_unnamed_addr #1
+
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 @callee_unknown_use1(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind uwtable}
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+
+
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca5.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca5.ll
new file mode 100644
index 00000000000..0bde58fbccd
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAlloca5.ll
@@ -0,0 +1,66 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+
+%"class.base" = type { %"struct.base"* }
+%"struct.base" = type opaque
+
+@g = external local_unnamed_addr global i32, align 4
+
+define i32 @callee_unknown_use2(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL:define{{.*}}@callee_unknown_use2.{{[0-9]}}
+; CHECK-NOT: alloca
+bb:
+ %tmp = alloca i32, align 4
+ %tmp1 = bitcast i32* %tmp to i8*
+ %tmp2 = load i32, i32* @g, align 4, !tbaa !2
+ %tmp3 = add nsw i32 %tmp2, 1
+ %tmp4 = icmp slt i32 %arg, 0
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) #2
+ store i32 %tmp3, i32* %tmp, align 4, !tbaa !2
+ store i32 %tmp3, i32* @g, align 4, !tbaa !2
+ call void @bar(i32* nonnull %tmp) #2
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) #2
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb
+ %tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ]
+ %tmp10 = bitcast i8* %tmp1 to i32*
+ ret i32 %tmp7
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
+
+declare void @bar(i32*) local_unnamed_addr #2
+declare void @bar2(i32*, i32*) local_unnamed_addr #1
+
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define i32 @caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 @callee_unknown_use2(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind uwtable}
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+
+
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAnd.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAnd.ll
new file mode 100644
index 00000000000..6d555b740e5
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAnd.ll
@@ -0,0 +1,56 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S | FileCheck %s
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT %s
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb5
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @channels() #2
+ %tmp3 = icmp slt i32 %tmp2, %arg
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb1
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb1, %bb
+ %tmp6 = phi i32 [ 0, %bb4 ], [ 1, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp6
+}
+
+declare i32 @channels(...) local_unnamed_addr #1
+
+declare void @foo(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call void @bar.1.
+; LIMIT-LABEL: @dummy_caller
+; LIMIT: br i1
+; LIMIT-NOT: br
+; LIMIT: call void @bar.1.
+ %tmp = tail call i32 @bar(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind }
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAndOr.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAndOr.ll
new file mode 100644
index 00000000000..9da9ed4437e
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAndOr.ll
@@ -0,0 +1,63 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S | FileCheck %s
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=3 -S | FileCheck --check-prefix=LIMIT %s
+; RUN: opt < %s -passes=partial-inliner -max-num-inline-blocks=3 -S | FileCheck --check-prefix=LIMIT %s
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb4
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @n() #2
+ %tmp3 = icmp slt i32 %tmp2, %arg
+ br i1 %tmp3, label %bb7, label %bb4
+
+bb4: ; preds = %bb1, %bb
+ %tmp5 = tail call i32 (...) @m() #2
+ %tmp6 = icmp slt i32 %tmp5, %arg
+ br i1 %tmp6, label %bb7, label %bb8
+
+bb7: ; preds = %bb4, %bb1
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ br label %bb8
+
+bb8: ; preds = %bb7, %bb4
+ %tmp9 = phi i32 [ 0, %bb7 ], [ 1, %bb4 ]
+ ret i32 %tmp9
+}
+
+declare i32 @n(...) local_unnamed_addr #1
+
+declare i32 @m(...) local_unnamed_addr #1
+
+declare void @foo(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call void @bar.1.
+; LIMIT-LABEL: @dummy_caller
+; LIMIT-NOT: br i1
+; LIMIT: call i32 @bar
+ %tmp = tail call i32 @bar(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind }
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
new file mode 100644
index 00000000000..18c934bc6a1
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
@@ -0,0 +1,85 @@
+; RUN: opt < %s -S -partial-inliner -skip-partial-inlining-cost-analysis=true | FileCheck %s
+
+
+define i32 @callee_most(i32 %v) unnamed_addr #0 #1 {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10
+ br label %if.end
+
+if.end:
+ %v2 = phi i32 [ %v, %entry ], [ %sub, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+define i32 @callee_noinline(i32 %v) optnone noinline {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10
+ br label %if.end
+
+if.end:
+ %v2 = phi i32 [ %v, %entry ], [ %sub, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+define i32 @callee_writeonly(i32 %v) writeonly {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10
+ br label %if.end
+
+if.end:
+ %v2 = phi i32 [ %v, %entry ], [ %sub, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+; CHECK-LABEL: @caller
+; CHECK: call void @callee_most.2.if.then(i32 %v
+; CHECK: call i32 @callee_noinline(i32 %v)
+; CHECK: call void @callee_writeonly.1.if.then(i32 %v
+define i32 @caller(i32 %v) {
+entry:
+ %c1 = call i32 @callee_most(i32 %v)
+ %c2 = call i32 @callee_noinline(i32 %v)
+ %c3 = call i32 @callee_writeonly(i32 %v)
+ ret i32 %c3
+}
+
+; CHECK: define internal void @callee_writeonly.1.if.then(i32 %v, i32* %sub.out) {
+; CHECK: define internal void @callee_most.2.if.then(i32 %v, i32* %sub.out) [[FN_ATTRS:#[0-9]+]]
+
+; attributes to preserve
+attributes #0 = {
+ inlinehint minsize noduplicate noimplicitfloat norecurse noredzone nounwind
+ nonlazybind optsize safestack sanitize_address sanitize_hwaddress sanitize_memory
+ sanitize_thread ssp sspreq sspstrong strictfp uwtable "foo"="bar"
+ "patchable-function"="prologue-short-redirect" "probe-stack"="_foo_guard" "stack-probe-size"="4096" }
+
+; CHECK: attributes [[FN_ATTRS]] = { inlinehint minsize noduplicate noimplicitfloat norecurse noredzone nounwind nonlazybind optsize safestack sanitize_address sanitize_hwaddress sanitize_memory sanitize_thread ssp sspreq sspstrong strictfp uwtable "foo"="bar" "patchable-function"="prologue-short-redirect" "probe-stack"="_foo_guard" "stack-probe-size"="4096" }
+
+; attributes to drop
+attributes #1 = {
+ alignstack=16 convergent inaccessiblememonly inaccessiblemem_or_argmemonly naked
+ noreturn readonly argmemonly returns_twice speculatable "thunk"
+}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineCallRef.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineCallRef.ll
new file mode 100644
index 00000000000..4465a0fd485
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineCallRef.ll
@@ -0,0 +1,56 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S | FileCheck %s
+
+
+; Function Attrs: nounwind
+declare void @foo(...) local_unnamed_addr #0
+
+; Function Attrs: noinline
+define i32 @caller(i32 (i32)* nocapture %arg, i32 (i32)* nocapture %arg1, i32 %arg2) local_unnamed_addr #1 {
+bb:
+ %tmp = tail call i32 %arg(i32 %arg2) #0
+ %tmp3 = tail call i32 %arg1(i32 %arg2) #0
+ %tmp4 = add nsw i32 %tmp3, %tmp
+ ret i32 %tmp4
+}
+
+; Function Attrs: nounwind
+define i32 @bar(i32 %arg) #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb2
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ tail call void (...) @foo() #0
+ br label %bb2
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3
+}
+
+; Function Attrs: nounwind
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; check that caller is not wrongly inlined by partial inliner
+; CHECK: call i32 @caller
+; CHECK-NOT: call .* @bar
+ %tmp = tail call i32 @caller(i32 (i32)* nonnull @bar, i32 (i32)* nonnull @bar, i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 5.0.0 (trunk 300897) (llvm/trunk 300947)"}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineDebug.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineDebug.ll
new file mode 100644
index 00000000000..c68a070a41d
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineDebug.ll
@@ -0,0 +1,106 @@
+; RUN: opt < %s -S -partial-inliner -skip-partial-inlining-cost-analysis=true | FileCheck %s
+
+; CHECK-LABEL: @callee
+; CHECK: %mul = mul nsw i32 %v, 10, !dbg ![[DBG1:[0-9]+]]
+define i32 @callee(i32 %v) !dbg !16 {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %mul = mul nsw i32 %v, 10, !dbg !17
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10, !dbg !23
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ %v2 = phi i32 [ %v, %entry ], [ %mul, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+; CHECK-LABEL: @caller
+; CHECK: codeRepl.i:
+; CHECK-NOT: br label
+; CHECK: call void @callee.2.if.then(i32 %v, i32* %mul.loc.i), !dbg ![[DBG2:[0-9]+]]
+define i32 @caller(i32 %v) !dbg !8 {
+entry:
+ %call = call i32 @callee(i32 %v), !dbg !14
+ ret i32 %call
+}
+
+
+; CHECK-LABEL: @callee2
+; CHECK: %sub = sub i32 %v, 10, !dbg ![[DBG3:[0-9]+]]
+define i32 @callee2(i32 %v) !dbg !18 {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10, !dbg !20
+ br label %if.end
+
+if.end:
+ %v2 = phi i32 [ %v, %entry ], [ %sub, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+; CHECK-LABEL: @caller2
+; CHECK: codeRepl.i:
+; CHECK-NOT: br label
+; CHECK: call void @callee2.1.if.then(i32 %v, i32* %sub.loc.i), !dbg ![[DBG4:[0-9]+]]
+define i32 @caller2(i32 %v) !dbg !21 {
+entry:
+ %call = call i32 @callee2(i32 %v), !dbg !22
+ ret i32 %call
+}
+
+; CHECK-LABEL: define internal void @callee2.1.if.then
+; CHECK: br label %if.then, !dbg ![[DBG5:[0-9]+]]
+
+; CHECK-LABEL: define internal void @callee.2.if.then
+; CHECK: br label %if.then, !dbg ![[DBG6:[0-9]+]]
+
+; CHECK: ![[DBG1]] = !DILocation(line: 10, column: 7,
+; CHECK: ![[DBG2]] = !DILocation(line: 10, column: 7,
+; CHECK: ![[DBG3]] = !DILocation(line: 110, column: 17,
+; CHECK: ![[DBG4]] = !DILocation(line: 110, column: 17,
+; CHECK: ![[DBG5]] = !DILocation(line: 110, column: 17,
+; CHECK: ![[DBG6]] = !DILocation(line: 10, column: 7,
+
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 (trunk 177881)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "test.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{i32 1, !"min_enum_size", i32 4}
+!7 = !{!"clang version 6.0.0"}
+!8 = distinct !DISubprogram(name: "caller", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11}
+!11 = !DIBasicType(name: "int", size: 19, encoding: DW_ATE_signed)
+!12 = !{!13}
+!13 = !DILocalVariable(name: "v", arg: 1, scope: !8, file: !1, line: 3, type: !11)
+!14 = !DILocation(line: 5, column: 10, scope: !8)
+!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 9, column: 7)
+!16 = distinct !DISubprogram(name: "callee", scope: !1, file: !1, line: 8, type: !9, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!17 = !DILocation(line: 10, column: 7, scope: !15)
+!18 = distinct !DISubprogram(name: "callee2", scope: !1, file: !1, line: 8, type: !9, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!19 = distinct !DILexicalBlock(scope: !18, file: !1, line: 100, column: 1)
+!20 = !DILocation(line: 110, column: 17, scope: !19)
+!21 = distinct !DISubprogram(name: "caller2", scope: !1, file: !1, line: 8, type: !9, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!22 = !DILocation(line: 110, column: 17, scope: !21)
+!23 = !DILocation(line: 15, column: 7, scope: !15)
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineEntryPHICost.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineEntryPHICost.ll
new file mode 100644
index 00000000000..a8c2d62710d
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineEntryPHICost.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S | FileCheck %s
+
+; Check that we do not overcompute the outlined region cost, where the PHIs in
+; the outlined region entry (BB4) are moved outside the region by CodeExtractor.
+
+define i32 @bar(i32 %arg) {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb2
+
+bb1:
+ br i1 undef, label %bb4, label %bb2
+
+bb2: ; preds = %bb, %bb1
+ br i1 undef, label %bb4, label %bb5
+
+bb4: ; preds = %bb1, %bb2
+ %xx1 = phi i32 [ 1, %bb1 ], [ 9, %bb2 ]
+ %xx2 = phi i32 [ 1, %bb1 ], [ 9, %bb2 ]
+ %xx3 = phi i32 [ 1, %bb1 ], [ 9, %bb2 ]
+ tail call void (...) @foo() #2
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb2
+ %tmp6 = phi i32 [ 1, %bb2 ], [ 9, %bb4 ]
+ ret i32 %tmp6
+}
+
+declare void @foo(...)
+
+define i32 @dummy_caller(i32 %arg) {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call void @bar.1.
+ %tmp = tail call i32 @bar(i32 %arg)
+ ret i32 %tmp
+}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineEntryUpdate.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineEntryUpdate.ll
new file mode 100644
index 00000000000..0efc8299dab
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineEntryUpdate.ll
@@ -0,0 +1,41 @@
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -passes=partial-inliner -S | FileCheck %s
+
+define i32 @Func(i1 %cond, i32* align 4 %align.val) !prof !1 {
+; CHECK: @Func({{.*}}) !prof [[REMAINCOUNT:![0-9]+]]
+entry:
+ br i1 %cond, label %if.then, label %return
+if.then:
+ ; Dummy store to have more than 0 uses
+ store i32 10, i32* %align.val, align 4
+ br label %return
+return: ; preds = %entry
+ ret i32 0
+}
+
+define internal i32 @Caller1(i1 %cond, i32* align 2 %align.val) !prof !3{
+entry:
+; CHECK-LABEL: @Caller1
+; CHECK: br
+; CHECK: call void @Func.1.
+; CHECK: br
+; CHECK: call void @Func.1.
+ %val = call i32 @Func(i1 %cond, i32* %align.val)
+ %val2 = call i32 @Func(i1 %cond, i32* %align.val)
+ ret i32 %val
+}
+
+define internal i32 @Caller2(i1 %cond, i32* align 2 %align.val) !prof !2{
+entry:
+; CHECK-LABEL: @Caller2
+; CHECK: br
+; CHECK: call void @Func.1.
+ %val = call i32 @Func(i1 %cond, i32* %align.val)
+ ret i32 %val
+}
+
+; CHECK: [[REMAINCOUNT]] = !{!"function_entry_count", i64 150}
+!1 = !{!"function_entry_count", i64 200}
+!2 = !{!"function_entry_count", i64 10}
+!3 = !{!"function_entry_count", i64 20}
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineHighCost.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineHighCost.ll
new file mode 100644
index 00000000000..e43a94dc6c3
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineHighCost.ll
@@ -0,0 +1,107 @@
+; The outlined region has high frequency and the outlining
+; call sequence is expensive (input, output, multiple exit etc)
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=2 -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -max-num-inline-blocks=2 -S | FileCheck %s
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -max-num-inline-blocks=2 -S | FileCheck --check-prefix=NOCOST %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -max-num-inline-blocks=2 -S | FileCheck --check-prefix=NOCOST %s
+
+
+; Function Attrs: nounwind
+define i32 @bar_hot_outline_region(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb16, !prof !1
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @foo() #0
+ %tmp3 = tail call i32 (...) @foo() #0
+ %tmp4 = tail call i32 (...) @foo() #0
+ %tmp5 = tail call i32 (...) @foo() #0
+ %tmp6 = tail call i32 (...) @foo() #0
+ %tmp7 = tail call i32 (...) @foo() #0
+ %tmp8 = add nsw i32 %arg, 1
+ %tmp9 = tail call i32 @goo(i32 %tmp8) #0
+ %tmp10 = tail call i32 (...) @foo() #0
+ %tmp11 = icmp eq i32 %tmp10, 0
+ br i1 %tmp11, label %bb12, label %bb16
+
+bb12: ; preds = %bb1
+ %tmp13 = tail call i32 (...) @foo() #0
+ %tmp14 = icmp eq i32 %tmp13, 0
+ %tmp15 = select i1 %tmp14, i32 0, i32 3
+ br label %bb16
+
+bb16: ; preds = %bb12, %bb1, %bb
+ %tmp17 = phi i32 [ 2, %bb1 ], [ %tmp15, %bb12 ], [ 0, %bb ]
+ ret i32 %tmp17
+}
+
+define i32 @bar_cold_outline_region(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb16, !prof !2
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @foo() #0
+ %tmp3 = tail call i32 (...) @foo() #0
+ %tmp4 = tail call i32 (...) @foo() #0
+ %tmp5 = tail call i32 (...) @foo() #0
+ %tmp6 = tail call i32 (...) @foo() #0
+ %tmp7 = tail call i32 (...) @foo() #0
+ %tmp8 = add nsw i32 %arg, 1
+ %tmp9 = tail call i32 @goo(i32 %tmp8) #0
+ %tmp10 = tail call i32 (...) @foo() #0
+ %tmp11 = icmp eq i32 %tmp10, 0
+ br i1 %tmp11, label %bb12, label %bb16
+
+bb12: ; preds = %bb1
+ %tmp13 = tail call i32 (...) @foo() #0
+ %tmp14 = icmp eq i32 %tmp13, 0
+ %tmp15 = select i1 %tmp14, i32 0, i32 3
+ br label %bb16
+
+bb16: ; preds = %bb12, %bb1, %bb
+ %tmp17 = phi i32 [ 2, %bb1 ], [ %tmp15, %bb12 ], [ 0, %bb ]
+ ret i32 %tmp17
+}
+
+; Function Attrs: nounwind
+declare i32 @foo(...) local_unnamed_addr #0
+
+; Function Attrs: nounwind
+declare i32 @goo(i32) local_unnamed_addr #0
+
+; Function Attrs: nounwind
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK-NOT: br i1
+; CHECK-NOT: call{{.*}}bar_hot_outline_region.
+; NOCOST-LABEL: @dummy_caller
+; NOCOST: br i1
+; NOCOST: call{{.*}}bar_hot_outline_region.
+
+ %tmp = tail call i32 @bar_hot_outline_region(i32 %arg)
+ ret i32 %tmp
+}
+
+define i32 @dummy_caller2(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller2
+; CHECK: br i1
+; CHECK: call{{.*}}bar_cold_outline_region.
+; NOCOST-LABEL: @dummy_caller2
+; NOCOST: br i1
+; NOCOST: call{{.*}}bar_cold_outline_region.
+
+ %tmp = tail call i32 @bar_cold_outline_region(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 5.0.0 (trunk 301898)"}
+!1 = !{!"branch_weights", i32 2000, i32 1}
+!2 = !{!"branch_weights", i32 1, i32 100}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll
new file mode 100644
index 00000000000..2e0fbf6073e
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineInvokeProducesOutVal.ll
@@ -0,0 +1,51 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+
+; Function Attrs: nounwind uwtable
+define dso_local i8* @bar(i32 %arg) local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb1, label %bb5
+
+bb1: ; preds = %bb
+ %call26 = invoke i8* @invoke_callee() #2
+ to label %cont unwind label %lpad
+lpad: ; preds = %if.end
+ %0 = landingpad { i8*, i32 }
+ cleanup
+ resume { i8*, i32 } undef
+
+cont:
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb1, %bb
+ %retval = phi i8* [ %call26, %cont ], [ undef, %bb]
+ ret i8* %retval
+}
+
+; CHECK-LABEL: @dummy_caller
+; CHECK-LABEL: bb:
+; CHECK-NEXT: [[CALL26LOC:%.*]] = alloca i8*
+; CHECK-LABEL: codeRepl.i:
+; CHECK-NEXT: %lt.cast.i = bitcast i8** [[CALL26LOC]] to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* %lt.cast.i)
+; CHECK-NEXT: call void @bar.1.bb1(i8** [[CALL26LOC]])
+; CHECK-NEXT: %call26.reload.i = load i8*, i8** [[CALL26LOC]]
+; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 -1, i8* %lt.cast.i)
+define i8* @dummy_caller(i32 %arg) {
+bb:
+ %tmp = tail call i8* @bar(i32 %arg)
+ ret i8* %tmp
+}
+
+; CHECK-LABEL: define internal void @bar.1.bb1
+; CHECK-LABEL: bb1:
+; CHECK-NEXT: %call26 = invoke i8* @invoke_callee()
+; CHECK-NEXT: to label %cont unwind label %lpad
+; CHECK-LABEL: cont:
+; CHECK-NEXT: store i8* %call26, i8** %call26.out
+; CHECK-NEXT: br label %bb5.exitStub
+
+; Function Attrs: nobuiltin
+declare dso_local noalias nonnull i8* @invoke_callee() local_unnamed_addr #1
+
+declare dso_local i32 @__gxx_personality_v0(...)
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineLiveAcross.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineLiveAcross.ll
new file mode 100644
index 00000000000..1e1a1b062d4
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineLiveAcross.ll
@@ -0,0 +1,61 @@
+; RUN: opt -S -partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+define i32 @test(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 (...) @bar() #1
+ %tmp1 = icmp slt i32 %arg, 0
+ br i1 %tmp1, label %bb6, label %bb2
+
+bb2: ; preds = %bb
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ %tmp3 = tail call i32 (...) @bar() #1
+ %tmp4 = icmp eq i32 %tmp3, 10
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb2
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb2, %bb
+ %tmp7 = phi i32 [ %tmp, %bb5 ], [ 0, %bb ], [ %tmp, %bb2 ]
+ ret i32 %tmp7
+}
+
+declare i32 @bar(...) local_unnamed_addr #1
+
+declare void @foo(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL: @dummy_caller
+; CHECK: codeRepl.i:
+; CHECK: call void @test.1.bb2()
+; CHECK-NOT: load
+; CHECK br
+
+bb:
+ %tmp = tail call i32 @test(i32 %arg)
+ ret i32 %tmp
+}
+
+; CHECK-LABEL: define internal void @test.1.bb2()
+; CHECK: .exitStub:
+; CHECK-NOT: store i32 %tmp7, i32* %tmp7.out
+; CHECK: ret
+
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind uwtable }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineNoInline.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineNoInline.ll
new file mode 100644
index 00000000000..6c0b83298d2
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineNoInline.ll
@@ -0,0 +1,45 @@
+; RUN: opt < %s -partial-inliner -S -stats -pass-remarks=partial-inlining 2>&1 | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S -stats -pass-remarks=partial-inlining 2>&1 | FileCheck %s
+
+@stat = external global i32, align 4
+
+define i32 @inline_fail(i32 %count, ...) {
+entry:
+ %vargs = alloca i8*, align 8
+ %vargs1 = bitcast i8** %vargs to i8*
+ call void @llvm.va_start(i8* %vargs1)
+ %stat1 = load i32, i32* @stat, align 4
+ %cmp = icmp slt i32 %stat1, 0
+ br i1 %cmp, label %bb2, label %bb1
+
+bb1: ; preds = %entry
+ %vg1 = add nsw i32 %stat1, 1
+ store i32 %vg1, i32* @stat, align 4
+ %va1 = va_arg i8** %vargs, i32
+ call void @foo(i32 %count, i32 %va1) #2
+ br label %bb2
+
+bb2: ; preds = %bb1, %entry
+ %res = phi i32 [ 1, %bb1 ], [ 0, %entry ]
+ call void @llvm.va_end(i8* %vargs1)
+ ret i32 %res
+}
+
+define i32 @caller(i32 %arg) {
+bb:
+ %res = tail call i32 (i32, ...) @inline_fail(i32 %arg, i32 %arg)
+ ret i32 %res
+}
+
+declare void @foo(i32, i32)
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_end(i8*)
+
+; Check that no remarks have been emitted, inline_fail has not been partial
+; inlined, no code has been extracted and the partial-inlining counter
+; has not been incremented.
+
+; CHECK-NOT: remark
+; CHECK: tail call i32 (i32, ...) @inline_fail(i32 %arg, i32 %arg)
+; CHECK-NOT: inline_fail.1_bb1
+; CHECK-NOT: partial-inlining
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineNoLiveOut.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineNoLiveOut.ll
new file mode 100644
index 00000000000..d41492f8ffd
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineNoLiveOut.ll
@@ -0,0 +1,62 @@
+; RUN: opt -S -partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+define i32 @test(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = tail call i32 (...) @bar() #1
+ %tmp1 = icmp slt i32 %arg, 0
+ br i1 %tmp1, label %bb6, label %bb2
+
+bb2: ; preds = %bb
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ %tmp3 = tail call i32 (...) @bar() #1
+ %tmp4 = icmp eq i32 %tmp3, 10
+ br i1 %tmp4, label %bb6, label %bb5
+
+bb5: ; preds = %bb2
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ br label %bb6
+
+bb6: ; preds = %bb5, %bb2, %bb
+ %tmp7 = phi i32 [ 1, %bb5 ], [ 0, %bb ], [ 1, %bb2 ]
+ ret i32 %tmp7
+}
+
+; Function Attrs: nounwind uwtable
+declare i32 @bar(...) local_unnamed_addr #0
+
+; Function Attrs: nounwind uwtable
+declare void @foo(...) local_unnamed_addr #0
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+; CHECK-LABEL: @dummy_caller
+; CHECK: codeRepl.i:
+; CHECK: call void @test.1.bb2()
+; CHECK-NOT: load
+; CHECK br
+bb:
+ %tmp = tail call i32 @test(i32 %arg)
+ ret i32 %tmp
+}
+
+; CHECK-LABEL: define internal void @test.1.bb2()
+; CHECK: .exitStub:
+; CHECK-NOT: store i32 %tmp7, i32* %tmp7.out
+; CHECK: ret
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 303574)"}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineNotViable.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineNotViable.ll
new file mode 100644
index 00000000000..010d677e5dc
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineNotViable.ll
@@ -0,0 +1,63 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+;
+
+define i32 @callee_indr_branch(i32 %v) {
+entry:
+ %cmp = icmp sgt i32 %v, 2000
+ %addr = select i1 %cmp, i8* blockaddress(@callee_indr_branch, %if.then), i8* blockaddress(@callee_indr_branch, %if.end)
+ indirectbr i8* %addr, [ label %if.then, label %if.end]
+
+if.then: ; preds = %entry
+ %mul = mul nsw i32 %v, 10
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ %v2 = phi i32 [ %v, %entry ], [ %mul, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+declare void @use_fp(i8 *)
+declare void @llvm.localescape(...)
+declare i8* @llvm.frameaddress(i32)
+declare i8* @llvm.localrecover(i8*, i8*, i32)
+
+
+
+define i32 @callee_frameescape(i32 %v) {
+entry:
+ %a = alloca i32
+ call void (...) @llvm.localescape(i32* %a)
+ %cmp = icmp sgt i32 %v, 2000
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %mul = mul nsw i32 %v, 10
+ br label %if.then2
+
+if.then2:
+ %sub = sub i32 %v, 10
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ %v2 = phi i32 [ %v, %entry ], [ %mul, %if.then2 ]
+ %add = add nsw i32 %v2, 200
+ ret i32 %add
+}
+
+
+; CHECK-LABEL: @caller
+; CHECK: %r1 = call i32 @callee_indr_branch(i32 %v)
+; CHECK-NEXT: %r2 = call i32 @callee_frameescape(i32 %v)
+define i32 @caller(i32 %v) {
+entry:
+ %r1 = call i32 @callee_indr_branch(i32 %v)
+ %r2 = call i32 @callee_frameescape(i32 %v)
+ %res = add i32 %r1, %r2
+ ret i32 %res
+}
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineORECrash.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineORECrash.ll
new file mode 100644
index 00000000000..c7f14945cd3
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineORECrash.ll
@@ -0,0 +1,170 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -inline-threshold=0 -disable-output
+
+target datalayout = "e-m:e-i64:64-n32:64"
+target triple = "powerpc64le-unknown-linux-gnu"
+
+%0 = type { i32 (...)**, %1, %1, %3, %3, %3, i8, float, %4*, %5*, %5*, i32, i32, i32, i32, float, float, float, i8*, i32, float, float, float, i8, [7 x i8] }
+%1 = type { %2, %3 }
+%2 = type { [3 x %3] }
+%3 = type { [4 x float] }
+%4 = type <{ i8*, i16, i16, [4 x i8], i8*, i32, %3, %3, [4 x i8] }>
+%5 = type { i32 (...)**, i32, i8* }
+%6 = type <{ %7, [4 x i8], %19*, %20*, %30, %35, %3, float, i8, i8, i8, i8, %37, i32, [4 x i8] }>
+%7 = type <{ %8, [7 x i8], void (%16*, float)*, void (%16*, float)*, i8*, %17 }>
+%8 = type <{ i32 (...)**, %9, %11*, %12, %13*, %14*, %15*, i8 }>
+%9 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %0**, i8, [7 x i8] }>
+%11 = type { i32 (...)** }
+%12 = type { float, i32, i32, float, i8, %15*, i8, i8, i8, float, i8, float, %13* }
+%13 = type opaque
+%14 = type { i32 (...)** }
+%15 = type { i32 (...)** }
+%16 = type <{ %8, [7 x i8], void (%16*, float)*, void (%16*, float)*, i8*, %17, [4 x i8] }>
+%17 = type { %18 }
+%18 = type { float, float, float, float, float, i32, float, float, float, float, float, i32, float, float, float, i32, i32 }
+%19 = type { i32 (...)** }
+%20 = type <{ i32 (...)**, %21, %25, %9, i8, [7 x i8] }>
+%21 = type { %22 }
+%22 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %24*, i8, [7 x i8] }>
+%24 = type { i32, i32 }
+%25 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %27**, i8, [7 x i8] }>
+%27 = type { i32, [4 x i8], [4 x %29], i8*, i8*, i32, float, float, i32 }
+%29 = type <{ %3, %3, %3, %3, %3, float, float, float, i32, i32, i32, i32, [4 x i8], i8*, float, i8, [3 x i8], float, float, i32, %3, %3, [4 x i8] }>
+%30 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %32**, i8, [7 x i8] }>
+%32 = type { i32 (...)**, i32, i32, i32, i8, %33*, %33*, float, float, %3, %3, %3 }
+%33 = type <{ %0, %2, %3, %3, float, %3, %3, %3, %3, %3, %3, %3, float, float, i8, [3 x i8], float, float, float, float, float, float, %34*, %30, i32, i32, i32, [4 x i8] }>
+%34 = type { i32 (...)** }
+%35 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %33**, i8, [7 x i8] }>
+%37 = type <{ i8, [3 x i8], i32, i32, [4 x i8], %39**, i8, [7 x i8] }>
+%39 = type { i32 (...)** }
+%40 = type <{ i32 (...)**, %9, %11*, %12, %13*, %14*, %15*, i8, [7 x i8] }>
+
+@gDisableDeactivation = external local_unnamed_addr global i8, align 1
+@0 = external dso_local unnamed_addr constant [29 x i8], align 1
+@1 = external dso_local unnamed_addr constant [14 x i8], align 1
+@2 = external dso_local unnamed_addr constant [22 x i8], align 1
+@gDeactivationTime = external local_unnamed_addr global float, align 4
+
+declare void @_ZN15CProfileManager12Stop_ProfileEv() local_unnamed_addr
+
+declare void @_ZN15CProfileManager13Start_ProfileEPKc(i8*) local_unnamed_addr
+
+declare void @_ZN17btCollisionObject18setActivationStateEi(%0*, i32 signext) local_unnamed_addr
+
+declare hidden void @__clang_call_terminate(i8*) local_unnamed_addr
+
+declare i32 @__gxx_personality_v0(...)
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #0
+
+define void @_ZN23btDiscreteDynamicsWorld28internalSingleStepSimulationEf(%6*, float) unnamed_addr align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) !prof !27 {
+ invoke void null(%6* nonnull %0, float %1)
+ to label %5 unwind label %3
+
+; <label>:3: ; preds = %2
+ %4 = landingpad { i8*, i32 }
+ cleanup
+ br label %16
+
+; <label>:5: ; preds = %2
+ %6 = invoke %15* null(%40* null)
+ to label %11 unwind label %13
+
+; <label>:7: ; preds = %5
+ invoke void null(%40* null)
+ to label %8 unwind label %13
+
+; <label>:8: ; preds = %7
+ invoke void null(%6* nonnull %0)
+ to label %9 unwind label %13
+
+; <label>:9: ; preds = %8
+ invoke void null(%6* nonnull %0, %17* nonnull dereferenceable(68) null)
+ to label %10 unwind label %13
+
+; <label>:10: ; preds = %9
+ invoke void null(%6* nonnull %0, float %1)
+ to label %11 unwind label %13
+
+; <label>:11:
+ invoke void @_ZN23btDiscreteDynamicsWorld21updateActivationStateEf(%6* nonnull %0, float %1)
+ to label %12 unwind label %13
+
+; <label>:12:
+ ret void
+
+; <label>:13:
+ %14 = landingpad { i8*, i32 }
+ cleanup
+ %15 = extractvalue { i8*, i32 } %14, 0
+ br label %16
+
+
+; <label>:16:
+ call void @_ZN15CProfileManager12Stop_ProfileEv()
+ resume { i8*, i32 } zeroinitializer
+}
+
+define void @_ZN23btDiscreteDynamicsWorld21updateActivationStateEf(%6* nocapture readonly, float) local_unnamed_addr align 2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) !prof !27 {
+ %3 = icmp sgt i32 0, 0
+ br i1 %3, label %4, label %5, !prof !29
+
+; <label>:4: ; preds = %2
+ br i1 false, label %5, label %6, !prof !30
+
+; <label>:5: ; preds = %7, %4, %2
+ ret void
+
+; <label>:6: ; preds = %4
+ invoke void @_ZN17btCollisionObject18setActivationStateEi(%0* nonnull null, i32 signext 0)
+ to label %7 unwind label %8
+
+; <label>:7: ; preds = %6
+ invoke void @_ZN17btCollisionObject18setActivationStateEi(%0* nonnull null, i32 signext 1)
+ to label %5 unwind label %8
+
+; <label>:8: ; preds = %7, %6
+ %9 = landingpad { i8*, i32 }
+ cleanup
+ resume { i8*, i32 } %9
+}
+
+; Function Attrs: noreturn nounwind
+declare void @llvm.trap() #1
+
+attributes #0 = { argmemonly nounwind }
+attributes #1 = { noreturn nounwind }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"ProfileSummary", !1}
+!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
+!2 = !{!"ProfileFormat", !"InstrProf"}
+!3 = !{!"TotalCount", i64 6540578580}
+!4 = !{!"MaxCount", i64 629805108}
+!5 = !{!"MaxInternalCount", i64 40670372}
+!6 = !{!"MaxFunctionCount", i64 629805108}
+!7 = !{!"NumCounts", i64 8554}
+!8 = !{!"NumFunctions", i64 3836}
+!9 = !{!"DetailedSummary", !10}
+!10 = !{!11, !12, !13, !14, !15, !16, !16, !17, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26}
+!11 = !{i32 10000, i64 629805108, i32 1}
+!12 = !{i32 100000, i64 366853677, i32 2}
+!13 = !{i32 200000, i64 196816893, i32 4}
+!14 = !{i32 300000, i64 192575561, i32 7}
+!15 = !{i32 400000, i64 130688163, i32 11}
+!16 = !{i32 500000, i64 74857169, i32 19}
+!17 = !{i32 600000, i64 48184151, i32 30}
+!18 = !{i32 700000, i64 21298588, i32 49}
+!19 = !{i32 800000, i64 10721033, i32 90}
+!20 = !{i32 900000, i64 3301634, i32 202}
+!21 = !{i32 950000, i64 1454952, i32 362}
+!22 = !{i32 990000, i64 343872, i32 675}
+!23 = !{i32 999000, i64 46009, i32 1112}
+!24 = !{i32 999900, i64 6067, i32 1435}
+!25 = !{i32 999990, i64 700, i32 1721}
+!26 = !{i32 999999, i64 72, i32 1955}
+!27 = !{!"function_entry_count", i64 700}
+!28 = !{!"branch_weights", i32 701, i32 1}
+!29 = !{!"branch_weights", i32 954001, i32 701}
+!30 = !{!"branch_weights", i32 1, i32 954001}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll
new file mode 100644
index 00000000000..5f2a0ff475d
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineOptRemark.ll
@@ -0,0 +1,138 @@
+; RUN: opt -S -partial-inliner -pass-remarks=partial-inlining -disable-output < %s 2>&1 | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -pass-remarks=partial-inlining -disable-output < %s 2>&1 | FileCheck %s
+; RUN: opt -S -partial-inliner -pass-remarks=partial-inlining -disable-output -max-partial-inlining=1 < %s 2>&1 | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -pass-remarks=partial-inlining -disable-output -max-partial-inlining=1 < %s 2>&1 | FileCheck %s
+
+; RUN: opt -S -partial-inliner -pass-remarks=partial-inlining -disable-partial-inlining < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+; RUN: opt -S -passes=partial-inliner -pass-remarks=partial-inlining --disable-partial-inlining < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+; RUN: opt -S -partial-inliner -pass-remarks=partial-inlining -max-partial-inlining=0 < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+; RUN: opt -S -passes=partial-inliner -pass-remarks=partial-inlining -max-partial-inlining=0 < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+; RUN: opt -S -partial-inliner -pass-remarks=partial-inlining -inline-threshold=0 < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+; RUN: opt -S -passes=partial-inliner -pass-remarks=partial-inlining -inline-threshold=0 < %s 2>&1 | FileCheck --check-prefix=LIMIT %s
+
+define i32 @bar(i32 %arg) local_unnamed_addr #0 !dbg !5 {
+bb:
+ %tmp = icmp slt i32 %arg, 0, !dbg !7
+ br i1 %tmp, label %bb1, label %bb2, !dbg !8
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0, !dbg !9
+ tail call void (...) @foo() #0, !dbg !10
+ tail call void (...) @foo() #0, !dbg !11
+ tail call void (...) @foo() #0, !dbg !12
+ tail call void (...) @foo() #0, !dbg !13
+ tail call void (...) @foo() #0, !dbg !14
+ tail call void (...) @foo() #0, !dbg !15
+ tail call void (...) @foo() #0, !dbg !16
+ tail call void (...) @foo() #0, !dbg !17
+ br label %bb2, !dbg !18
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3, !dbg !19
+}
+
+define i32 @bar_noinline(i32 %arg) local_unnamed_addr #1 !dbg !23 {
+bb:
+ %tmp = icmp slt i32 %arg, 0, !dbg !24
+ br i1 %tmp, label %bb1, label %bb2, !dbg !24
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0, !dbg !24
+ tail call void (...) @foo() #0, !dbg !24
+ tail call void (...) @foo() #0, !dbg !24
+ br label %bb2, !dbg !24
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3, !dbg !24
+}
+
+define i32 @bar_alwaysinline(i32 %arg) local_unnamed_addr #2 !dbg !25 {
+bb:
+ %tmp = icmp slt i32 %arg, 0, !dbg !26
+ br i1 %tmp, label %bb1, label %bb2, !dbg !26
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0, !dbg !26
+ tail call void (...) @foo() #0, !dbg !26
+ tail call void (...) @foo() #0, !dbg !26
+ br label %bb2, !dbg !26
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3, !dbg !26
+}
+
+define i32 @bar_cold(i32 %arg) local_unnamed_addr #3 !dbg !27 {
+bb:
+ %tmp = icmp slt i32 %arg, 0, !dbg !28
+ br i1 %tmp, label %bb1, label %bb2, !dbg !28
+
+bb1: ; preds = %bb
+ tail call void (...) @foo() #0, !dbg !28
+ tail call void (...) @foo() #0, !dbg !28
+ tail call void (...) @foo() #0, !dbg !28
+ br label %bb2, !dbg !28
+
+bb2: ; preds = %bb1, %bb
+ %tmp3 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp3, !dbg !28
+}
+
+; Function Attrs: nounwind
+declare void @foo(...) local_unnamed_addr #0
+
+; Function Attrs: nounwind
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 !dbg !20 {
+bb:
+; CHECK:remark{{.*}}bar partially inlined into dummy_caller
+; CHECK-NOT:remark{{.*}}bar_noinline partially inlined into dummy_caller
+; CHECK-NOT:remark{{.*}}bar_alwaysinline partially inlined into dummy_caller
+; CHECK-NOT:remark{{.*}}bar_cold partially inlined into dummy_caller
+; LIMIT-NOT:remark{{.*}}bar partially inlined into dummy_caller
+ %tmp = tail call i32 @bar(i32 %arg), !dbg !21
+ %tmp2 = tail call i32 @bar_noinline(i32 %arg), !dbg !21
+ %tmp3 = tail call i32 @bar_alwaysinline(i32 %arg), !dbg !21
+ %tmp4 = tail call i32 @bar_cold(i32 %arg), !dbg !21
+ ret i32 %tmp, !dbg !22
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline nounwind }
+attributes #2 = { alwaysinline nounwind }
+attributes #3 = { cold nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3}
+!llvm.ident = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "t.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{!"clang "}
+!5 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!6 = !DISubroutineType(types: !2)
+!7 = !DILocation(line: 4, column: 14, scope: !5)
+!8 = !DILocation(line: 4, column: 6, scope: !5)
+!9 = !DILocation(line: 5, column: 5, scope: !5)
+!10 = !DILocation(line: 6, column: 5, scope: !5)
+!11 = !DILocation(line: 7, column: 5, scope: !5)
+!12 = !DILocation(line: 8, column: 5, scope: !5)
+!13 = !DILocation(line: 9, column: 5, scope: !5)
+!14 = !DILocation(line: 10, column: 5, scope: !5)
+!15 = !DILocation(line: 11, column: 5, scope: !5)
+!16 = !DILocation(line: 12, column: 5, scope: !5)
+!17 = !DILocation(line: 13, column: 5, scope: !5)
+!18 = !DILocation(line: 14, column: 5, scope: !5)
+!19 = !DILocation(line: 17, column: 1, scope: !5)
+!20 = distinct !DISubprogram(name: "dummy_caller", scope: !1, file: !1, line: 19, type: !6, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!21 = !DILocation(line: 21, column: 11, scope: !20)
+!22 = !DILocation(line: 21, column: 4, scope: !20)
+!23 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!24 = !DILocation(line: 4, column: 6, scope: !23)
+!25 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!26 = !DILocation(line: 4, column: 6, scope: !25)
+!27 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !2)
+!28 = !DILocation(line: 4, column: 6, scope: !27)
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineOr.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineOr.ll
new file mode 100644
index 00000000000..cbf7a47de9b
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineOr.ll
@@ -0,0 +1,97 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT %s
+; RUN: opt < %s -passes=partial-inliner -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT %s
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb4, label %bb1
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @channels() #1
+ %tmp3 = icmp slt i32 %tmp2, %arg
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb1, %bb
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb1
+ %.0 = phi i32 [ 0, %bb4 ], [ 1, %bb1 ]
+ ret i32 %.0
+}
+
+declare i32 @channels(...) local_unnamed_addr
+
+declare void @foo(...) local_unnamed_addr
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call void @bar.2.
+; LIMIT-LABEL: @dummy_caller
+; LIMIT-NOT: br
+; LIMIT: call i32 @bar(
+ %tmp = tail call i32 @bar(i32 %arg)
+ ret i32 %tmp
+}
+
+define i32 @bar_multi_ret(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb4, label %bb1
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @channels() #1
+ %tmp3 = icmp slt i32 %tmp2, %arg
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb1, %bb
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ tail call void (...) @foo() #1
+ %tmp4 = icmp slt i32 %arg, 10
+ br i1 %tmp4, label %bb6, label %bb5
+bb6:
+ tail call void (...) @foo() #1
+ %tmp5 = icmp slt i32 %arg, 3
+ br i1 %tmp5, label %bb7, label %bb5
+bb7:
+ tail call void (...) @foo() #1
+ br label %bb8
+bb8:
+ ret i32 0
+
+bb5: ; preds = %bb4, %bb1
+ %.0 = phi i32 [ 0, %bb4 ], [ 1, %bb1 ], [0, %bb6]
+ ret i32 %.0
+}
+
+define i32 @dummy_caller2(i32 %arg) local_unnamed_addr #0 {
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call {{.*}} @bar_multi_ret.1.
+ %tmp = tail call i32 @bar_multi_ret(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind uwtable }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+
+!0 = !{!"clang version 5.0.0 (trunk 300576)"}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineOrAnd.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineOrAnd.ll
new file mode 100644
index 00000000000..09d0e2503ea
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineOrAnd.ll
@@ -0,0 +1,71 @@
+; RUN: opt < %s -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S | FileCheck %s
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=3 -skip-partial-inlining-cost-analysis -S | FileCheck --check-prefix=LIMIT3 %s
+; RUN: opt < %s -passes=partial-inliner -max-num-inline-blocks=3 -skip-partial-inlining-cost-analysis -S | FileCheck --check-prefix=LIMIT3 %s
+; RUN: opt < %s -partial-inliner -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT2 %s
+; RUN: opt < %s -passes=partial-inliner -max-num-inline-blocks=2 -S | FileCheck --check-prefix=LIMIT2 %s
+
+
+; Function Attrs: nounwind uwtable
+define i32 @bar(i32 %arg) local_unnamed_addr #0 {
+bb:
+ %tmp = icmp slt i32 %arg, 0
+ br i1 %tmp, label %bb4, label %bb1
+
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 (...) @n() #2
+ %tmp3 = icmp slt i32 %tmp2, %arg
+ br i1 %tmp3, label %bb4, label %bb8
+
+bb4: ; preds = %bb1, %bb
+ %tmp5 = tail call i32 (...) @m() #2
+ %tmp6 = icmp sgt i32 %tmp5, %arg
+ br i1 %tmp6, label %bb7, label %bb8
+
+bb7: ; preds = %bb4
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ tail call void (...) @foo() #2
+ br label %bb8
+
+bb8: ; preds = %bb7, %bb4, %bb1
+ %tmp9 = phi i32 [ 0, %bb7 ], [ 1, %bb4 ], [ 1, %bb1 ]
+ ret i32 %tmp9
+}
+
+declare i32 @n(...) local_unnamed_addr #1
+
+declare i32 @m(...) local_unnamed_addr #1
+
+declare void @foo(...) local_unnamed_addr #1
+
+; Function Attrs: nounwind uwtable
+define i32 @dummy_caller(i32 %arg) local_unnamed_addr #0 {
+bb:
+; CHECK-LABEL: @dummy_caller
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: br i1
+; CHECK: call void @bar.1.
+; LIMIT3-LABEL: @dummy_caller
+; LIMIT3: br i1
+; LIMIT3: br i1
+; LIMIT3-NOT: br i1
+; LIMIT3: call void @bar.1.
+; LIMIT2-LABEL: @dummy_caller
+; LIMIT2-NOT: br i1
+; LIMIT2: call i32 @bar(
+ %tmp = tail call i32 @bar(i32 %arg)
+ ret i32 %tmp
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind }
+
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll b/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
new file mode 100644
index 00000000000..5d187abb68a
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlinePGOMultiRegion.ll
@@ -0,0 +1,169 @@
+; RUN: opt -S -partial-inliner -min-block-execution=1 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -min-block-execution=1 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; Require a dummy block (if.then.b) as successor to if.then due to PI requirement
+; of region containing more than one BB.
+define signext i32 @bar(i32 signext %value, i32 signext %ub) #0 !prof !30 {
+entry:
+ %value.addr = alloca i32, align 4
+ %ub.addr = alloca i32, align 4
+ %sum = alloca i32, align 4
+ %i = alloca i32, align 4
+ store i32 %value, i32* %value.addr, align 4
+ store i32 %ub, i32* %ub.addr, align 4
+ store i32 0, i32* %sum, align 4
+ store i32 0, i32* %i, align 4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %0 = load i32, i32* %i, align 4
+ %1 = load i32, i32* %ub.addr, align 4
+ %cmp = icmp slt i32 %0, %1
+ br i1 %cmp, label %for.body, label %for.cond2, !prof !31
+
+for.body: ; preds = %for.cond
+ %2 = load i32, i32* %value.addr, align 4
+ %rem = srem i32 %2, 20
+ %cmp1 = icmp eq i32 %rem, 0
+ br i1 %cmp1, label %if.then, label %if.else, !prof !32
+
+if.then: ; preds = %for.body
+ %3 = load i32, i32* %value.addr, align 4
+ %4 = load i32, i32* %i, align 4
+ %mul = mul nsw i32 %4, 5
+ %add = add nsw i32 %3, %mul
+ %5 = load i32, i32* %sum, align 4
+ %add2 = add nsw i32 %5, %add
+ store i32 %add2, i32* %sum, align 4
+ br label %if.then.b
+
+if.then.b: ; preds = %if.then
+ br label %if.end
+
+if.else: ; preds = %for.body
+ %6 = load i32, i32* %value.addr, align 4
+ %7 = load i32, i32* %i, align 4
+ %sub = sub nsw i32 %6, %7
+ %8 = load i32, i32* %sum, align 4
+ %add3 = add nsw i32 %8, %sub
+ store i32 %add3, i32* %sum, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %9 = load i32, i32* %i, align 4
+ %inc = add nsw i32 %9, 1
+ store i32 %inc, i32* %i, align 4
+ br label %for.cond
+
+for.cond2: ; preds = %for.cond
+ %10 = load i32, i32* %i, align 4
+ %11 = load i32, i32* %ub.addr, align 4
+ %cmp2 = icmp slt i32 %10, %11
+ br i1 %cmp2, label %for.body2, label %for.end, !prof !31
+
+for.body2: ; preds = %for.cond2
+ %12 = load i32, i32* %value.addr, align 4
+ %rem2 = srem i32 %12, 20
+ %cmp3 = icmp eq i32 %rem2, 0
+ br i1 %cmp3, label %if.then2, label %if.else2, !prof !32
+
+if.then2: ; preds = %for.body2
+ %13 = load i32, i32* %value.addr, align 4
+ %14 = load i32, i32* %i, align 4
+ %mul2 = mul nsw i32 %14, 5
+ %add4 = add nsw i32 %13, %mul2
+ %15 = load i32, i32* %sum, align 4
+ %add5 = add nsw i32 %15, %add4
+ store i32 %add5, i32* %sum, align 4
+ br label %if.then2.b
+
+if.then2.b: ; preds = %if.then2
+ br label %if.end2
+
+if.else2: ; preds = %for.body2
+ %16 = load i32, i32* %value.addr, align 4
+ %17 = load i32, i32* %i, align 4
+ %sub2 = sub nsw i32 %16, %17
+ %18 = load i32, i32* %sum, align 4
+ %add6 = add nsw i32 %18, %sub2
+ store i32 %add6, i32* %sum, align 4
+ br label %if.end2
+
+if.end2: ; preds = %if.else2, %if.then2
+ br label %for.inc2
+
+for.inc2: ; preds = %if.end2
+ %19 = load i32, i32* %i, align 4
+ %inc2 = add nsw i32 %19, 1
+ store i32 %inc2, i32* %i, align 4
+ br label %for.cond2
+
+for.end: ; preds = %for.cond2
+ %20 = load i32, i32* %sum, align 4
+ ret i32 %20
+}
+
+define signext i32 @foo(i32 signext %value, i32 signext %ub) #0 !prof !30 {
+; CHECK-LABEL: @foo
+; CHECK-NOT: call signext i32 @bar
+; CHECK: codeRepl1.i:
+; CHECK: call void @bar.1.if.then
+; CHECK: codeRepl.i:
+; CHECK: call void @bar.1.if.then2
+entry:
+ %value.addr = alloca i32, align 4
+ %ub.addr = alloca i32, align 4
+ store i32 %value, i32* %value.addr, align 4
+ store i32 %ub, i32* %ub.addr, align 4
+ %0 = load i32, i32* %value.addr, align 4
+ %1 = load i32, i32* %ub.addr, align 4
+ %call = call signext i32 @bar(i32 signext %0, i32 signext %1)
+ ret i32 %call
+}
+
+; CHECK-LABEL: define internal void @bar.1.if.then2
+; CHECK: .exitStub:
+; CHECK: ret void
+
+; CHECK-LABEL: define internal void @bar.1.if.then
+; CHECK: .exitStub:
+; CHECK: ret void
+
+!llvm.module.flags = !{!0, !1, !2}
+!llvm.ident = !{!29}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"PIC Level", i32 2}
+!2 = !{i32 1, !"ProfileSummary", !3}
+!3 = !{!4, !5, !6, !7, !8, !9, !10, !11}
+!4 = !{!"ProfileFormat", !"InstrProf"}
+!5 = !{!"TotalCount", i64 103}
+!6 = !{!"MaxCount", i64 100}
+!7 = !{!"MaxInternalCount", i64 1}
+!8 = !{!"MaxFunctionCount", i64 100}
+!9 = !{!"NumCounts", i64 5}
+!10 = !{!"NumFunctions", i64 3}
+!11 = !{!"DetailedSummary", !12}
+!12 = !{!13, !14, !15, !16, !17, !18, !18, !19, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28}
+!13 = !{i32 10000, i64 100, i32 1}
+!14 = !{i32 100000, i64 100, i32 1}
+!15 = !{i32 200000, i64 100, i32 1}
+!16 = !{i32 300000, i64 100, i32 1}
+!17 = !{i32 400000, i64 100, i32 1}
+!18 = !{i32 500000, i64 100, i32 1}
+!19 = !{i32 600000, i64 100, i32 1}
+!20 = !{i32 700000, i64 100, i32 1}
+!21 = !{i32 800000, i64 100, i32 1}
+!22 = !{i32 900000, i64 100, i32 1}
+!23 = !{i32 950000, i64 100, i32 1}
+!24 = !{i32 990000, i64 1, i32 4}
+!25 = !{i32 999000, i64 1, i32 4}
+!26 = !{i32 999900, i64 1, i32 4}
+!27 = !{i32 999990, i64 1, i32 4}
+!28 = !{i32 999999, i64 1, i32 4}
+!29 = !{!"clang version 6.0.0 (123456)"}
+!30 = !{!"function_entry_count", i64 2}
+!31 = !{!"branch_weights", i32 100, i32 1}
+!32 = !{!"branch_weights", i32 0, i32 100}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlinePGORegion.ll b/llvm/test/Transforms/CodeExtractor/PartialInlinePGORegion.ll
new file mode 100644
index 00000000000..4aa70624315
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlinePGORegion.ll
@@ -0,0 +1,120 @@
+; RUN: opt -S -partial-inliner -min-block-execution=1 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -min-block-execution=1 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; Require a dummy block (if.then.b) as successor to if.then due to PI requirement
+; of region containing more than one BB.
+define signext i32 @bar(i32 signext %value, i32 signext %ub) #0 !prof !30 {
+entry:
+ %value.addr = alloca i32, align 4
+ %ub.addr = alloca i32, align 4
+ %sum = alloca i32, align 4
+ %i = alloca i32, align 4
+ store i32 %value, i32* %value.addr, align 4
+ store i32 %ub, i32* %ub.addr, align 4
+ store i32 0, i32* %sum, align 4
+ store i32 0, i32* %i, align 4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %0 = load i32, i32* %i, align 4
+ %1 = load i32, i32* %ub.addr, align 4
+ %cmp = icmp slt i32 %0, %1
+ br i1 %cmp, label %for.body, label %for.end, !prof !31
+
+for.body: ; preds = %for.cond
+ %2 = load i32, i32* %value.addr, align 4
+ %rem = srem i32 %2, 20
+ %cmp1 = icmp eq i32 %rem, 0
+ br i1 %cmp1, label %if.then, label %if.else, !prof !32
+
+if.then: ; preds = %for.body
+ %3 = load i32, i32* %value.addr, align 4
+ %4 = load i32, i32* %i, align 4
+ %mul = mul nsw i32 %4, 5
+ %add = add nsw i32 %3, %mul
+ %5 = load i32, i32* %sum, align 4
+ %add2 = add nsw i32 %5, %add
+ store i32 %add2, i32* %sum, align 4
+ br label %if.then.b
+
+if.then.b: ; preds = %if.then
+ br label %if.end
+
+if.else: ; preds = %for.body
+ %6 = load i32, i32* %value.addr, align 4
+ %7 = load i32, i32* %i, align 4
+ %sub = sub nsw i32 %6, %7
+ %8 = load i32, i32* %sum, align 4
+ %add3 = add nsw i32 %8, %sub
+ store i32 %add3, i32* %sum, align 4
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ br label %for.inc
+
+for.inc: ; preds = %if.end
+ %9 = load i32, i32* %i, align 4
+ %inc = add nsw i32 %9, 1
+ store i32 %inc, i32* %i, align 4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ %10 = load i32, i32* %sum, align 4
+ ret i32 %10
+}
+
+define signext i32 @foo(i32 signext %value, i32 signext %ub) #0 !prof !30 {
+; CHECK-LABEL: @foo
+; CHECK: codeRepl.i:
+; CHECK-NOT: call signext i32 @bar
+; CHECK: call void @bar.1.if.then
+entry:
+ %value.addr = alloca i32, align 4
+ %ub.addr = alloca i32, align 4
+ store i32 %value, i32* %value.addr, align 4
+ store i32 %ub, i32* %ub.addr, align 4
+ %0 = load i32, i32* %value.addr, align 4
+ %1 = load i32, i32* %ub.addr, align 4
+ %call = call signext i32 @bar(i32 signext %0, i32 signext %1)
+ ret i32 %call
+}
+
+; CHECK-LABEL: define internal void @bar.1.if.then
+; CHECK: .exitStub:
+; CHECK: ret void
+
+!llvm.module.flags = !{!0, !1, !2}
+!llvm.ident = !{!29}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"PIC Level", i32 2}
+!2 = !{i32 1, !"ProfileSummary", !3}
+!3 = !{!4, !5, !6, !7, !8, !9, !10, !11}
+!4 = !{!"ProfileFormat", !"InstrProf"}
+!5 = !{!"TotalCount", i64 103}
+!6 = !{!"MaxCount", i64 100}
+!7 = !{!"MaxInternalCount", i64 1}
+!8 = !{!"MaxFunctionCount", i64 100}
+!9 = !{!"NumCounts", i64 5}
+!10 = !{!"NumFunctions", i64 3}
+!11 = !{!"DetailedSummary", !12}
+!12 = !{!13, !14, !15, !16, !17, !18, !18, !19, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28}
+!13 = !{i32 10000, i64 100, i32 1}
+!14 = !{i32 100000, i64 100, i32 1}
+!15 = !{i32 200000, i64 100, i32 1}
+!16 = !{i32 300000, i64 100, i32 1}
+!17 = !{i32 400000, i64 100, i32 1}
+!18 = !{i32 500000, i64 100, i32 1}
+!19 = !{i32 600000, i64 100, i32 1}
+!20 = !{i32 700000, i64 100, i32 1}
+!21 = !{i32 800000, i64 100, i32 1}
+!22 = !{i32 900000, i64 100, i32 1}
+!23 = !{i32 950000, i64 100, i32 1}
+!24 = !{i32 990000, i64 1, i32 4}
+!25 = !{i32 999000, i64 1, i32 4}
+!26 = !{i32 999900, i64 1, i32 4}
+!27 = !{i32 999990, i64 1, i32 4}
+!28 = !{i32 999999, i64 1, i32 4}
+!29 = !{!"clang version 6.0.0 (123456)"}
+!30 = !{!"function_entry_count", i64 2}
+!31 = !{!"branch_weights", i32 100, i32 1}
+!32 = !{!"branch_weights", i32 0, i32 100}
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineVarArg.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineVarArg.ll
new file mode 100644
index 00000000000..8582f5e18f8
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineVarArg.ll
@@ -0,0 +1,107 @@
+; RUN: opt < %s -partial-inliner -S -skip-partial-inlining-cost-analysis | FileCheck %s
+; RUN: opt < %s -passes=partial-inliner -S -skip-partial-inlining-cost-analysis | FileCheck %s
+
+@stat = external global i32, align 4
+
+define i32 @vararg(i32 %count, ...) {
+entry:
+ %vargs = alloca i8*, align 8
+ %stat1 = load i32, i32* @stat, align 4
+ %cmp = icmp slt i32 %stat1, 0
+ br i1 %cmp, label %bb2, label %bb1
+
+bb1: ; preds = %entry
+ %vg1 = add nsw i32 %stat1, 1
+ store i32 %vg1, i32* @stat, align 4
+ %vargs1 = bitcast i8** %vargs to i8*
+ call void @llvm.va_start(i8* %vargs1)
+ %va1 = va_arg i8** %vargs, i32
+ call void @foo(i32 %count, i32 %va1) #2
+ call void @llvm.va_end(i8* %vargs1)
+ br label %bb2
+
+bb2: ; preds = %bb1, %entry
+ %res = phi i32 [ 1, %bb1 ], [ 0, %entry ]
+ ret i32 %res
+}
+
+declare void @foo(i32, i32)
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_end(i8*)
+
+define i32 @caller1(i32 %arg) {
+bb:
+ %tmp = tail call i32 (i32, ...) @vararg(i32 %arg)
+ ret i32 %tmp
+}
+; CHECK-LABEL: @caller1
+; CHECK: codeRepl.i:
+; CHECK-NEXT: call void (i32, i8**, i32, ...) @vararg.3.bb1(i32 %stat1.i, i8** %vargs.i, i32 %arg)
+
+define i32 @caller2(i32 %arg, float %arg2) {
+bb:
+ %tmp = tail call i32 (i32, ...) @vararg(i32 %arg, i32 10, float %arg2)
+ ret i32 %tmp
+}
+
+; CHECK-LABEL: @caller2
+; CHECK: codeRepl.i:
+; CHECK-NEXT: call void (i32, i8**, i32, ...) @vararg.3.bb1(i32 %stat1.i, i8** %vargs.i, i32 %arg, i32 10, float %arg2)
+
+; Test case to check that we do not extract a vararg function, if va_end is in
+; a block that is not outlined.
+define i32 @vararg_not_legal(i32 %count, ...) {
+entry:
+ %vargs = alloca i8*, align 8
+ %vargs0 = bitcast i8** %vargs to i8*
+ %stat1 = load i32, i32* @stat, align 4
+ %cmp = icmp slt i32 %stat1, 0
+ br i1 %cmp, label %bb2, label %bb1
+
+bb1: ; preds = %entry
+ %vg1 = add nsw i32 %stat1, 1
+ store i32 %vg1, i32* @stat, align 4
+ %vargs1 = bitcast i8** %vargs to i8*
+ call void @llvm.va_start(i8* %vargs1)
+ %va1 = va_arg i8** %vargs, i32
+ call void @foo(i32 %count, i32 %va1)
+ br label %bb2
+
+bb2: ; preds = %bb1, %entry
+ %res = phi i32 [ 1, %bb1 ], [ 0, %entry ]
+ %ptr = phi i8* [ %vargs1, %bb1 ], [ %vargs0, %entry]
+ call void @llvm.va_end(i8* %ptr)
+ ret i32 %res
+}
+
+; CHECK-LABEL: @caller3
+; CHECK: tail call i32 (i32, ...) @vararg_not_legal(i32 %arg, i32 %arg)
+define i32 @caller3(i32 %arg) {
+bb:
+ %res = tail call i32 (i32, ...) @vararg_not_legal(i32 %arg, i32 %arg)
+ ret i32 %res
+}
+
+declare i32* @err(i32*)
+
+define signext i32 @vararg2(i32 * %l, ...) {
+entry:
+ br i1 undef, label %cleanup, label %cond.end
+
+cond.end: ; preds = %entry
+ %call51 = call i32* @err(i32* nonnull %l)
+ unreachable
+
+cleanup: ; preds = %entry
+ ret i32 0
+}
+
+define i32* @caller_with_signext(i32* %foo) {
+entry:
+ %call1 = tail call signext i32 (i32*, ...) @vararg2(i32* %foo, i32 signext 8)
+ unreachable
+}
+
+; CHECK-LABEL: @caller_with_signext
+; CHECK: codeRepl.i:
+; CHECK-NEXT: call void (i32*, ...) @vararg2.1.cond.end(i32* %foo, i32 signext 8)
diff --git a/llvm/test/Transforms/CodeExtractor/PartialInlineVarArgsDebug.ll b/llvm/test/Transforms/CodeExtractor/PartialInlineVarArgsDebug.ll
new file mode 100644
index 00000000000..d19de842b61
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/PartialInlineVarArgsDebug.ll
@@ -0,0 +1,68 @@
+; RUN: opt < %s -S -partial-inliner -skip-partial-inlining-cost-analysis=true | FileCheck %s
+
+; CHECK-LABEL: @callee
+; CHECK: %mul = mul nsw i32 %v, 10, !dbg ![[DBG1:[0-9]+]]
+define i32 @callee(i32 %v, ...) !dbg !16 {
+entry:
+ %cmp = icmp sgt i32 %v, 2000, !dbg !17
+ br i1 %cmp, label %if.then, label %if.end, !dbg !19
+
+if.then: ; preds = %entry
+ %mul = mul nsw i32 %v, 10, !dbg !20
+ br label %if.end, !dbg !21
+
+if.end: ; preds = %if.then, %entry
+ %v2 = phi i32 [ %v, %entry ], [ %mul, %if.then ]
+ %add = add nsw i32 %v2, 200, !dbg !22
+ ret i32 %add, !dbg !23
+}
+
+; CHECK-LABEL: @caller
+; CHECK: codeRepl.i:
+; CHECK-NOT: br label
+; CHECK: call void (i32, i32*, ...) @callee.1.if.then(i32 %v, i32* %mul.loc.i, i32 99), !dbg ![[DBG2:[0-9]+]]
+define i32 @caller(i32 %v) !dbg !8 {
+entry:
+ %call = call i32 (i32, ...) @callee(i32 %v, i32 99), !dbg !14
+ ret i32 %call, !dbg !15
+}
+
+; CHECK-LABEL: define internal void @callee.1.if.then
+; CHECK: br label %if.then, !dbg ![[DBG3:[0-9]+]]
+
+; CHECK: ![[DBG1]] = !DILocation(line: 10, column: 7,
+; CHECK: ![[DBG2]] = !DILocation(line: 10, column: 7,
+; CHECK: ![[DBG3]] = !DILocation(line: 10, column: 7,
+
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5, !6}
+!llvm.ident = !{!7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 (trunk 177881)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "test.c", directory: "/tmp")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{i32 1, !"min_enum_size", i32 4}
+!7 = !{!"clang version 6.0.0"}
+!8 = distinct !DISubprogram(name: "caller", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !12)
+!9 = !DISubroutineType(types: !10)
+!10 = !{!11, !11}
+!11 = !DIBasicType(name: "int", size: 19, encoding: DW_ATE_signed)
+!12 = !{!13}
+!13 = !DILocalVariable(name: "v", arg: 1, scope: !8, file: !1, line: 3, type: !11)
+!14 = !DILocation(line: 5, column: 10, scope: !8)
+!15 = !DILocation(line: 5, column: 3, scope: !8)
+!16 = distinct !DISubprogram(name: "callee", scope: !1, file: !1, line: 8, type: !9, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !26)
+!26 = !{!27}
+!27 = !DILocalVariable(name: "v", arg: 1, scope: !16, file: !1, line: 8, type: !11)
+!17 = !DILocation(line: 9, column: 9, scope: !18)
+!18 = distinct !DILexicalBlock(scope: !16, file: !1, line: 9, column: 7)
+!19 = !DILocation(line: 9, column: 7, scope: !16)
+!20 = !DILocation(line: 10, column: 7, scope: !18)
+!21 = !DILocation(line: 10, column: 5, scope: !18)
+!22 = !DILocation(line: 11, column: 5, scope: !16)
+!36 = !DILocation(line: 12, column: 10, scope: !16)
+!23 = !DILocation(line: 12, column: 3, scope: !16)
diff --git a/llvm/test/Transforms/CodeExtractor/SingleCondition.ll b/llvm/test/Transforms/CodeExtractor/SingleCondition.ll
new file mode 100644
index 00000000000..334364484ee
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/SingleCondition.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -passes=partial-inliner -S | FileCheck %s
+
+define internal i32 @inlinedFunc(i1 %cond, i32* align 4 %align.val) {
+entry:
+ br i1 %cond, label %if.then, label %return
+if.then:
+ ; Dummy store to have more than 0 uses
+ store i32 10, i32* %align.val, align 4
+ br label %return
+return: ; preds = %entry
+ ret i32 0
+}
+
+define internal i32 @dummyCaller(i1 %cond, i32* align 2 %align.val) {
+entry:
+; CHECK-LABEL: @dummyCaller
+; CHECK: br
+; CHECK: call void @inlinedFunc.1.
+ %val = call i32 @inlinedFunc(i1 %cond, i32* %align.val)
+ ret i32 %val
+}
+
diff --git a/llvm/test/Transforms/CodeExtractor/X86/InheritTargetAttributes.ll b/llvm/test/Transforms/CodeExtractor/X86/InheritTargetAttributes.ll
new file mode 100644
index 00000000000..e6a5113261e
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/X86/InheritTargetAttributes.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis | llc -filetype=null
+; RUN: opt < %s -partial-inliner -skip-partial-inlining-cost-analysis -S | FileCheck %s
+; This testcase checks to see if CodeExtractor properly inherits
+; target specific attributes for the extracted function. This can
+; cause certain instructions that depend on the attributes to not
+; be lowered. Like in this test where we try to 'select' the blendvps
+; intrinsic on x86 that requires the +sse4.1 target feature.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind readnone
+declare <4 x float> @llvm.x86.sse41.blendvps(<4 x float>, <4 x float>, <4 x float>) #0
+
+; Function Attrs: nounwind uwtable
+define <4 x float> @inlinedFunc(i1, <4 x float>, <4 x float>, <4 x float>) #1 {
+entry:
+ br i1 %0, label %if.then, label %return
+if.then:
+; Target intrinsic that requires sse4.1
+ %target.call = call <4 x float> @llvm.x86.sse41.blendvps(<4 x float> %1, <4 x float> %2, <4 x float> %3)
+ br label %return
+return: ; preds = %entry
+ %retval = phi <4 x float> [ zeroinitializer, %entry ], [ %target.call, %if.then ]
+ ret <4 x float> %retval
+}
+
+; Function Attrs: nounwind uwtable
+define <4 x float> @dummyCaller(i1, <4 x float>, <4 x float>, <4 x float>) #1 {
+entry:
+ %val = call <4 x float> @inlinedFunc(i1 %0, <4 x float> %1, <4 x float> %2, <4 x float> %3)
+ ret <4 x float> %val
+}
+
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind uwtable "target-cpu"="x86-64" "target-features"="+sse4.1" }
+
+; CHECK: define {{.*}} @inlinedFunc.1.if.then{{.*}} [[COUNT1:#[0-9]+]]
+; CHECK: [[COUNT1]] = { {{.*}} "target-cpu"="x86-64" "target-features"="+sse4.1" }
diff --git a/llvm/test/Transforms/CodeExtractor/X86/lit.local.cfg b/llvm/test/Transforms/CodeExtractor/X86/lit.local.cfg
new file mode 100644
index 00000000000..e71f3cc4c41
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/X86/lit.local.cfg
@@ -0,0 +1,3 @@
+if not 'X86' in config.root.targets:
+ config.unsupported = True
+
diff --git a/llvm/test/Transforms/CodeExtractor/cost.ll b/llvm/test/Transforms/CodeExtractor/cost.ll
new file mode 100644
index 00000000000..841b42b7c35
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/cost.ll
@@ -0,0 +1,64 @@
+; RUN: opt -S < %s -partial-inliner -partial-inlining-extra-penalty=10 | FileCheck %s
+; RUN: opt -S < %s -passes=partial-inliner -partial-inlining-extra-penalty=10 | FileCheck %s
+define i32 @outline_region_notlikely(i32* %arg) local_unnamed_addr {
+bb:
+; ptr != null is predicted to be true
+ %tmp = icmp ne i32* %arg, null
+ br i1 %tmp, label %bb8, label %bb1
+
+; bb1 is not likely
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp3 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp4 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp5 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp6 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp7 = tail call i32 @foo(i32* nonnull %arg)
+ br label %bb8
+
+bb8: ; preds = %bb1, %bb
+ %tmp9 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp9
+}
+
+define i32 @outline_region_likely(i32* %arg) local_unnamed_addr {
+bb:
+; ptr == null is predicted to be false
+ %tmp = icmp eq i32* %arg, null
+ br i1 %tmp, label %bb8, label %bb1
+
+; bb1 is likely
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp3 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp4 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp5 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp6 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp7 = tail call i32 @foo(i32* nonnull %arg)
+ br label %bb8
+
+bb8: ; preds = %bb1, %bb
+ %tmp9 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp9
+}
+
+declare i32 @foo(i32* %arg)
+
+define i32 @dummy_caller(i32* %arg) local_unnamed_addr {
+; CHECK-LABEL: @dummy_caller
+ %tmp = call i32 @outline_region_notlikely(i32* %arg)
+; CHECK: call void @outline_region_notlikely.2.bb1
+ %tmp2 = tail call i32 @outline_region_likely(i32* %arg)
+; CHECK: %tmp2 = tail call i32 @outline_region_likely(i32* %arg)
+ ret i32 %tmp
+
+}
+
+; CHECK-LABEL: define internal void @outline_region_notlikely.2.bb1(i32* %arg) {
+; CHECK-NEXT: newFuncRoot:
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
diff --git a/llvm/test/Transforms/CodeExtractor/cost_meta.ll b/llvm/test/Transforms/CodeExtractor/cost_meta.ll
new file mode 100644
index 00000000000..ca1690a4c9f
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/cost_meta.ll
@@ -0,0 +1,41 @@
+; RUN: opt -S < %s -partial-inliner -partial-inlining-extra-penalty=2000 | FileCheck %s
+; RUN: opt -S < %s -passes=partial-inliner -partial-inlining-extra-penalty=2000 | FileCheck %s
+define i32 @outline_region_notlikely(i32* %arg) local_unnamed_addr {
+bb:
+; ptr != null is predicted to be true
+ %tmp = icmp ne i32* %arg, null
+ br i1 %tmp, label %bb8, label %bb1, !prof !2
+
+; bb1 is not likely
+bb1: ; preds = %bb
+ %tmp2 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp3 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp4 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp5 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp6 = tail call i32 @foo(i32* nonnull %arg)
+ %tmp7 = tail call i32 @foo(i32* nonnull %arg)
+ br label %bb8
+
+bb8: ; preds = %bb1, %bb
+ %tmp9 = phi i32 [ 0, %bb1 ], [ 1, %bb ]
+ ret i32 %tmp9
+}
+
+define i32 @dummy_caller(i32* %arg) local_unnamed_addr {
+; CHECK-LABEL: @dummy_caller
+ %tmp = call i32 @outline_region_notlikely(i32* %arg)
+ ret i32 %tmp
+ }
+
+
+; CHECK-LABEL: define internal void @outline_region_notlikely.1.bb1(i32* %arg) {
+; CHECK-NEXT: newFuncRoot:
+
+declare i32 @foo(i32 * %arg)
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!"branch_weights", i32 2000, i32 1}
diff --git a/llvm/test/Transforms/CodeExtractor/extract-assume.ll b/llvm/test/Transforms/CodeExtractor/extract-assume.ll
new file mode 100644
index 00000000000..b79c6a69137
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/extract-assume.ll
@@ -0,0 +1,29 @@
+; RUN: opt -passes="function(slp-vectorizer),module(hotcoldsplit),function(slp-vectorizer,print<assumptions>)" -disable-output %s 2>&1 | FileCheck %s
+;
+; Make sure this compiles. Check that function assumption cache is refreshed
+; after extracting blocks with assume calls from the function.
+
+; CHECK: Cached assumptions for function: fun
+; CHECK-NEXT: Cached assumptions for function: fun.cold
+; CHECK-NEXT: %cmp = icmp uge i32 %x, 64
+
+declare void @fun2(i32) #0
+
+define void @fun(i32 %x) {
+entry:
+ br i1 undef, label %if.then, label %if.else
+
+if.then:
+ ret void
+
+if.else:
+ %cmp = icmp uge i32 %x, 64
+ call void @llvm.assume(i1 %cmp)
+ call void @fun2(i32 %x)
+ unreachable
+}
+
+declare void @llvm.assume(i1) #1
+
+attributes #0 = { alwaysinline }
+attributes #1 = { nounwind }
diff --git a/llvm/test/Transforms/CodeExtractor/inline_eh.ll b/llvm/test/Transforms/CodeExtractor/inline_eh.ll
new file mode 100644
index 00000000000..a69e0c30bb9
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/inline_eh.ll
@@ -0,0 +1,52 @@
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -passes=partial-inliner -S | FileCheck %s
+
+declare void @bar()
+declare i32 @__gxx_personality_v0(...)
+declare i8* @__cxa_begin_catch(i8*)
+declare void @__cxa_end_catch()
+
+define internal void @callee(i1 %cond) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+ br i1 %cond, label %if.then, label %if.end
+
+if.then:
+ invoke void @bar()
+ to label %invoke.cont unwind label %lpad
+
+invoke.cont:
+ br label %try.cont
+
+lpad:
+ %0 = landingpad { i8*, i32 }
+ catch i8* null
+ %1 = extractvalue { i8*, i32 } %0, 0
+ %2 = extractvalue { i8*, i32 } %0, 1
+ br label %catch
+
+catch:
+ %3 = call i8* @__cxa_begin_catch(i8* %1)
+ call void @__cxa_end_catch()
+ br label %try.cont
+
+try.cont:
+ br label %if.end
+
+if.end:
+ ret void
+}
+
+define internal void @caller(i1 %cond) {
+; CHECK-LABEL: define {{.*}} @caller
+entry:
+; CHECK: entry:
+; CHECK-NEXT: br i1
+; CHECK: codeRepl.i:
+; CHECK-NEXT: call void @callee.1.{{.*}}()
+ call void @callee(i1 %cond)
+ ret void
+}
+
+; CHECK-LABEL: define {{.*}} @callee.1.{{.*}}() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+; CHECK: invoke void @bar()
+; CHECK: landingpad
diff --git a/llvm/test/Transforms/CodeExtractor/inline_eh_1.ll b/llvm/test/Transforms/CodeExtractor/inline_eh_1.ll
new file mode 100644
index 00000000000..b01abb6c1e8
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/inline_eh_1.ll
@@ -0,0 +1,56 @@
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -partial-inliner -S | FileCheck %s
+; RUN: opt < %s -skip-partial-inlining-cost-analysis -passes=partial-inliner -S | FileCheck %s
+
+declare dso_local void @bar()
+declare dso_local i32 @__CxxFrameHandler3(...)
+
+define internal void @callee(i1 %cond) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+entry:
+ br i1 %cond, label %if.then, label %if.end
+
+if.then:
+ invoke void @bar()
+ to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:
+ br label %try.cont
+
+ehcleanup:
+ %0 = cleanuppad within none []
+ cleanupret from %0 unwind label %catch.dispatch
+
+catch.dispatch:
+ %1 = catchswitch within none [label %catch] unwind to caller
+
+catch:
+ %2 = catchpad within %1 [i8* null, i32 64, i8* null]
+ catchret from %2 to label %catchret.dest
+
+catchret.dest:
+ br label %try.cont
+
+try.cont:
+ br label %if.end
+
+if.end:
+ ret void
+}
+
+define internal void @caller(i1 %cond) {
+; CHECK-LABEL: define {{.*}} @caller
+entry:
+; CHECK: entry:
+; CHECK-NEXT: br i1
+; CHECK: codeRepl.i:
+; CHECK-NEXT: call void @callee.1.{{.*}}()
+ call void @callee(i1 %cond)
+ ret void
+}
+
+; CHECK-LABEL: define {{.*}} @callee.1.{{.*}}() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
+; CHECK: invoke void @bar()
+; CHECK: cleanuppad
+; CHECK-NEXT: cleanupret
+; CHECK: catchswitch
+; CHECK: catchpad
+; CHECK-NEXT: catchret
diff --git a/llvm/test/Transforms/CodeExtractor/live_shrink.ll b/llvm/test/Transforms/CodeExtractor/live_shrink.ll
new file mode 100644
index 00000000000..780ab480c4b
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/live_shrink.ll
@@ -0,0 +1,67 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov()
+bb:
+; CHECK: bb:
+; CHECK-NOT: alloca
+; CHECK-NOT: bitcast
+; CHECK-NOT: llvm.lifetime
+; CHECK: br i1
+; CHECK: codeRepl.i:
+; CHECK: call void @_Z3foov.1.
+
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1.
+; CHECK: newFuncRoot:
+; CHECK-NEXT: %tmp = alloca %class.A
+; CHECK-NEXT: %tmp1 = bitcast %class.A* %tmp to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK-NEXT: br label %bb5.exitStub
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/llvm/test/Transforms/CodeExtractor/live_shrink_gep.ll b/llvm/test/Transforms/CodeExtractor/live_shrink_gep.ll
new file mode 100644
index 00000000000..aed86f84b66
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/live_shrink_gep.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i8 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 1
+ %tmp1 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0
+ call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov()
+bb:
+; CHECK: bb:
+; CHECK-NOT: alloca
+; CHECK-NOT: getelementptr
+; CHECK-NOT: llvm.lifetime
+; CHECK: br i1
+; CHECK: codeRepl.i:
+; CHECK: call void @_Z3foov.1.
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1.
+; CHECK: newFuncRoot:
+; CHECK-NEXT: %tmp = alloca %class.A
+; CHECK-NEXT: %tmp1 = getelementptr
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: br label %bb5.exitStub
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/llvm/test/Transforms/CodeExtractor/live_shrink_hoist.ll b/llvm/test/Transforms/CodeExtractor/live_shrink_hoist.ll
new file mode 100644
index 00000000000..13dab8d6b83
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/live_shrink_hoist.ll
@@ -0,0 +1,70 @@
+; RUN: opt -S -partial-inliner -max-num-inline-blocks=3 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb9
+
+bb4: ; preds = %bb
+ %foo = icmp eq i32 %tmp2, 0
+ br i1 %foo, label %bb5, label %bb9
+
+bb5: ; preds = %bb4
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ %tmp5 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0
+ %tmp6 = load i32, i32* %tmp5, align 4, !tbaa !6
+ %tmp7 = icmp sgt i32 %tmp6, 0
+ br i1 %tmp7, label %bb9, label %bb8
+
+bb8: ; preds = %bb4
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb9
+
+bb9: ; preds = %bb8, %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+bb:
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1.
+; CHECK: bb9:
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK: br label %.exitStub
+
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
+!6 = !{!7, !3, i64 0}
+!7 = !{!"_ZTS1A", !3, i64 0}
diff --git a/llvm/test/Transforms/CodeExtractor/live_shrink_multiple.ll b/llvm/test/Transforms/CodeExtractor/live_shrink_multiple.ll
new file mode 100644
index 00000000000..9350ca2ef9c
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/live_shrink_multiple.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = alloca %class.A, align 4
+ %tmp2 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2)
+ %tmp3 = bitcast %class.A* %tmp1 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3)
+ %tmp4 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp5 = icmp eq i32 %tmp4, 0
+ br i1 %tmp5, label %bb6, label %bb7
+
+bb6: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb7
+
+bb7: ; preds = %bb6, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+bb:
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1.
+; CHECK: newFuncRoot:
+; CHECK-NEXT: alloca
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK-NEXT: alloca
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: br label {{.*}}exitStub
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/llvm/test/Transforms/CodeExtractor/live_shrink_unsafe.ll b/llvm/test/Transforms/CodeExtractor/live_shrink_unsafe.ll
new file mode 100644
index 00000000000..ea6458cc46e
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/live_shrink_unsafe.ll
@@ -0,0 +1,94 @@
+; The expected behavior of this file is expected to change when partial
+; inlining legality check is enhanced.
+
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+@condptr = external local_unnamed_addr global i32*, align 8
+
+; Function Attrs: uwtable
+define void @_Z3foo_unknown_mem_accessv() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = alloca %class.A, align 4
+ %tmp2 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2)
+ %tmp3 = bitcast %class.A* %tmp1 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3)
+ %tmp4 = load i32*, i32** @condptr, align 8, !tbaa !2
+ %tmp5 = load i32, i32* %tmp4, align 4, !tbaa !6
+ %tmp6 = icmp eq i32 %tmp5, 0
+ br i1 %tmp6, label %bb7, label %bb8
+
+bb7: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb8
+
+bb8: ; preds = %bb7, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2)
+ ret void
+}
+
+declare void @_Z3barv() local_unnamed_addr
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+define void @_Z3foo_unknown_calli(i32 %arg) local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ tail call void @_Z3barv()
+ %tmp2 = icmp eq i32 %arg, 0
+ br i1 %tmp2, label %bb3, label %bb4
+
+bb3: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb4
+
+bb4: ; preds = %bb3, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov
+; CHECK-NEXT: bb:
+; CHECK: alloca
+; CHECK: lifetime
+bb:
+ call void @_Z3foo_unknown_mem_accessv()
+ %tmp = load i32, i32* @cond, align 4, !tbaa !2
+ tail call void @_Z3foo_unknown_calli(i32 %tmp)
+ ret void
+}
+
+; CHECK-LABEL define internal void @_Z3foo_unknown_calli.1_bb3
+; CHECK: newFuncRoot:
+; CHECK-NEXT: br label %bb3
+
+; CHECK: bb4.exitStub:
+; CHECK-NEXT: ret void
+
+; CHECK: bb3:
+; CHECK-NOT: lifetime.ed
+; CHECK: br label %bb4.exitStub
+
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"any pointer", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"int", !4, i64 0}
diff --git a/llvm/test/Transforms/CodeExtractor/unreachable-block.ll b/llvm/test/Transforms/CodeExtractor/unreachable-block.ll
new file mode 100644
index 00000000000..7ce65f529a6
--- /dev/null
+++ b/llvm/test/Transforms/CodeExtractor/unreachable-block.ll
@@ -0,0 +1,36 @@
+; RUN: opt -S -partial-inliner %s | FileCheck %s
+
+; CHECK-LABEL: define void @dipsy(
+; CHECK-NEXT: call void @tinkywinky.1.ontrue()
+; CHECK-NEXT: call void @patatuccio()
+; CHECK-NEXT: ret void
+; CHECK-NEXT: }
+
+; CHECK-LABEL: define internal void @tinkywinky.1.ontrue() {
+; CHECK-NEXT: newFuncRoot:
+; CHECK-NEXT: br label %ontrue
+; CHECK: onfalse{{.*}}:
+; CHECK-NEXT: ret void
+; CHECK: ontrue:
+; CHECK-NEXT: call void @patatino()
+; CHECK-NEXT: br label %onfalse{{.*}}
+; CHECK-NEXT: }
+
+declare void @patatino()
+declare void @patatuccio()
+
+define fastcc void @tinkywinky() {
+ br i1 true, label %ontrue, label %onfalse
+ontrue:
+ call void @patatino()
+ br label %onfalse
+onfalse:
+ call void @patatuccio()
+ ret void
+cantreachme:
+ ret void
+}
+define void @dipsy() {
+ call fastcc void @tinkywinky()
+ ret void
+}
OpenPOWER on IntegriCloud