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(Instruction
*InsertPt
,
27 SmallVector
<Instruction
*, 4> NewInsts
;
28 if (auto *CE
= dyn_cast
<ConstantExpr
>(C
)) {
29 NewInsts
.push_back(CE
->getAsInstruction(InsertPt
));
30 } else if (isa
<ConstantStruct
>(C
) || isa
<ConstantArray
>(C
)) {
31 Value
*V
= PoisonValue::get(C
->getType());
32 for (auto [Idx
, Op
] : enumerate(C
->operands())) {
33 V
= InsertValueInst::Create(V
, Op
, Idx
, "", InsertPt
);
34 NewInsts
.push_back(cast
<Instruction
>(V
));
36 } else if (isa
<ConstantVector
>(C
)) {
37 Type
*IdxTy
= Type::getInt32Ty(C
->getContext());
38 Value
*V
= PoisonValue::get(C
->getType());
39 for (auto [Idx
, Op
] : enumerate(C
->operands())) {
40 V
= InsertElementInst::Create(V
, Op
, ConstantInt::get(IdxTy
, Idx
), "",
42 NewInsts
.push_back(cast
<Instruction
>(V
));
45 llvm_unreachable("Not an expandable user");
50 bool convertUsersOfConstantsToInstructions(ArrayRef
<Constant
*> Consts
) {
51 // Find all expandable direct users of Consts.
52 SmallVector
<Constant
*> Stack
;
53 for (Constant
*C
: Consts
)
54 for (User
*U
: C
->users())
55 if (isExpandableUser(U
))
56 Stack
.push_back(cast
<Constant
>(U
));
58 // Include transitive users.
59 SetVector
<Constant
*> ExpandableUsers
;
60 while (!Stack
.empty()) {
61 Constant
*C
= Stack
.pop_back_val();
62 if (!ExpandableUsers
.insert(C
))
65 for (auto *Nested
: C
->users())
66 if (isExpandableUser(Nested
))
67 Stack
.push_back(cast
<Constant
>(Nested
));
70 // Find all instructions that use any of the expandable users
71 SetVector
<Instruction
*> InstructionWorklist
;
72 for (Constant
*C
: ExpandableUsers
)
73 for (User
*U
: C
->users())
74 if (auto *I
= dyn_cast
<Instruction
>(U
))
75 InstructionWorklist
.insert(I
);
77 // Replace those expandable operands with instructions
79 while (!InstructionWorklist
.empty()) {
80 Instruction
*I
= InstructionWorklist
.pop_back_val();
81 DebugLoc Loc
= I
->getDebugLoc();
82 for (Use
&U
: I
->operands()) {
84 if (auto *Phi
= dyn_cast
<PHINode
>(I
)) {
85 BasicBlock
*BB
= Phi
->getIncomingBlock(U
);
86 BasicBlock::iterator It
= BB
->getFirstInsertionPt();
87 assert(It
!= BB
->end() && "Unexpected empty basic block");
91 if (auto *C
= dyn_cast
<Constant
>(U
.get())) {
92 if (ExpandableUsers
.contains(C
)) {
94 auto NewInsts
= expandUser(BI
, C
);
95 for (auto *NI
: NewInsts
)
97 InstructionWorklist
.insert(NewInsts
.begin(), NewInsts
.end());
98 U
.set(NewInsts
.back());
104 for (Constant
*C
: Consts
)
105 C
->removeDeadConstantUsers();