29#define DEBUG_TYPE "normalize"
45 const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
52 void nameFunctionArguments(
Function &
F)
const;
62 void reorderInstructions(
Function &
F)
const;
64 std::stack<Instruction *> &TopologicalSort,
66 void reorderInstructionOperandsByNames(
Instruction *
I)
const;
67 void reorderPHIIncomingValues(
PHINode *Phi)
const;
77 bool hasOnlyImmediateOperands(
const Instruction *
I)
const;
88bool IRNormalizer::runOnFunction(
Function &
F) {
89 nameFunctionArguments(
F);
92 Outputs = collectOutputInstructions(
F);
95 reorderInstructions(
F);
99 for (
auto &
I : Outputs)
105 reorderInstructionOperandsByNames(&
I);
108 reorderPHIIncomingValues(Phi);
110 foldInstructionName(&
I);
119void IRNormalizer::nameFunctionArguments(Function &
F)
const {
120 int ArgumentCounter = 0;
121 for (
auto &
A :
F.args()) {
122 if (
Options.RenameAll ||
A.getName().empty()) {
123 A.setName(
"a" + Twine(ArgumentCounter));
124 ArgumentCounter += 1;
133void IRNormalizer::nameBasicBlocks(Function &
F)
const {
136 uint64_t Hash = MagicHashConstant;
143 if (
Options.RenameAll ||
B.getName().empty()) {
145 B.setName(
"bb" + std::to_string(Hash).
substr(0, 5));
155void IRNormalizer::nameInstruction(Instruction *
I) {
159 if (NamedInstructions.contains(
I))
161 NamedInstructions.insert(
I);
162 if (isInitialInstruction(
I)) {
163 nameAsInitialInstruction(
I);
166 nameAsRegularInstruction(
I);
171void IRNormalizer::sortCommutativeOperands(Instruction *
I,
T &
Operands)
const {
172 if (!(
I->isCommutative() &&
Operands.size() >= 2))
174 auto CommutativeEnd =
Operands.begin();
175 std::advance(CommutativeEnd, 2);
192void IRNormalizer::nameAsInitialInstruction(Instruction *
I)
const {
193 if (
I->getType()->isVoidTy())
195 if (!(
I->getName().empty() ||
Options.RenameAll))
203 for (
auto &
Op :
I->operands()) {
205 std::string TextRepresentation;
206 raw_string_ostream Stream(TextRepresentation);
207 Op->printAsOperand(Stream,
false);
208 Operands.push_back(StringRef(Stream.str()));
215 uint64_t Hash = MagicHashConstant;
220 SmallPtrSet<const Instruction *, 32> Visited;
222 SetVector<int> OutputFootprint = getOutputFootprint(
I, Visited);
225 for (
const int &Output : OutputFootprint)
229 SmallString<256>
Name;
230 Name.append(
"vl" + std::to_string(Hash).
substr(0, 5));
237 Name.append(
F->getName());
241 for (
size_t i = 0; i <
Operands.size(); ++i) {
269void IRNormalizer::nameAsRegularInstruction(Instruction *
I) {
281 for (
auto &
Op :
I->operands()) {
288 std::string TextRepresentation;
289 raw_string_ostream Stream(TextRepresentation);
290 Op->printAsOperand(Stream,
false);
291 Operands.push_back(StringRef(Stream.str()));
298 uint64_t Hash = MagicHashConstant;
304 SmallVector<int, 4> OperandsOpcodes;
307 for (
auto &
Op :
I->operands())
311 sortCommutativeOperands(
I, OperandsOpcodes);
314 for (
const int Code : OperandsOpcodes)
318 SmallString<512>
Name;
319 Name.append(
"op" + std::to_string(Hash).
substr(0, 5));
323 if (
const Function *
F = CI->getCalledFunction())
324 Name.append(
F->getName());
327 for (
size_t i = 0; i <
Operands.size(); ++i) {
335 if ((
I->getName().empty() ||
Options.RenameAll) && !
I->getType()->isVoidTy())
352void IRNormalizer::foldInstructionName(Instruction *
I)
const {
357 for (
auto *U :
I->users())
364 if (isOutput(
I) || !
I->getName().starts_with(
"op"))
370 for (
auto &
Op :
I->operands()) {
373 I->getName().starts_with(
"op") ||
I->getName().starts_with(
"vl");
375 Operands.push_back(HasNormalName ?
I->getName().substr(0, 7)
382 SmallString<256>
Name;
383 Name.append(
I->getName().substr(0, 7));
386 for (
size_t i = 0; i <
Operands.size(); ++i) {
404void IRNormalizer::reorderInstructions(Function &
F)
const {
407 << BB.getName() <<
"\n");
415 std::stack<Instruction *> TopologicalSort;
416 SmallPtrSet<const Instruction *, 32> Visited;
419 if (!(isOutput(&
I) ||
I.isTerminator()))
421 LLVM_DEBUG(
dbgs() <<
"\tReordering from source effecting instruction: ";
423 reorderDefinition(&
I, TopologicalSort, Visited);
435 LLVM_DEBUG(
dbgs() <<
"\tReordering from source instruction: ";
I.dump());
436 reorderDefinition(&
I, TopologicalSort, Visited);
439 LLVM_DEBUG(
dbgs() <<
"Inserting instructions into: " << BB.getName()
442 while (!TopologicalSort.empty()) {
444 auto FirstNonPHIOrDbgOrAlloca = BB.getFirstNonPHIOrDbgOrAlloca();
447 Intrinsic::experimental_convergence_entry ||
449 FirstNonPHIOrDbgOrAlloca++;
452 TopologicalSort.pop();
457void IRNormalizer::reorderDefinition(
458 Instruction *Definition, std::stack<Instruction *> &TopologicalSort,
459 SmallPtrSet<const Instruction *, 32> &Visited)
const {
462 Visited.
insert(Definition);
466 const auto FirstNonPHIOrDbgOrAlloca =
468 if (FirstNonPHIOrDbgOrAlloca ==
BasicBlock->end())
470 if (Definition->
comesBefore(&*FirstNonPHIOrDbgOrAlloca))
474 for (
auto &Operand : Definition->
operands()) {
478 reorderDefinition(
Op, TopologicalSort, Visited);
502 TopologicalSort.emplace(Definition);
510void IRNormalizer::reorderInstructionOperandsByNames(Instruction *
I)
const {
519 for (
auto &
Op :
I->operands()) {
523 Operands.push_back(std::pair<std::string, Value *>(
V->getName(), V));
525 std::string TextRepresentation;
526 raw_string_ostream Stream(TextRepresentation);
527 Op->printAsOperand(Stream,
false);
528 Operands.push_back(std::pair<std::string, Value *>(Stream.str(), V));
537 unsigned Position = 0;
538 for (
auto &
Op :
I->operands()) {
548void IRNormalizer::reorderPHIIncomingValues(PHINode *Phi)
const {
553 for (
auto &BB :
Phi->blocks()) {
554 Value *
V =
Phi->getIncomingValueForBlock(BB);
555 Values.
push_back(std::pair<Value *, BasicBlock *>(V, BB));
559 llvm::sort(Values, [](
const std::pair<Value *, BasicBlock *> &
LHS,
560 const std::pair<Value *, BasicBlock *> &
RHS) {
565 for (
unsigned i = 0; i < Values.
size(); ++i) {
566 Phi->setIncomingBlock(i, Values[i].second);
567 Phi->setIncomingValue(i, Values[i].first);
576SmallVector<Instruction *, 16>
577IRNormalizer::collectOutputInstructions(Function &
F)
const {
580 SmallVector<Instruction *, 16> Outputs;
591bool IRNormalizer::isOutput(
const Instruction *
I)
const {
600bool IRNormalizer::isInitialInstruction(
const Instruction *
I)
const {
603 return !
I->user_empty() && hasOnlyImmediateOperands(
I);
609bool IRNormalizer::hasOnlyImmediateOperands(
const Instruction *
I)
const {
610 for (
const auto &
Op :
I->operands())
622SetVector<int> IRNormalizer::getOutputFootprint(
623 Instruction *
I, SmallPtrSet<const Instruction *, 32> &Visited)
const {
627 SetVector<int> Outputs;
638 for (
const auto &
B : *Func) {
639 for (
const auto &
E :
B) {
650 for (
auto *U :
I->users()) {
653 SetVector<int> OutputsUsingUI = getOutputFootprint(UI, Visited);
666 IRNormalizer(Options).runOnFunction(
F);
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
mir Rename Register Operands
This file implements a set that has insertion order iteration characteristics.
static StringRef substr(StringRef Str, uint64_t Len)
This file defines the SmallPtrSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
Represents analyses that only rely on functions' control flow.
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
bool isMustTailCall() const
Implements a dense probed hash-table based set.
bool isTerminator() const
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
A set of analyses that are preserved following a run of a transformation pass.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
A vector that has set insertion semantics.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void dump() const
Support for debugging, callable in GDB: V->dump()
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
uint64_t hash_16_bytes(uint64_t low, uint64_t high)
NodeAddr< PhiNode * > Phi
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) const