xref: /llvm-project/llvm/lib/IR/ReplaceConstant.cpp (revision 5ef768d22bb33d9ab59a8ba9abe747bed9e068a2)
1622eaa4aSYaxun (Sam) Liu //===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===//
2622eaa4aSYaxun (Sam) Liu //
3622eaa4aSYaxun (Sam) Liu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4622eaa4aSYaxun (Sam) Liu // See https://llvm.org/LICENSE.txt for license information.
5622eaa4aSYaxun (Sam) Liu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6622eaa4aSYaxun (Sam) Liu //
7622eaa4aSYaxun (Sam) Liu //===----------------------------------------------------------------------===//
8622eaa4aSYaxun (Sam) Liu //
9622eaa4aSYaxun (Sam) Liu // This file implements a utility function for replacing LLVM constant
10622eaa4aSYaxun (Sam) Liu // expressions by instructions.
11622eaa4aSYaxun (Sam) Liu //
12622eaa4aSYaxun (Sam) Liu //===----------------------------------------------------------------------===//
13622eaa4aSYaxun (Sam) Liu 
14622eaa4aSYaxun (Sam) Liu #include "llvm/IR/ReplaceConstant.h"
15576060fbSNikita Popov #include "llvm/ADT/SetVector.h"
16a5bbc6efSBill Wendling #include "llvm/IR/Constants.h"
17622eaa4aSYaxun (Sam) Liu #include "llvm/IR/Instructions.h"
18622eaa4aSYaxun (Sam) Liu 
19622eaa4aSYaxun (Sam) Liu namespace llvm {
203af5f3e6Shsmahesha 
isExpandableUser(User * U)215b86eaebSNikita Popov static bool isExpandableUser(User *U) {
225b86eaebSNikita Popov   return isa<ConstantExpr>(U) || isa<ConstantAggregate>(U);
230317147aSNikita Popov }
240317147aSNikita Popov 
expandUser(BasicBlock::iterator InsertPt,Constant * C)259a96fb44SStephen Tozer static SmallVector<Instruction *, 4> expandUser(BasicBlock::iterator InsertPt,
26a3238969SWenju He                                                 Constant *C) {
27a3238969SWenju He   SmallVector<Instruction *, 4> NewInsts;
285b86eaebSNikita Popov   if (auto *CE = dyn_cast<ConstantExpr>(C)) {
299a96fb44SStephen Tozer     Instruction *ConstInst = CE->getAsInstruction();
309a96fb44SStephen Tozer     ConstInst->insertBefore(*InsertPt->getParent(), InsertPt);
319a96fb44SStephen Tozer     NewInsts.push_back(ConstInst);
325b86eaebSNikita Popov   } else if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) {
335b86eaebSNikita Popov     Value *V = PoisonValue::get(C->getType());
34a3238969SWenju He     for (auto [Idx, Op] : enumerate(C->operands())) {
355b86eaebSNikita Popov       V = InsertValueInst::Create(V, Op, Idx, "", InsertPt);
36a3238969SWenju He       NewInsts.push_back(cast<Instruction>(V));
37a3238969SWenju He     }
385b86eaebSNikita Popov   } else if (isa<ConstantVector>(C)) {
395b86eaebSNikita Popov     Type *IdxTy = Type::getInt32Ty(C->getContext());
405b86eaebSNikita Popov     Value *V = PoisonValue::get(C->getType());
41a3238969SWenju He     for (auto [Idx, Op] : enumerate(C->operands())) {
425b86eaebSNikita Popov       V = InsertElementInst::Create(V, Op, ConstantInt::get(IdxTy, Idx), "",
435b86eaebSNikita Popov                                     InsertPt);
44a3238969SWenju He       NewInsts.push_back(cast<Instruction>(V));
45a3238969SWenju He     }
465b86eaebSNikita Popov   } else {
475b86eaebSNikita Popov     llvm_unreachable("Not an expandable user");
485b86eaebSNikita Popov   }
49a3238969SWenju He   return NewInsts;
505b86eaebSNikita Popov }
515b86eaebSNikita Popov 
convertUsersOfConstantsToInstructions(ArrayRef<Constant * > Consts,Function * RestrictToFunc,bool RemoveDeadConstants,bool IncludeSelf)520aeaa2d9Sagozillon bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts,
530aeaa2d9Sagozillon                                            Function *RestrictToFunc,
54*5ef768d2SNikita Popov                                            bool RemoveDeadConstants,
55*5ef768d2SNikita Popov                                            bool IncludeSelf) {
565b86eaebSNikita Popov   // Find all expandable direct users of Consts.
575b86eaebSNikita Popov   SmallVector<Constant *> Stack;
58*5ef768d2SNikita Popov   for (Constant *C : Consts) {
59*5ef768d2SNikita Popov     if (IncludeSelf) {
60*5ef768d2SNikita Popov       assert(isExpandableUser(C) && "One of the constants is not expandable");
61*5ef768d2SNikita Popov       Stack.push_back(C);
62*5ef768d2SNikita Popov     } else {
635b86eaebSNikita Popov       for (User *U : C->users())
645b86eaebSNikita Popov         if (isExpandableUser(U))
655b86eaebSNikita Popov           Stack.push_back(cast<Constant>(U));
66*5ef768d2SNikita Popov     }
67*5ef768d2SNikita Popov   }
685b86eaebSNikita Popov 
695b86eaebSNikita Popov   // Include transitive users.
705b86eaebSNikita Popov   SetVector<Constant *> ExpandableUsers;
715b86eaebSNikita Popov   while (!Stack.empty()) {
725b86eaebSNikita Popov     Constant *C = Stack.pop_back_val();
735b86eaebSNikita Popov     if (!ExpandableUsers.insert(C))
745b86eaebSNikita Popov       continue;
755b86eaebSNikita Popov 
765b86eaebSNikita Popov     for (auto *Nested : C->users())
775b86eaebSNikita Popov       if (isExpandableUser(Nested))
785b86eaebSNikita Popov         Stack.push_back(cast<Constant>(Nested));
795b86eaebSNikita Popov   }
805b86eaebSNikita Popov 
815b86eaebSNikita Popov   // Find all instructions that use any of the expandable users
82576060fbSNikita Popov   SetVector<Instruction *> InstructionWorklist;
835b86eaebSNikita Popov   for (Constant *C : ExpandableUsers)
845b86eaebSNikita Popov     for (User *U : C->users())
85576060fbSNikita Popov       if (auto *I = dyn_cast<Instruction>(U))
860aeaa2d9Sagozillon         if (!RestrictToFunc || I->getFunction() == RestrictToFunc)
87576060fbSNikita Popov           InstructionWorklist.insert(I);
88576060fbSNikita Popov 
895b86eaebSNikita Popov   // Replace those expandable operands with instructions
90576060fbSNikita Popov   bool Changed = false;
91576060fbSNikita Popov   while (!InstructionWorklist.empty()) {
92576060fbSNikita Popov     Instruction *I = InstructionWorklist.pop_back_val();
93a3238969SWenju He     DebugLoc Loc = I->getDebugLoc();
94576060fbSNikita Popov     for (Use &U : I->operands()) {
959a96fb44SStephen Tozer       BasicBlock::iterator BI = I->getIterator();
96576060fbSNikita Popov       if (auto *Phi = dyn_cast<PHINode>(I)) {
97576060fbSNikita Popov         BasicBlock *BB = Phi->getIncomingBlock(U);
989a96fb44SStephen Tozer         BI = BB->getFirstInsertionPt();
999a96fb44SStephen Tozer         assert(BI != BB->end() && "Unexpected empty basic block");
100576060fbSNikita Popov       }
101576060fbSNikita Popov 
1025b86eaebSNikita Popov       if (auto *C = dyn_cast<Constant>(U.get())) {
1035b86eaebSNikita Popov         if (ExpandableUsers.contains(C)) {
104576060fbSNikita Popov           Changed = true;
105a3238969SWenju He           auto NewInsts = expandUser(BI, C);
106a3238969SWenju He           for (auto *NI : NewInsts)
107a3238969SWenju He             NI->setDebugLoc(Loc);
108a3238969SWenju He           InstructionWorklist.insert(NewInsts.begin(), NewInsts.end());
109a3238969SWenju He           U.set(NewInsts.back());
1105b86eaebSNikita Popov         }
1115b86eaebSNikita Popov       }
1125b86eaebSNikita Popov     }
1135b86eaebSNikita Popov   }
1145b86eaebSNikita Popov 
1150aeaa2d9Sagozillon   if (RemoveDeadConstants)
1165b86eaebSNikita Popov     for (Constant *C : Consts)
117576060fbSNikita Popov       C->removeDeadConstantUsers();
118576060fbSNikita Popov 
119576060fbSNikita Popov   return Changed;
120576060fbSNikita Popov }
121576060fbSNikita Popov 
122622eaa4aSYaxun (Sam) Liu } // namespace llvm
123