Skip to content

Commit 367db01

Browse files
committed
ssaupdaterbulk_add_phi_optimization
1 parent 2f4e71a commit 367db01

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H
1414
#define LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H
1515

16-
#include "llvm/ADT/DenseMap.h"
1716
#include "llvm/ADT/StringRef.h"
1817
#include "llvm/IR/PredIteratorCache.h"
1918

@@ -77,6 +76,10 @@ class SSAUpdaterBulk {
7776
/// vector.
7877
void RewriteAllUses(DominatorTree *DT,
7978
SmallVectorImpl<PHINode *> *InsertedPHIs = nullptr);
79+
80+
/// Rewrite all uses and simplify the inserted PHI nodes.
81+
/// Use this method to preserve behavior when replacing SSAUpdater.
82+
void RewriteAndOptimizeAllUses(DominatorTree *DT);
8083
};
8184

8285
} // end namespace llvm

llvm/lib/Transforms/Utils/SSAUpdaterBulk.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/Transforms/Utils/SSAUpdaterBulk.h"
14+
#include "llvm/Analysis/InstructionSimplify.h"
1415
#include "llvm/Analysis/IteratedDominanceFrontier.h"
1516
#include "llvm/IR/BasicBlock.h"
1617
#include "llvm/IR/Dominators.h"
1718
#include "llvm/IR/IRBuilder.h"
18-
#include "llvm/IR/Instructions.h"
1919
#include "llvm/IR/Use.h"
2020
#include "llvm/IR/Value.h"
21+
#include "llvm/Transforms/Utils/Local.h"
2122

2223
using namespace llvm;
2324

@@ -222,3 +223,38 @@ void SSAUpdaterBulk::RewriteAllUses(DominatorTree *DT,
222223
}
223224
}
224225
}
226+
227+
// Perform a single pass of simplification over the worklist of PHIs.
228+
static void SimplifyPass(MutableArrayRef<PHINode *> Worklist) {
229+
if (Worklist.empty())
230+
return;
231+
232+
const DataLayout &DL = Worklist.front()->getParent()->getDataLayout();
233+
for (PHINode *&PHI : Worklist) {
234+
if (Value *Simplified = simplifyInstruction(PHI, DL)) {
235+
PHI->replaceAllUsesWith(Simplified);
236+
PHI->eraseFromParent();
237+
PHI = nullptr; // Mark as removed.
238+
}
239+
}
240+
}
241+
242+
static void DeduplicatePass(ArrayRef<PHINode *> Worklist) {
243+
SmallDenseMap<BasicBlock *, unsigned> BBs;
244+
for (PHINode *PHI : Worklist) {
245+
if (PHI)
246+
++BBs[PHI->getParent()];
247+
}
248+
249+
for (auto [BB, NumNewPHIs] : BBs) {
250+
auto FirstExistedPN = std::next(BB->phis().begin(), NumNewPHIs);
251+
EliminateNewDuplicatePHINodes(BB, FirstExistedPN);
252+
}
253+
}
254+
255+
void SSAUpdaterBulk::RewriteAndOptimizeAllUses(DominatorTree *DT) {
256+
SmallVector<PHINode *, 4> PHIs;
257+
RewriteAllUses(DT, &PHIs);
258+
SimplifyPass(PHIs);
259+
DeduplicatePass(PHIs);
260+
}

llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,70 @@ TEST(SSAUpdaterBulk, TwoBBLoop) {
308308
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
309309
EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I);
310310
}
311+
312+
TEST(SSAUpdaterBulk, SimplifyPHIs) {
313+
const char *IR = R"(
314+
define void @main(i32 %val, i1 %cond) {
315+
entry:
316+
br i1 %cond, label %left, label %right
317+
left:
318+
%add = add i32 %val, 1
319+
br label %exit
320+
right:
321+
%sub = sub i32 %val, 1
322+
br label %exit
323+
exit:
324+
%phi = phi i32 [ %sub, %right ], [ %add, %left ]
325+
%cmp = icmp slt i32 0, 42
326+
ret void
327+
}
328+
)";
329+
330+
llvm::LLVMContext Context;
331+
llvm::SMDiagnostic Err;
332+
std::unique_ptr<llvm::Module> M = llvm::parseAssemblyString(IR, Err, Context);
333+
ASSERT_NE(M, nullptr) << "Failed to parse IR: " << Err.getMessage();
334+
335+
Function *F = M->getFunction("main");
336+
auto *Entry = &F->getEntryBlock();
337+
auto *Left = Entry->getTerminator()->getSuccessor(0);
338+
auto *Right = Entry->getTerminator()->getSuccessor(1);
339+
auto *Exit = Left->getSingleSuccessor();
340+
auto *Val = &*F->arg_begin();
341+
auto *Phi = &Exit->front();
342+
auto *Cmp = &*std::next(Exit->begin());
343+
auto *Add = &Left->front();
344+
auto *Sub = &Right->front();
345+
346+
SSAUpdaterBulk Updater;
347+
Type *I32Ty = Type::getInt32Ty(Context);
348+
349+
// Use %val directly instead of creating a phi.
350+
unsigned ValVar = Updater.AddVariable("Val", I32Ty);
351+
Updater.AddAvailableValue(ValVar, Left, Val);
352+
Updater.AddAvailableValue(ValVar, Right, Val);
353+
Updater.AddUse(ValVar, &Cmp->getOperandUse(0));
354+
355+
// Use existing %phi for %add and %sub values.
356+
unsigned AddSubVar = Updater.AddVariable("AddSub", I32Ty);
357+
Updater.AddAvailableValue(AddSubVar, Left, Add);
358+
Updater.AddAvailableValue(AddSubVar, Right, Sub);
359+
Updater.AddUse(AddSubVar, &Cmp->getOperandUse(1));
360+
361+
auto ExitSizeBefore = Exit->size();
362+
DominatorTree DT(*F);
363+
Updater.RewriteAndOptimizeAllUses(&DT);
364+
365+
#if 0 // Enable for debugging.
366+
Exit->dump();
367+
// Output:
368+
// exit: ; preds = %right, %left
369+
// %phi = phi i32 [ %sub, %right ], [ %add, %left ]
370+
// %cmp = icmp slt i32 %val, %phi
371+
// ret void
372+
#endif
373+
EXPECT_EQ(Exit->size(), ExitSizeBefore);
374+
ASSERT_EQ(&Exit->front(), Phi);
375+
EXPECT_EQ(Val, Cmp->getOperand(0));
376+
EXPECT_EQ(Phi, Cmp->getOperand(1));
377+
}

0 commit comments

Comments
 (0)