xref: /freebsd/contrib/llvm-project/llvm/lib/IR/ReplaceConstant.cpp (revision 2c2ec6bbc9cc7762a250ffe903bda6c2e44d25ff)
1 //===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a utility function for replacing LLVM constant
10 // expressions by instructions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/IR/ReplaceConstant.h"
15 #include "llvm/ADT/SetVector.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Instructions.h"
18 
19 namespace llvm {
20 
21 static bool isExpandableUser(User *U) {
22   return isa<ConstantExpr>(U) || isa<ConstantAggregate>(U);
23 }
24 
25 static SmallVector<Instruction *, 4> expandUser(BasicBlock::iterator InsertPt,
26                                                 Constant *C) {
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));
37     }
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), "",
43                                     InsertPt);
44       NewInsts.push_back(cast<Instruction>(V));
45     }
46   } else {
47     llvm_unreachable("Not an expandable user");
48   }
49   return NewInsts;
50 }
51 
52 bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts,
53                                            Function *RestrictToFunc,
54                                            bool RemoveDeadConstants,
55                                            bool IncludeSelf) {
56   // Find all expandable direct users of Consts.
57   SmallVector<Constant *> Stack;
58   for (Constant *C : Consts) {
59     assert(!isa<ConstantData>(C) &&
60            "should not be expanding trivial constant users");
61 
62     if (IncludeSelf) {
63       assert(isExpandableUser(C) && "One of the constants is not expandable");
64       Stack.push_back(C);
65     } else {
66       for (User *U : C->users())
67         if (isExpandableUser(U))
68           Stack.push_back(cast<Constant>(U));
69     }
70   }
71 
72   // Include transitive users.
73   SetVector<Constant *> ExpandableUsers;
74   while (!Stack.empty()) {
75     Constant *C = Stack.pop_back_val();
76     if (!ExpandableUsers.insert(C))
77       continue;
78 
79     for (auto *Nested : C->users())
80       if (isExpandableUser(Nested))
81         Stack.push_back(cast<Constant>(Nested));
82   }
83 
84   // Find all instructions that use any of the expandable users
85   SetVector<Instruction *> InstructionWorklist;
86   for (Constant *C : ExpandableUsers)
87     for (User *U : C->users())
88       if (auto *I = dyn_cast<Instruction>(U))
89         if (!RestrictToFunc || I->getFunction() == RestrictToFunc)
90           InstructionWorklist.insert(I);
91 
92   // Replace those expandable operands with instructions
93   bool Changed = false;
94   while (!InstructionWorklist.empty()) {
95     Instruction *I = InstructionWorklist.pop_back_val();
96     DebugLoc Loc = I->getDebugLoc();
97     for (Use &U : I->operands()) {
98       BasicBlock::iterator BI = I->getIterator();
99       if (auto *Phi = dyn_cast<PHINode>(I)) {
100         BasicBlock *BB = Phi->getIncomingBlock(U);
101         BI = BB->getFirstInsertionPt();
102         assert(BI != BB->end() && "Unexpected empty basic block");
103       }
104 
105       if (auto *C = dyn_cast<Constant>(U.get())) {
106         if (ExpandableUsers.contains(C)) {
107           Changed = true;
108           auto NewInsts = expandUser(BI, C);
109           for (auto *NI : NewInsts)
110             NI->setDebugLoc(Loc);
111           InstructionWorklist.insert_range(NewInsts);
112           U.set(NewInsts.back());
113         }
114       }
115     }
116   }
117 
118   if (RemoveDeadConstants)
119     for (Constant *C : Consts)
120       C->removeDeadConstantUsers();
121 
122   return Changed;
123 }
124 
125 } // namespace llvm
126