Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
LLVM bpEVL
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Lorenzo Albano
LLVM bpEVL
Commits
b1120055
Commit
b1120055
authored
22 years ago
by
Chris Lattner
Browse files
Options
Downloads
Patches
Plain Diff
Rework inline pass to use cloning infrastructure to do the dirty work
llvm-svn: 4766
parent
891bbab8
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
llvm/lib/Transforms/IPO/InlineSimple.cpp
+38
-112
38 additions, 112 deletions
llvm/lib/Transforms/IPO/InlineSimple.cpp
llvm/lib/Transforms/Utils/CloneFunction.cpp
+14
-7
14 additions, 7 deletions
llvm/lib/Transforms/Utils/CloneFunction.cpp
with
52 additions
and
119 deletions
llvm/lib/Transforms/IPO/InlineSimple.cpp
+
38
−
112
View file @
b1120055
...
...
@@ -32,27 +32,6 @@
static
Statistic
<>
NumInlined
(
"inline"
,
"Number of functions inlined"
);
using
std
::
cerr
;
// RemapInstruction - Convert the instruction operands from referencing the
// current values into those specified by ValueMap.
//
static
inline
void
RemapInstruction
(
Instruction
*
I
,
std
::
map
<
const
Value
*
,
Value
*>
&
ValueMap
)
{
for
(
unsigned
op
=
0
,
E
=
I
->
getNumOperands
();
op
!=
E
;
++
op
)
{
const
Value
*
Op
=
I
->
getOperand
(
op
);
Value
*
V
=
ValueMap
[
Op
];
if
(
!
V
&&
(
isa
<
GlobalValue
>
(
Op
)
||
isa
<
Constant
>
(
Op
)))
continue
;
// Globals and constants don't get relocated
if
(
!
V
)
{
cerr
<<
"Val =
\n
"
<<
Op
<<
"Addr = "
<<
(
void
*
)
Op
;
cerr
<<
"
\n
Inst = "
<<
I
;
}
assert
(
V
&&
"Referenced value not in value map!"
);
I
->
setOperand
(
op
,
V
);
}
}
// InlineFunction - This function forcibly inlines the called function into the
// basic block of the caller. This returns false if it is not possible to
// inline this call. The program is still in a well defined state if this
...
...
@@ -92,7 +71,7 @@ bool InlineFunction(CallInst *CI) {
// function.
//
PHINode
*
PHI
=
0
;
if
(
CalledFunc
->
getReturnType
()
!=
Type
::
VoidTy
)
{
if
(
!
CI
->
use_empty
()
)
{
// The PHI node should go at the front of the new basic block to merge all
// possible incoming values.
//
...
...
@@ -105,102 +84,52 @@ bool InlineFunction(CallInst *CI) {
CI
->
replaceAllUsesWith
(
PHI
);
}
// Keep a mapping between the original function's values and the new
// duplicated code's values. This includes all of: Function arguments,
// instruction values, constant pool entries, and basic blocks.
// Get a pointer to the last basic block in the function, which will have the
// new function inlined after it.
//
std
::
map
<
const
Value
*
,
Value
*>
ValueMap
;
Function
::
iterator
LastBlock
=
&
OrigBB
->
getParent
()
->
back
()
;
// Add the function arguments to the mapping: (start counting at 1 to skip the
// function reference itself)
//
Function
::
const_aiterator
PTI
=
CalledFunc
->
abegin
();
for
(
unsigned
a
=
1
,
E
=
CI
->
getNumOperands
();
a
!=
E
;
++
a
,
++
PTI
)
ValueMap
[
PTI
]
=
CI
->
getOperand
(
a
);
ValueMap
[
NewBB
]
=
NewBB
;
// Returns get converted to reference NewBB
// Loop over all of the basic blocks in the function, inlining them as
// appropriate. Keep track of the first basic block of the function...
//
for
(
Function
::
const_iterator
BB
=
CalledFunc
->
begin
();
BB
!=
CalledFunc
->
end
();
++
BB
)
{
assert
(
BB
->
getTerminator
()
&&
"BasicBlock doesn't have terminator!?!?"
);
// Create a new basic block to copy instructions into!
BasicBlock
*
IBB
=
new
BasicBlock
(
""
,
NewBB
->
getParent
());
if
(
BB
->
hasName
())
IBB
->
setName
(
BB
->
getName
()
+
".i"
);
// .i = inlined once
ValueMap
[
BB
]
=
IBB
;
// Add basic block mapping.
// Make sure to capture the mapping that a return will use...
// TODO: This assumes that the RET is returning a value computed in the same
// basic block as the return was issued from!
//
const
TerminatorInst
*
TI
=
BB
->
getTerminator
();
// Loop over all instructions copying them over...
Instruction
*
NewInst
;
for
(
BasicBlock
::
const_iterator
II
=
BB
->
begin
();
II
!=
--
BB
->
end
();
++
II
)
{
IBB
->
getInstList
().
push_back
((
NewInst
=
II
->
clone
()));
ValueMap
[
II
]
=
NewInst
;
// Add instruction map to value.
if
(
II
->
hasName
())
NewInst
->
setName
(
II
->
getName
()
+
".i"
);
// .i = inlined once
}
// Calculate the vector of arguments to pass into the function cloner...
std
::
vector
<
Value
*>
ArgVector
;
for
(
unsigned
i
=
1
,
e
=
CI
->
getNumOperands
();
i
!=
e
;
++
i
)
ArgVector
.
push_back
(
CI
->
getOperand
(
i
));
// Copy over the terminator now...
switch
(
TI
->
getOpcode
())
{
case
Instruction
::
Ret
:
{
const
ReturnInst
*
RI
=
cast
<
ReturnInst
>
(
TI
);
if
(
PHI
)
{
// The PHI node should include this value!
assert
(
RI
->
getReturnValue
()
&&
"Ret should have value!"
);
assert
(
RI
->
getReturnValue
()
->
getType
()
==
PHI
->
getType
()
&&
"Ret value not consistent in function!"
);
PHI
->
addIncoming
((
Value
*
)
RI
->
getReturnValue
(),
(
BasicBlock
*
)
cast
<
BasicBlock
>
(
&*
BB
));
}
// Since we are now done with the CallInst, we can delete it.
delete
CI
;
// Add a branch to the code that was after the original Call.
IBB
->
getInstList
().
push_back
(
new
BranchInst
(
NewBB
));
break
;
}
case
Instruction
::
Br
:
IBB
->
getInstList
().
push_back
(
TI
->
clone
());
break
;
// Make a vector to capture the return instructions in the cloned function...
std
::
vector
<
ReturnInst
*>
Returns
;
default
:
cerr
<<
"FunctionInlining: Don't know how to handle terminator: "
<<
TI
;
abort
();
}
}
// Do all of the hard part of cloning the callee into the caller...
CloneFunctionInto
(
OrigBB
->
getParent
(),
CalledFunc
,
ArgVector
,
Returns
,
".i"
);
// Loop over all of the return instructions, turning them into unconditional
// branches to the merge point now...
for
(
unsigned
i
=
0
,
e
=
Returns
.
size
();
i
!=
e
;
++
i
)
{
ReturnInst
*
RI
=
Returns
[
i
];
BasicBlock
*
BB
=
RI
->
getParent
();
// Loop over all of the instructions in the function, fixing up operand
// references as we go. This uses ValueMap to do all the hard work.
//
for
(
Function
::
const_iterator
BB
=
CalledFunc
->
begin
();
BB
!=
CalledFunc
->
end
();
++
BB
)
{
BasicBlock
*
NBB
=
(
BasicBlock
*
)
ValueMap
[
BB
];
// Add a branch to the merge point where the PHI node would live...
new
BranchInst
(
NewBB
,
RI
);
// Loop over all instructions, fixing each one as we find it...
//
for
(
BasicBlock
::
iterator
II
=
NBB
->
begin
();
II
!=
NBB
->
end
();
++
II
)
RemapInstruction
(
II
,
ValueMap
);
}
if
(
PHI
)
{
// The PHI node should include this value!
assert
(
RI
->
getReturnValue
()
&&
"Ret should have value!"
);
assert
(
RI
->
getReturnValue
()
->
getType
()
==
PHI
->
getType
()
&&
"Ret value not consistent in function!"
);
PHI
->
addIncoming
(
RI
->
getReturnValue
(),
BB
);
}
if
(
PHI
)
{
RemapInstruction
(
PHI
,
ValueMap
);
// Fix the PHI node also...
// Delete the return instruction now
BB
->
getInstList
().
erase
(
RI
);
}
// Check to see if the PHI node only has one argument. This is a common
// case resulting from there only being a single return instruction in the
// function call. Because this is so common, eliminate the PHI node.
//
if
(
PHI
->
getNumIncomingValues
()
==
1
)
{
PHI
->
replaceAllUsesWith
(
PHI
->
getIncomingValue
(
0
));
PHI
->
getParent
()
->
getInstList
().
erase
(
PHI
);
}
// Check to see if the PHI node only has one argument. This is a common
// case resulting from there only being a single return instruction in the
// function call. Because this is so common, eliminate the PHI node.
//
if
(
PHI
&&
PHI
->
getNumIncomingValues
()
==
1
)
{
PHI
->
replaceAllUsesWith
(
PHI
->
getIncomingValue
(
0
));
PHI
->
getParent
()
->
getInstList
().
erase
(
PHI
);
}
// Change the branch that used to go to NewBB to branch to the first basic
...
...
@@ -209,10 +138,7 @@ bool InlineFunction(CallInst *CI) {
TerminatorInst
*
Br
=
OrigBB
->
getTerminator
();
assert
(
Br
&&
Br
->
getOpcode
()
==
Instruction
::
Br
&&
"splitBasicBlock broken!"
);
Br
->
setOperand
(
0
,
ValueMap
[
&
CalledFunc
->
front
()]);
// Since we are now done with the CallInst, we can finally delete it.
delete
CI
;
Br
->
setOperand
(
0
,
++
LastBlock
);
return
true
;
}
...
...
This diff is collapsed.
Click to expand it.
llvm/lib/Transforms/Utils/CloneFunction.cpp
+
14
−
7
View file @
b1120055
...
...
@@ -4,6 +4,7 @@
// FIXME: document
#include
"llvm/Transforms/Utils/Cloning.h"
#include
"llvm/iTerminators.h"
#include
"llvm/Function.h"
#include
<map>
...
...
@@ -35,9 +36,10 @@ static inline void RemapInstruction(Instruction *I,
// ArgMap values.
//
void
CloneFunctionInto
(
Function
*
NewFunc
,
const
Function
*
OldFunc
,
const
std
::
vector
<
Value
*>
&
ArgMap
)
{
assert
(
OldFunc
->
aempty
()
||
!
NewFunc
->
aempty
()
&&
"Synthesization of arguments is not implemented yet!"
);
const
std
::
vector
<
Value
*>
&
ArgMap
,
std
::
vector
<
ReturnInst
*>
&
Returns
,
const
char
*
NameSuffix
)
{
assert
(
NameSuffix
&&
"NameSuffix cannot be null!"
);
assert
(
OldFunc
->
asize
()
==
ArgMap
.
size
()
&&
"Improper number of argument values to map specified!"
);
...
...
@@ -55,25 +57,30 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
// Loop over all of the basic blocks in the function, cloning them as
// appropriate.
// appropriate. Note that we save BE this way in order to handle cloning of
// recursive functions into themselves.
//
for
(
Function
::
const_iterator
BI
=
OldFunc
->
begin
(),
BE
=
OldFunc
->
end
();
BI
!=
BE
;
++
BI
)
{
const
BasicBlock
&
BB
=
*
BI
;
assert
(
BB
.
getTerminator
()
&&
"BasicBlock doesn't have terminator!?!?"
);
// Create a new basic block to copy instructions into!
BasicBlock
*
CBB
=
new
BasicBlock
(
BB
.
getName
(),
NewFunc
);
BasicBlock
*
CBB
=
new
BasicBlock
(
""
,
NewFunc
);
if
(
BB
.
hasName
())
CBB
->
setName
(
BB
.
getName
()
+
NameSuffix
);
ValueMap
[
&
BB
]
=
CBB
;
// Add basic block mapping.
// Loop over all instructions copying them over...
for
(
BasicBlock
::
const_iterator
II
=
BB
.
begin
(),
IE
=
BB
.
end
();
II
!=
IE
;
++
II
)
{
Instruction
*
NewInst
=
II
->
clone
();
NewInst
->
setName
(
II
->
getName
());
// Name is not cloned...
if
(
II
->
hasName
())
NewInst
->
setName
(
II
->
getName
()
+
NameSuffix
);
// Name is not cloned...
CBB
->
getInstList
().
push_back
(
NewInst
);
ValueMap
[
II
]
=
NewInst
;
// Add instruction map to value.
}
if
(
ReturnInst
*
RI
=
dyn_cast
<
ReturnInst
>
(
CBB
->
getTerminator
()))
Returns
.
push_back
(
RI
);
}
// Loop over all of the instructions in the function, fixing up operand
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment