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(Instruction *InsertPt, 26 Constant *C) { 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)); 35 } 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), "", 41 InsertPt); 42 NewInsts.push_back(cast<Instruction>(V)); 43 } 44 } else { 45 llvm_unreachable("Not an expandable user"); 46 } 47 return NewInsts; 48 } 49 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)); 57 58 // Include transitive users. 59 SetVector<Constant *> ExpandableUsers; 60 while (!Stack.empty()) { 61 Constant *C = Stack.pop_back_val(); 62 if (!ExpandableUsers.insert(C)) 63 continue; 64 65 for (auto *Nested : C->users()) 66 if (isExpandableUser(Nested)) 67 Stack.push_back(cast<Constant>(Nested)); 68 } 69 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); 76 77 // Replace those expandable operands with instructions 78 bool Changed = false; 79 while (!InstructionWorklist.empty()) { 80 Instruction *I = InstructionWorklist.pop_back_val(); 81 DebugLoc Loc = I->getDebugLoc(); 82 for (Use &U : I->operands()) { 83 auto *BI = I; 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"); 88 BI = &*It; 89 } 90 91 if (auto *C = dyn_cast<Constant>(U.get())) { 92 if (ExpandableUsers.contains(C)) { 93 Changed = true; 94 auto NewInsts = expandUser(BI, C); 95 for (auto *NI : NewInsts) 96 NI->setDebugLoc(Loc); 97 InstructionWorklist.insert(NewInsts.begin(), NewInsts.end()); 98 U.set(NewInsts.back()); 99 } 100 } 101 } 102 } 103 104 for (Constant *C : Consts) 105 C->removeDeadConstantUsers(); 106 107 return Changed; 108 } 109 110 } // namespace llvm 111