Skip to content

Commit 4ad0aa7

Browse files
authored
[SSAUpdaterBulk] Add expectedly failing loop tests. (#131761)
These tests demonstrate the issue in SSAUpdaterBulk when it calculates incoming values from loop back edges. The failures are marked with `EXPECT_NONFATAL_FAILURE`, which is the way to designate an "expected fail" in the Google Test suite.
1 parent 1094ffc commit 4ad0aa7

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "llvm/IR/Instructions.h"
1515
#include "llvm/IR/LLVMContext.h"
1616
#include "llvm/IR/Module.h"
17+
#include "llvm/Support/SourceMgr.h"
18+
#include "gtest/gtest-spi.h"
1719
#include "gtest/gtest.h"
1820

1921
using namespace llvm;
@@ -192,3 +194,120 @@ TEST(SSAUpdaterBulk, Irreducible) {
192194
EXPECT_EQ(UpdatePhi->getIncomingValueForBlock(LoopStartBB), AddOp2);
193195
EXPECT_EQ(UpdatePhi->getIncomingValueForBlock(IfBB), UndefValue::get(I32Ty));
194196
}
197+
198+
TEST(SSAUpdaterBulk, SingleBBLoop) {
199+
const char *IR = R"(
200+
define void @main() {
201+
entry:
202+
br label %loop
203+
loop:
204+
%i = add i32 0, 1
205+
%cmp = icmp slt i32 %i, 42
206+
br i1 %cmp, label %loop, label %exit
207+
exit:
208+
ret void
209+
}
210+
)";
211+
212+
llvm::LLVMContext Context;
213+
llvm::SMDiagnostic Err;
214+
std::unique_ptr<llvm::Module> M = llvm::parseAssemblyString(IR, Err, Context);
215+
ASSERT_NE(M, nullptr) << "Failed to parse IR: " << Err.getMessage();
216+
217+
Function *F = M->getFunction("main");
218+
auto *Entry = &F->getEntryBlock();
219+
auto *Loop = Entry->getSingleSuccessor();
220+
auto *I = &Loop->front();
221+
222+
// Rewrite first operand of "%i = add i32 0, 1" to use incoming values entry:0
223+
// or loop:%i (that is the value of %i from the previous iteration).
224+
SSAUpdaterBulk Updater;
225+
Type *I32Ty = Type::getInt32Ty(Context);
226+
unsigned PrevI = Updater.AddVariable("i.prev", I32Ty);
227+
Updater.AddAvailableValue(PrevI, Entry, ConstantInt::get(I32Ty, 0));
228+
Updater.AddAvailableValue(PrevI, Loop, I);
229+
Updater.AddUse(PrevI, &I->getOperandUse(0));
230+
231+
SmallVector<PHINode *, 1> Inserted;
232+
DominatorTree DT(*F);
233+
Updater.RewriteAllUses(&DT, &Inserted);
234+
235+
#if 0 // Enable for debugging.
236+
Loop->dump();
237+
// Output:
238+
// loop: ; preds = %loop, %entry
239+
// %i.prev = phi i32 [ %i.prev, %loop ], [ 0, %entry ]
240+
// %i = add i32 %i.prev, 1
241+
// %cmp = icmp slt i32 %i, 42
242+
// br i1 %cmp, label %loop, label %exit
243+
#endif
244+
245+
ASSERT_EQ(Inserted.size(), 1u);
246+
PHINode *Phi = Inserted[0];
247+
EXPECT_EQ(Phi, dyn_cast<PHINode>(I->getOperand(0)));
248+
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
249+
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I),
250+
"Expected equality of these values");
251+
}
252+
253+
TEST(SSAUpdaterBulk, TwoBBLoop) {
254+
const char *IR = R"(
255+
define void @main() {
256+
entry:
257+
br label %loop_header
258+
loop_header:
259+
br label %loop
260+
loop:
261+
%i = add i32 0, 1
262+
%cmp = icmp slt i32 %i, 42
263+
br i1 %cmp, label %loop_header, label %exit
264+
exit:
265+
ret void
266+
}
267+
)";
268+
269+
llvm::LLVMContext Context;
270+
llvm::SMDiagnostic Err;
271+
std::unique_ptr<llvm::Module> M = llvm::parseAssemblyString(IR, Err, Context);
272+
ASSERT_NE(M, nullptr) << "Failed to parse IR: " << Err.getMessage();
273+
274+
Function *F = M->getFunction("main");
275+
auto *Entry = &F->getEntryBlock();
276+
auto *LoopHdr = Entry->getSingleSuccessor();
277+
auto *Loop = LoopHdr->getSingleSuccessor();
278+
auto *I = &Loop->front();
279+
280+
// Rewrite first operand of "%i = add i32 0, 1" to use incoming values entry:0
281+
// or loop:%i (that is the value of %i from the previous iteration).
282+
SSAUpdaterBulk Updater;
283+
Type *I32Ty = Type::getInt32Ty(Context);
284+
unsigned PrevI = Updater.AddVariable("i.prev", I32Ty);
285+
Updater.AddAvailableValue(PrevI, Entry, ConstantInt::get(I32Ty, 0));
286+
Updater.AddAvailableValue(PrevI, Loop, I);
287+
Updater.AddUse(PrevI, &I->getOperandUse(0));
288+
289+
SmallVector<PHINode *, 1> Inserted;
290+
DominatorTree DT(*F);
291+
Updater.RewriteAllUses(&DT, &Inserted);
292+
293+
#if 0 // Enable for debugging.
294+
LoopHdr->dump();
295+
Loop->dump();
296+
// Output:
297+
// loop_header: ; preds = %loop, %entry
298+
// %i.prev = phi i32 [ %i, %loop ], [ 0, %entry ]
299+
// br label %loop
300+
// loop: ; preds = %loop_header
301+
// %i = add i32 %i, 1
302+
// %cmp = icmp slt i32 %i, 42
303+
// br i1 %cmp, label %loop_header, label %exit
304+
#endif
305+
306+
ASSERT_EQ(Inserted.size(), 1u);
307+
PHINode *Phi = Inserted[0];
308+
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(Phi, dyn_cast<PHINode>(I->getOperand(0))),
309+
"Expected equality of these values");
310+
EXPECT_EQ(Phi->getParent(), LoopHdr);
311+
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
312+
EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I);
313+
}

0 commit comments

Comments
 (0)