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/ADT/SetVector.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Instructions.h"
21 static bool isExpandableUser(User
*U
) {
22 return isa
<ConstantExpr
>(U
) || isa
<ConstantAggregate
>(U
);
25 static SmallVector
<Instruction
*, 4> expandUser(BasicBlock::iterator InsertPt
,
27 SmallVector
<Instruction
*, 4> NewInsts
;
28 if (auto *CE
= dyn_cast
<ConstantExpr
>(C
)) {
29 Instruction
*ConstInst
= CE
->getAsInstruction();
30 ConstInst
->insertBefore(*InsertPt
->getParent(), InsertPt
);
31 NewInsts
.push_back(ConstInst
);
32 } else if (isa
<ConstantStruct
>(C
) || isa
<ConstantArray
>(C
)) {
33 Value
*V
= PoisonValue::get(C
->getType());
34 for (auto [Idx
, Op
] : enumerate(C
->operands())) {
35 V
= InsertValueInst::Create(V
, Op
, Idx
, "", InsertPt
);
36 NewInsts
.push_back(cast
<Instruction
>(V
));
38 } else if (isa
<ConstantVector
>(C
)) {
39 Type
*IdxTy
= Type::getInt32Ty(C
->getContext());
40 Value
*V
= PoisonValue::get(C
->getType());
41 for (auto [Idx
, Op
] : enumerate(C
->operands())) {
42 V
= InsertElementInst::Create(V
, Op
, ConstantInt::get(IdxTy
, Idx
), "",
44 NewInsts
.push_back(cast
<Instruction
>(V
));
47 llvm_unreachable("Not an expandable user");
52 bool convertUsersOfConstantsToInstructions(ArrayRef
<Constant
*> Consts
,
53 Function
*RestrictToFunc
,
54 bool RemoveDeadConstants
,
56 // Find all expandable direct users of Consts.
57 SmallVector
<Constant
*> Stack
;
58 for (Constant
*C
: Consts
) {
60 assert(isExpandableUser(C
) && "One of the constants is not expandable");
63 for (User
*U
: C
->users())
64 if (isExpandableUser(U
))
65 Stack
.push_back(cast
<Constant
>(U
));
69 // Include transitive users.
70 SetVector
<Constant
*> ExpandableUsers
;
71 while (!Stack
.empty()) {
72 Constant
*C
= Stack
.pop_back_val();
73 if (!ExpandableUsers
.insert(C
))
76 for (auto *Nested
: C
->users())
77 if (isExpandableUser(Nested
))
78 Stack
.push_back(cast
<Constant
>(Nested
));
81 // Find all instructions that use any of the expandable users
82 SetVector
<Instruction
*> InstructionWorklist
;
83 for (Constant
*C
: ExpandableUsers
)
84 for (User
*U
: C
->users())
85 if (auto *I
= dyn_cast
<Instruction
>(U
))
86 if (!RestrictToFunc
|| I
->getFunction() == RestrictToFunc
)
87 InstructionWorklist
.insert(I
);
89 // Replace those expandable operands with instructions
91 while (!InstructionWorklist
.empty()) {
92 Instruction
*I
= InstructionWorklist
.pop_back_val();
93 DebugLoc Loc
= I
->getDebugLoc();
94 for (Use
&U
: I
->operands()) {
95 BasicBlock::iterator BI
= I
->getIterator();
96 if (auto *Phi
= dyn_cast
<PHINode
>(I
)) {
97 BasicBlock
*BB
= Phi
->getIncomingBlock(U
);
98 BI
= BB
->getFirstInsertionPt();
99 assert(BI
!= BB
->end() && "Unexpected empty basic block");
102 if (auto *C
= dyn_cast
<Constant
>(U
.get())) {
103 if (ExpandableUsers
.contains(C
)) {
105 auto NewInsts
= expandUser(BI
, C
);
106 for (auto *NI
: NewInsts
)
107 NI
->setDebugLoc(Loc
);
108 InstructionWorklist
.insert(NewInsts
.begin(), NewInsts
.end());
109 U
.set(NewInsts
.back());
115 if (RemoveDeadConstants
)
116 for (Constant
*C
: Consts
)
117 C
->removeDeadConstantUsers();