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