1 //===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements a utility function for replacing LLVM constant
10 // expressions by instructions.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/IR/ReplaceConstant.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/NoFolder.h"
20 // Replace a constant expression by instructions with equivalent operations at
21 // a specified location.
22 Instruction
*createReplacementInstr(ConstantExpr
*CE
, Instruction
*Instr
) {
23 auto *CEInstr
= CE
->getAsInstruction();
24 CEInstr
->insertBefore(Instr
);
28 void convertConstantExprsToInstructions(Instruction
*I
, ConstantExpr
*CE
,
29 SmallPtrSetImpl
<Instruction
*> *Insts
) {
30 // Collect all reachable paths to CE from constant exprssion operands of I.
31 std::map
<Use
*, std::vector
<std::vector
<ConstantExpr
*>>> CEPaths
;
32 collectConstantExprPaths(I
, CE
, CEPaths
);
34 // Convert all constant expressions to instructions which are collected at
36 convertConstantExprsToInstructions(I
, CEPaths
, Insts
);
39 void convertConstantExprsToInstructions(
41 std::map
<Use
*, std::vector
<std::vector
<ConstantExpr
*>>> &CEPaths
,
42 SmallPtrSetImpl
<Instruction
*> *Insts
) {
43 SmallPtrSet
<ConstantExpr
*, 8> Visited
;
44 for (Use
&U
: I
->operands()) {
45 // The operand U is either not a constant expression operand or the
46 // constant expression paths do not belong to U, ignore U.
47 if (!CEPaths
.count(&U
))
50 // If the instruction I is a PHI instruction, then fix the instruction
51 // insertion point to the entry of the incoming basic block for operand U.
53 if (auto *Phi
= dyn_cast
<PHINode
>(I
)) {
54 BasicBlock
*BB
= Phi
->getIncomingBlock(U
);
55 BI
= &(*(BB
->getFirstInsertionPt()));
58 // Go through the paths associated with operand U, and convert all the
59 // constant expressions along all paths to corresponding instructions.
61 auto &Paths
= CEPaths
[&U
];
62 for (auto &Path
: Paths
) {
63 for (auto *CE
: Path
) {
64 if (!Visited
.insert(CE
).second
)
66 auto *NI
= CE
->getAsInstruction();
68 II
->replaceUsesOfWith(CE
, NI
);
69 CE
->removeDeadConstantUsers();
78 void collectConstantExprPaths(
79 Instruction
*I
, ConstantExpr
*CE
,
80 std::map
<Use
*, std::vector
<std::vector
<ConstantExpr
*>>> &CEPaths
) {
81 for (Use
&U
: I
->operands()) {
82 // If the operand U is not a constant expression operand, then ignore it.
83 auto *CE2
= dyn_cast
<ConstantExpr
>(U
.get());
87 // Holds all reachable paths from CE2 to CE.
88 std::vector
<std::vector
<ConstantExpr
*>> Paths
;
90 // Collect all reachable paths from CE2 to CE.
91 std::vector
<ConstantExpr
*> Path
{CE2
};
92 std::vector
<std::vector
<ConstantExpr
*>> Stack
{Path
};
93 while (!Stack
.empty()) {
94 std::vector
<ConstantExpr
*> TPath
= Stack
.back();
96 auto *CE3
= TPath
.back();
99 Paths
.push_back(TPath
);
103 for (auto &UU
: CE3
->operands()) {
104 if (auto *CE4
= dyn_cast
<ConstantExpr
>(UU
.get())) {
105 std::vector
<ConstantExpr
*> NPath(TPath
.begin(), TPath
.end());
106 NPath
.push_back(CE4
);
107 Stack
.push_back(NPath
);
112 // Associate all the collected paths with U, and save it.