Skip to content

Commit f6795e6

Browse files
authored
[CodeExtractor] Refactor extractCodeRegion, fix alloca emission. (#114419)
Reorganize the code into phases: * Analyze/normalize * Create extracted function prototype * Generate the new function's implementation * Generate call to new function * Connect call to original function's CFG The motivation is #114669 to optionally clone the selected code region into the new function instead of moving it. The current structure made it difficult to add such functionality since there was no obvious place to do so, not made easier by some functions doing more than their name suggests. For instance, constructFunction modifies code outside the constructed function, but also function properties such as setPersonalityFn are derived somewhere else. Another example is emitCallAndSwitchStatement, which despite its name also inserts stores for output parameters. Many operations also implicitly depend on the order they are applied which this patch tries to reduce. For instance, ExtractedFuncRetVals becomes the list exit blocks which also defines the return value when leaving via that block. It is computed early such that the new function's return instructions and the switch can be generated independently. Also, ExtractedFuncRetVals is combining the lists ExitBlocks and OldTargets which were not always kept consistent with each other or NumExitBlocks. The method recomputeExitBlocks() will update it when necessary. The coding style partially contradict the current coding standard. For instance some local variable start with lower case letters. I updated some, but not all occurrences to make the diff match at least some lines as unchanged. The patch [D96854](https://reviews.llvm.org/D96854) introduced some confusion of function argument indexes this is fixed here as well, hence the patch is not NFC anymore. Tested in modified CodeExtractorTest.cpp. Patch [D121061](https://reviews.llvm.org/D121061) introduced AllocationBlock, but not all allocas were inserted there. Efectively includes the following fixes: 1. ce73b16 2. 4aaa925 3. Missing allocas, still unfixed Originally submitted as https://reviews.llvm.org/D115218
1 parent 7ebfbf9 commit f6795e6

File tree

3 files changed

+719
-533
lines changed

3 files changed

+719
-533
lines changed

llvm/include/llvm/Transforms/Utils/CodeExtractor.h

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Instruction;
3535
class Module;
3636
class Type;
3737
class Value;
38+
class StructType;
3839

3940
/// A cache for the CodeExtractor analysis. The operation \ref
4041
/// CodeExtractor::extractCodeRegion is guaranteed not to invalidate this
@@ -101,12 +102,25 @@ class CodeExtractorAnalysisCache {
101102

102103
// Bits of intermediate state computed at various phases of extraction.
103104
SetVector<BasicBlock *> Blocks;
104-
unsigned NumExitBlocks = std::numeric_limits<unsigned>::max();
105-
Type *RetTy;
106105

107-
// Mapping from the original exit blocks, to the new blocks inside
108-
// the function.
109-
SmallVector<BasicBlock *, 4> OldTargets;
106+
/// Lists of blocks that are branched from the code region to be extracted,
107+
/// also called the exit blocks. Each block is contained at most once. Its
108+
/// order defines the return value of the extracted function.
109+
///
110+
/// When there is just one (or no) exit block, the return value is
111+
/// irrelevant.
112+
///
113+
/// When there are exactly two exit blocks, the extracted function returns a
114+
/// boolean. For ExtractedFuncRetVals[0], it returns 'true'. For
115+
/// ExtractedFuncRetVals[1] it returns 'false'.
116+
/// NOTE: Since a boolean is represented by i1, ExtractedFuncRetVals[0]
117+
/// returns 1 and ExtractedFuncRetVals[1] returns 0, which opposite
118+
/// of the regular pattern below.
119+
///
120+
/// When there are 3 or more exit blocks, leaving the extracted function via
121+
/// the first block it returns 0. When leaving via the second entry it
122+
/// returns 1, etc.
123+
SmallVector<BasicBlock *> ExtractedFuncRetVals;
110124

111125
// Suffix to use when creating extracted function (appended to the original
112126
// function name + "."). If empty, the default is to use the entry block
@@ -238,26 +252,61 @@ class CodeExtractorAnalysisCache {
238252
getLifetimeMarkers(const CodeExtractorAnalysisCache &CEAC,
239253
Instruction *Addr, BasicBlock *ExitBlock) const;
240254

255+
/// Updates the list of SwitchCases (corresponding to exit blocks) after
256+
/// changes of the control flow or the Blocks list.
257+
void computeExtractedFuncRetVals();
258+
259+
/// Return the type used for the return code of the extracted function to
260+
/// indicate which exit block to jump to.
261+
Type *getSwitchType();
262+
241263
void severSplitPHINodesOfEntry(BasicBlock *&Header);
242-
void severSplitPHINodesOfExits(const SetVector<BasicBlock *> &Exits);
264+
void severSplitPHINodesOfExits();
243265
void splitReturnBlocks();
244266

245-
Function *constructFunction(const ValueSet &inputs,
246-
const ValueSet &outputs,
247-
BasicBlock *header,
248-
BasicBlock *newRootNode, BasicBlock *newHeader,
249-
Function *oldFunction, Module *M);
250-
251267
void moveCodeToFunction(Function *newFunction);
252268

253269
void calculateNewCallTerminatorWeights(
254270
BasicBlock *CodeReplacer,
255-
DenseMap<BasicBlock *, BlockFrequency> &ExitWeights,
271+
const DenseMap<BasicBlock *, BlockFrequency> &ExitWeights,
256272
BranchProbabilityInfo *BPI);
257273

258-
CallInst *emitCallAndSwitchStatement(Function *newFunction,
259-
BasicBlock *newHeader,
260-
ValueSet &inputs, ValueSet &outputs);
274+
/// Normalizes the control flow of the extracted regions, such as ensuring
275+
/// that the extracted region does not contain a return instruction.
276+
void normalizeCFGForExtraction(BasicBlock *&header);
277+
278+
/// Generates the function declaration for the function containing the
279+
/// extracted code.
280+
Function *constructFunctionDeclaration(const ValueSet &inputs,
281+
const ValueSet &outputs,
282+
BlockFrequency EntryFreq,
283+
const Twine &Name,
284+
ValueSet &StructValues,
285+
StructType *&StructTy);
286+
287+
/// Generates the code for the extracted function. That is: a prolog, the
288+
/// moved or copied code from the original function, and epilogs for each
289+
/// exit.
290+
void emitFunctionBody(const ValueSet &inputs, const ValueSet &outputs,
291+
const ValueSet &StructValues, Function *newFunction,
292+
StructType *StructArgTy, BasicBlock *header,
293+
const ValueSet &SinkingCands);
294+
295+
/// Generates a Basic Block that calls the extracted function.
296+
CallInst *emitReplacerCall(const ValueSet &inputs, const ValueSet &outputs,
297+
const ValueSet &StructValues,
298+
Function *newFunction, StructType *StructArgTy,
299+
Function *oldFunction, BasicBlock *ReplIP,
300+
BlockFrequency EntryFreq,
301+
ArrayRef<Value *> LifetimesStart,
302+
std::vector<Value *> &Reloads);
303+
304+
/// Connects the basic block containing the call to the extracted function
305+
/// into the original function's control flow.
306+
void insertReplacerCall(
307+
Function *oldFunction, BasicBlock *header, BasicBlock *codeReplacer,
308+
const ValueSet &outputs, ArrayRef<Value *> Reloads,
309+
const DenseMap<BasicBlock *, BlockFrequency> &ExitWeights);
261310
};
262311

263312
} // end namespace llvm

0 commit comments

Comments
 (0)