1e8d8bef9SDimitry Andric //===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9e8d8bef9SDimitry Andric // This file implements a utility function for replacing LLVM constant 10e8d8bef9SDimitry Andric // expressions by instructions. 11e8d8bef9SDimitry Andric // 12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 13e8d8bef9SDimitry Andric 14e8d8bef9SDimitry Andric #include "llvm/IR/ReplaceConstant.h" 1506c3fb27SDimitry Andric #include "llvm/ADT/SetVector.h" 1681ad6265SDimitry Andric #include "llvm/IR/Constants.h" 17e8d8bef9SDimitry Andric #include "llvm/IR/Instructions.h" 18e8d8bef9SDimitry Andric 19e8d8bef9SDimitry Andric namespace llvm { 20fe6060f1SDimitry Andric 2106c3fb27SDimitry Andric static bool isExpandableUser(User *U) { 2206c3fb27SDimitry Andric return isa<ConstantExpr>(U) || isa<ConstantAggregate>(U); 23fe6060f1SDimitry Andric } 24fe6060f1SDimitry Andric 25*5f757f3fSDimitry Andric static SmallVector<Instruction *, 4> expandUser(Instruction *InsertPt, 26*5f757f3fSDimitry Andric Constant *C) { 27*5f757f3fSDimitry Andric SmallVector<Instruction *, 4> NewInsts; 2806c3fb27SDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(C)) { 29*5f757f3fSDimitry Andric NewInsts.push_back(CE->getAsInstruction(InsertPt)); 3006c3fb27SDimitry Andric } else if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) { 3106c3fb27SDimitry Andric Value *V = PoisonValue::get(C->getType()); 32*5f757f3fSDimitry Andric for (auto [Idx, Op] : enumerate(C->operands())) { 3306c3fb27SDimitry Andric V = InsertValueInst::Create(V, Op, Idx, "", InsertPt); 34*5f757f3fSDimitry Andric NewInsts.push_back(cast<Instruction>(V)); 35*5f757f3fSDimitry Andric } 3606c3fb27SDimitry Andric } else if (isa<ConstantVector>(C)) { 3706c3fb27SDimitry Andric Type *IdxTy = Type::getInt32Ty(C->getContext()); 3806c3fb27SDimitry Andric Value *V = PoisonValue::get(C->getType()); 39*5f757f3fSDimitry Andric for (auto [Idx, Op] : enumerate(C->operands())) { 4006c3fb27SDimitry Andric V = InsertElementInst::Create(V, Op, ConstantInt::get(IdxTy, Idx), "", 4106c3fb27SDimitry Andric InsertPt); 42*5f757f3fSDimitry Andric NewInsts.push_back(cast<Instruction>(V)); 43*5f757f3fSDimitry Andric } 4406c3fb27SDimitry Andric } else { 4506c3fb27SDimitry Andric llvm_unreachable("Not an expandable user"); 4606c3fb27SDimitry Andric } 47*5f757f3fSDimitry Andric return NewInsts; 4806c3fb27SDimitry Andric } 49349cc55cSDimitry Andric 5006c3fb27SDimitry Andric bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts) { 5106c3fb27SDimitry Andric // Find all expandable direct users of Consts. 5206c3fb27SDimitry Andric SmallVector<Constant *> Stack; 5306c3fb27SDimitry Andric for (Constant *C : Consts) 5406c3fb27SDimitry Andric for (User *U : C->users()) 5506c3fb27SDimitry Andric if (isExpandableUser(U)) 5606c3fb27SDimitry Andric Stack.push_back(cast<Constant>(U)); 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric // Include transitive users. 5906c3fb27SDimitry Andric SetVector<Constant *> ExpandableUsers; 6006c3fb27SDimitry Andric while (!Stack.empty()) { 6106c3fb27SDimitry Andric Constant *C = Stack.pop_back_val(); 6206c3fb27SDimitry Andric if (!ExpandableUsers.insert(C)) 63fe6060f1SDimitry Andric continue; 64fe6060f1SDimitry Andric 6506c3fb27SDimitry Andric for (auto *Nested : C->users()) 6606c3fb27SDimitry Andric if (isExpandableUser(Nested)) 6706c3fb27SDimitry Andric Stack.push_back(cast<Constant>(Nested)); 6806c3fb27SDimitry Andric } 6906c3fb27SDimitry Andric 7006c3fb27SDimitry Andric // Find all instructions that use any of the expandable users 7106c3fb27SDimitry Andric SetVector<Instruction *> InstructionWorklist; 7206c3fb27SDimitry Andric for (Constant *C : ExpandableUsers) 7306c3fb27SDimitry Andric for (User *U : C->users()) 7406c3fb27SDimitry Andric if (auto *I = dyn_cast<Instruction>(U)) 7506c3fb27SDimitry Andric InstructionWorklist.insert(I); 7606c3fb27SDimitry Andric 7706c3fb27SDimitry Andric // Replace those expandable operands with instructions 7806c3fb27SDimitry Andric bool Changed = false; 7906c3fb27SDimitry Andric while (!InstructionWorklist.empty()) { 8006c3fb27SDimitry Andric Instruction *I = InstructionWorklist.pop_back_val(); 81*5f757f3fSDimitry Andric DebugLoc Loc = I->getDebugLoc(); 8206c3fb27SDimitry Andric for (Use &U : I->operands()) { 83fe6060f1SDimitry Andric auto *BI = I; 84fe6060f1SDimitry Andric if (auto *Phi = dyn_cast<PHINode>(I)) { 85fe6060f1SDimitry Andric BasicBlock *BB = Phi->getIncomingBlock(U); 8606c3fb27SDimitry Andric BasicBlock::iterator It = BB->getFirstInsertionPt(); 8706c3fb27SDimitry Andric assert(It != BB->end() && "Unexpected empty basic block"); 8806c3fb27SDimitry Andric BI = &*It; 89fe6060f1SDimitry Andric } 90fe6060f1SDimitry Andric 9106c3fb27SDimitry Andric if (auto *C = dyn_cast<Constant>(U.get())) { 9206c3fb27SDimitry Andric if (ExpandableUsers.contains(C)) { 9306c3fb27SDimitry Andric Changed = true; 94*5f757f3fSDimitry Andric auto NewInsts = expandUser(BI, C); 95*5f757f3fSDimitry Andric for (auto *NI : NewInsts) 96*5f757f3fSDimitry Andric NI->setDebugLoc(Loc); 97*5f757f3fSDimitry Andric InstructionWorklist.insert(NewInsts.begin(), NewInsts.end()); 98*5f757f3fSDimitry Andric U.set(NewInsts.back()); 99349cc55cSDimitry Andric } 100e8d8bef9SDimitry Andric } 101e8d8bef9SDimitry Andric } 102fe6060f1SDimitry Andric } 103349cc55cSDimitry Andric 10406c3fb27SDimitry Andric for (Constant *C : Consts) 10506c3fb27SDimitry Andric C->removeDeadConstantUsers(); 106fe6060f1SDimitry Andric 10706c3fb27SDimitry Andric return Changed; 108fe6060f1SDimitry Andric } 109fe6060f1SDimitry Andric 110e8d8bef9SDimitry Andric } // namespace llvm 111