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 Instruction *expandUser(Instruction *InsertPt, Constant *C) { 26 if (auto *CE = dyn_cast<ConstantExpr>(C)) { 27 return CE->getAsInstruction(InsertPt); 28 } else if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) { 29 Value *V = PoisonValue::get(C->getType()); 30 for (auto [Idx, Op] : enumerate(C->operands())) 31 V = InsertValueInst::Create(V, Op, Idx, "", InsertPt); 32 return cast<Instruction>(V); 33 } else if (isa<ConstantVector>(C)) { 34 Type *IdxTy = Type::getInt32Ty(C->getContext()); 35 Value *V = PoisonValue::get(C->getType()); 36 for (auto [Idx, Op] : enumerate(C->operands())) 37 V = InsertElementInst::Create(V, Op, ConstantInt::get(IdxTy, Idx), "", 38 InsertPt); 39 return cast<Instruction>(V); 40 } else { 41 llvm_unreachable("Not an expandable user"); 42 } 43 } 44 45 bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts) { 46 // Find all expandable direct users of Consts. 47 SmallVector<Constant *> Stack; 48 for (Constant *C : Consts) 49 for (User *U : C->users()) 50 if (isExpandableUser(U)) 51 Stack.push_back(cast<Constant>(U)); 52 53 // Include transitive users. 54 SetVector<Constant *> ExpandableUsers; 55 while (!Stack.empty()) { 56 Constant *C = Stack.pop_back_val(); 57 if (!ExpandableUsers.insert(C)) 58 continue; 59 60 for (auto *Nested : C->users()) 61 if (isExpandableUser(Nested)) 62 Stack.push_back(cast<Constant>(Nested)); 63 } 64 65 // Find all instructions that use any of the expandable users 66 SetVector<Instruction *> InstructionWorklist; 67 for (Constant *C : ExpandableUsers) 68 for (User *U : C->users()) 69 if (auto *I = dyn_cast<Instruction>(U)) 70 InstructionWorklist.insert(I); 71 72 // Replace those expandable operands with instructions 73 bool Changed = false; 74 while (!InstructionWorklist.empty()) { 75 Instruction *I = InstructionWorklist.pop_back_val(); 76 for (Use &U : I->operands()) { 77 auto *BI = I; 78 if (auto *Phi = dyn_cast<PHINode>(I)) { 79 BasicBlock *BB = Phi->getIncomingBlock(U); 80 BasicBlock::iterator It = BB->getFirstInsertionPt(); 81 assert(It != BB->end() && "Unexpected empty basic block"); 82 BI = &*It; 83 } 84 85 if (auto *C = dyn_cast<Constant>(U.get())) { 86 if (ExpandableUsers.contains(C)) { 87 Changed = true; 88 Instruction *NI = expandUser(BI, C); 89 InstructionWorklist.insert(NI); 90 U.set(NI); 91 } 92 } 93 } 94 } 95 96 for (Constant *C : Consts) 97 C->removeDeadConstantUsers(); 98 99 return Changed; 100 } 101 102 } // namespace llvm 103