123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- //===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements a utility function for replacing LLVM constant
- // expressions by instructions.
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/IR/ReplaceConstant.h"
- #include "llvm/ADT/SmallPtrSet.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/ValueMap.h"
- namespace llvm {
- void convertConstantExprsToInstructions(Instruction *I, ConstantExpr *CE,
- SmallPtrSetImpl<Instruction *> *Insts) {
- // Collect all reachable paths to CE from constant exprssion operands of I.
- std::map<Use *, std::vector<std::vector<ConstantExpr *>>> CEPaths;
- collectConstantExprPaths(I, CE, CEPaths);
- // Convert all constant expressions to instructions which are collected at
- // CEPaths.
- convertConstantExprsToInstructions(I, CEPaths, Insts);
- }
- void convertConstantExprsToInstructions(
- Instruction *I,
- std::map<Use *, std::vector<std::vector<ConstantExpr *>>> &CEPaths,
- SmallPtrSetImpl<Instruction *> *Insts) {
- ValueMap<ConstantExpr *, Instruction *> Visited;
- for (Use &U : I->operands()) {
- // The operand U is either not a constant expression operand or the
- // constant expression paths do not belong to U, ignore U.
- if (!CEPaths.count(&U))
- continue;
- // If the instruction I is a PHI instruction, then fix the instruction
- // insertion point to the entry of the incoming basic block for operand U.
- auto *BI = I;
- if (auto *Phi = dyn_cast<PHINode>(I)) {
- BasicBlock *BB = Phi->getIncomingBlock(U);
- BI = &(*(BB->getFirstInsertionPt()));
- }
- // Go through all the paths associated with operand U, and convert all the
- // constant expressions along all the paths to corresponding instructions.
- auto *II = I;
- auto &Paths = CEPaths[&U];
- for (auto &Path : Paths) {
- for (auto *CE : Path) {
- // Instruction which is equivalent to CE.
- Instruction *NI = nullptr;
- if (!Visited.count(CE)) {
- // CE is encountered first time, convert it into a corresponding
- // instruction NI, and appropriately insert NI before the parent
- // instruction.
- NI = CE->getAsInstruction(BI);
- // Mark CE as visited by mapping CE to NI.
- Visited[CE] = NI;
- // If required collect NI.
- if (Insts)
- Insts->insert(NI);
- } else {
- // We had already encountered CE, the correponding instruction already
- // exist, use it to replace CE.
- NI = Visited[CE];
- }
- assert(NI && "Expected an instruction corresponding to constant "
- "expression.");
- // Replace all uses of constant expression CE by the corresponding
- // instruction NI within the current parent instruction.
- II->replaceUsesOfWith(CE, NI);
- BI = II = NI;
- }
- }
- }
- // Remove all converted constant expressions which are dead by now.
- for (auto Item : Visited)
- Item.first->removeDeadConstantUsers();
- }
- void collectConstantExprPaths(
- Instruction *I, ConstantExpr *CE,
- std::map<Use *, std::vector<std::vector<ConstantExpr *>>> &CEPaths) {
- for (Use &U : I->operands()) {
- // If the operand U is not a constant expression operand, then ignore it.
- auto *CE2 = dyn_cast<ConstantExpr>(U.get());
- if (!CE2)
- continue;
- // Holds all reachable paths from CE2 to CE.
- std::vector<std::vector<ConstantExpr *>> Paths;
- // Collect all reachable paths from CE2 to CE.
- std::vector<ConstantExpr *> Path{CE2};
- std::vector<std::vector<ConstantExpr *>> Stack{Path};
- while (!Stack.empty()) {
- std::vector<ConstantExpr *> TPath = Stack.back();
- Stack.pop_back();
- auto *CE3 = TPath.back();
- if (CE3 == CE) {
- Paths.push_back(TPath);
- continue;
- }
- for (auto &UU : CE3->operands()) {
- if (auto *CE4 = dyn_cast<ConstantExpr>(UU.get())) {
- std::vector<ConstantExpr *> NPath(TPath.begin(), TPath.end());
- NPath.push_back(CE4);
- Stack.push_back(NPath);
- }
- }
- }
- // Associate all the collected paths with U, and save it.
- if (!Paths.empty())
- CEPaths[&U] = Paths;
- }
- }
- } // namespace llvm
|