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