From 6bda53c5914ac4d9fc86754283c080125528fa4a Mon Sep 17 00:00:00 2001 From: Serguei Katkov Date: Mon, 3 Apr 2023 22:53:11 +0700 Subject: [PATCH] [GuardWidening] Re-factor freezeAndPush. Re-write the code to avoid iteration over users of constants and global values. Reviewed By: mkazantsev Differential Revision: https://reviews.llvm.org/D147450 --- llvm/lib/Transforms/Scalar/GuardWidening.cpp | 42 ++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp index fef3347..62b40a2 100644 --- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -593,10 +593,35 @@ Value *GuardWideningImpl::freezeAndPush(Value *Orig, Instruction *InsertPt) { Instruction *InsertPtAtDef = getFreezeInsertPt(Orig, DT); if (!InsertPtAtDef) return new FreezeInst(Orig, "gw.freeze", InsertPt); + if (isa(Orig) || isa(Orig)) + return new FreezeInst(Orig, "gw.freeze", InsertPtAtDef); + SmallSet Visited; SmallVector Worklist; SmallSet DropPoisonFlags; SmallVector NeedFreeze; + DenseMap CacheOfFreezes; + + // A bit overloaded data structures. Visited contains constant/GV + // if we already met it. In this case CacheOfFreezes has a freeze if it is + // required. + auto handleConstantOrGlobal = [&](Use &U) { + Value *Def = U.get(); + if (!isa(Def) && !isa(Def)) + return false; + + if (Visited.insert(Def).second) { + if (isGuaranteedNotToBePoison(Def, nullptr, InsertPt, &DT)) + return true; + CacheOfFreezes[Def] = new FreezeInst(Def, Def->getName() + ".gw.fr", + getFreezeInsertPt(Def, DT)); + } + + if (CacheOfFreezes.count(Def)) + U.set(CacheOfFreezes[Def]); + return true; + }; + Worklist.push_back(Orig); while (!Worklist.empty()) { Value *V = Worklist.pop_back_val(); @@ -621,29 +646,22 @@ Value *GuardWideningImpl::freezeAndPush(Value *Orig, Instruction *InsertPt) { continue; } DropPoisonFlags.insert(I); - append_range(Worklist, I->operands()); + for (Use &U : I->operands()) + if (!handleConstantOrGlobal(U)) + Worklist.push_back(U.get()); } for (Instruction *I : DropPoisonFlags) I->dropPoisonGeneratingFlagsAndMetadata(); Value *Result = Orig; - SmallPtrSet NeedFreezeSet(NeedFreeze.begin(), NeedFreeze.end()); for (Value *V : NeedFreeze) { auto *FreezeInsertPt = getFreezeInsertPt(V, DT); FreezeInst *FI = new FreezeInst(V, V->getName() + ".gw.fr", FreezeInsertPt); ++FreezeAdded; if (V == Orig) Result = FI; - if (isa(V) || isa(V)) - V->replaceUsesWithIf( - FI, [&](const Use & U)->bool { return U.getUser() != FI; }); - else - // if it is a constant or global, just make a change only in instructions - // we visited and which are not marked as NeedFreeze itself. - V->replaceUsesWithIf(FI, [&](const Use & U)->bool { - return U.getUser() != FI && Visited.contains(U) && - !NeedFreezeSet.count(U); - }); + V->replaceUsesWithIf( + FI, [&](const Use & U)->bool { return U.getUser() != FI; }); } return Result; -- 2.7.4