From 576060fb41c2de536a24d5d421b1cd8942f20b64 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 3 Mar 2023 16:07:43 +0100 Subject: [PATCH] [ReplaceConstant] Extract code for expanding users of constant (NFC) AMDGPU implements some handy code for expanding all constexpr users of LDS globals. Extract the core logic into ReplaceConstant, so that it can be reused elsewhere. --- llvm/include/llvm/IR/ReplaceConstant.h | 6 +++ llvm/lib/IR/ReplaceConstant.cpp | 58 ++++++++++++++++++++++ .../lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp | 58 ++-------------------- 3 files changed, 68 insertions(+), 54 deletions(-) diff --git a/llvm/include/llvm/IR/ReplaceConstant.h b/llvm/include/llvm/IR/ReplaceConstant.h index 1d6b10d..e074ca6 100644 --- a/llvm/include/llvm/IR/ReplaceConstant.h +++ b/llvm/include/llvm/IR/ReplaceConstant.h @@ -19,6 +19,8 @@ namespace llvm { +template class ArrayRef; +class Constant; class ConstantExpr; class Instruction; class Use; @@ -54,6 +56,10 @@ void collectConstantExprPaths( Instruction *I, ConstantExpr *CE, std::map>> &CEPaths); +/// Replace constant expressions users of the given constants with +/// instructions. Return whether anything was changed. +bool convertUsersOfConstantsToInstructions(ArrayRef Consts); + } // end namespace llvm #endif // LLVM_IR_REPLACECONSTANT_H diff --git a/llvm/lib/IR/ReplaceConstant.cpp b/llvm/lib/IR/ReplaceConstant.cpp index 069da26..5498830 100644 --- a/llvm/lib/IR/ReplaceConstant.cpp +++ b/llvm/lib/IR/ReplaceConstant.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/ReplaceConstant.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -133,4 +134,61 @@ void collectConstantExprPaths( } } +bool convertUsersOfConstantsToInstructions(ArrayRef Consts) { + // Find all ConstantExpr that are direct users Consts. + SmallVector Stack; + for (Constant *C : Consts) + for (User *U : C->users()) + if (ConstantExpr *CE = dyn_cast(U)) + Stack.push_back(CE); + + // Expand to include constexpr users of direct users + SetVector ConstExprUsers; + while (!Stack.empty()) { + ConstantExpr *V = Stack.pop_back_val(); + if (ConstExprUsers.contains(V)) + continue; + + ConstExprUsers.insert(V); + + for (auto *Nested : V->users()) + if (ConstantExpr *CE = dyn_cast(Nested)) + Stack.push_back(CE); + } + + // Find all instructions that use any of the ConstExpr users + SetVector InstructionWorklist; + for (ConstantExpr *CE : ConstExprUsers) + for (User *U : CE->users()) + if (auto *I = dyn_cast(U)) + InstructionWorklist.insert(I); + + // Replace those ConstExpr operands with instructions + bool Changed = false; + while (!InstructionWorklist.empty()) { + Instruction *I = InstructionWorklist.pop_back_val(); + for (Use &U : I->operands()) { + auto *BI = I; + if (auto *Phi = dyn_cast(I)) { + BasicBlock *BB = Phi->getIncomingBlock(U); + BasicBlock::iterator It = BB->getFirstInsertionPt(); + assert(It != BB->end() && "Unexpected empty basic block"); + BI = &*It; + } + + if (ConstantExpr *C = dyn_cast(U.get())) { + if (ConstExprUsers.contains(C)) { + Changed = true; + Instruction *NI = C->getAsInstruction(BI); + InstructionWorklist.insert(NI); + U.set(NI); + C->removeDeadConstantUsers(); + } + } + } + } + + return Changed; +} + } // namespace llvm diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index 34dc86e..0804fda 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -134,6 +134,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/ReplaceConstant.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" @@ -248,63 +249,12 @@ class AMDGPULowerModuleLDS : public ModulePass { // if (constantExprUsesLDS(Op)) // replaceConstantExprInFunction(I, Op); - bool Changed = false; - - // Find all ConstantExpr that are direct users of an LDS global - SmallVector Stack; + SmallVector LDSGlobals; for (auto &GV : M.globals()) if (AMDGPU::isLDSVariableToLower(GV)) - for (User *U : GV.users()) - if (ConstantExpr *C = dyn_cast(U)) - Stack.push_back(C); - - // Expand to include constexpr users of direct users - SetVector ConstExprUsersOfLDS; - while (!Stack.empty()) { - ConstantExpr *V = Stack.pop_back_val(); - if (ConstExprUsersOfLDS.contains(V)) - continue; - - ConstExprUsersOfLDS.insert(V); - - for (auto *Nested : V->users()) - if (ConstantExpr *CE = dyn_cast(Nested)) - Stack.push_back(CE); - } - - // Find all instructions that use any of the ConstExpr users of LDS - SetVector InstructionWorklist; - for (ConstantExpr *CE : ConstExprUsersOfLDS) - for (User *U : CE->users()) - if (auto *I = dyn_cast(U)) - InstructionWorklist.insert(I); - - // Replace those ConstExpr operands with instructions - while (!InstructionWorklist.empty()) { - Instruction *I = InstructionWorklist.pop_back_val(); - for (Use &U : I->operands()) { - - auto *BI = I; - if (auto *Phi = dyn_cast(I)) { - BasicBlock *BB = Phi->getIncomingBlock(U); - BasicBlock::iterator It = BB->getFirstInsertionPt(); - assert(It != BB->end() && "Unexpected empty basic block"); - BI = &(*(It)); - } + LDSGlobals.push_back(&GV); - if (ConstantExpr *C = dyn_cast(U.get())) { - if (ConstExprUsersOfLDS.contains(C)) { - Changed = true; - Instruction *NI = C->getAsInstruction(BI); - InstructionWorklist.insert(NI); - U.set(NI); - C->removeDeadConstantUsers(); - } - } - } - } - - return Changed; + return convertUsersOfConstantsToInstructions(LDSGlobals); } public: -- 2.7.4