Skip to content

Commit d82945c

Browse files
author
v01dxyz
committed
(Draft) [SCEV] forgetValue: support (extractvalue 0, (with-overflow-inst op0, op1))
Without that, forgetValue stops at (with-overflow-inst op0, op1) while thanks to MatchBinaryOp, SCEV creation considers %extractvalue as if it is (op op0, op1). Because of that, it creates an unclearable SCEV value that could possibly turn out of sync after a transform is applied. The commit is in Draft as the fix is not satisfactory (code duplication, do we push EVO to Visited ?). Meant for discussion and for adding a test.
1 parent c2fe75f commit d82945c

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8412,8 +8412,34 @@ void ScalarEvolution::visitAndClearUsers(
84128412
SmallVectorImpl<const SCEV *> &ToForget) {
84138413
while (!Worklist.empty()) {
84148414
Instruction *I = Worklist.pop_back_val();
8415-
if (!isSCEVable(I->getType()))
8415+
if (!isSCEVable(I->getType())) {
8416+
// detect if a user is matching the pattern
8417+
// extractvalue 0, (with-overflow-inst op1, op2))
8418+
auto *WO = dyn_cast<WithOverflowInst>(I);
8419+
if (!WO)
8420+
continue;
8421+
8422+
for (auto *WOUser : WO->users()) {
8423+
auto *EVO = dyn_cast<ExtractValueInst>(WOUser);
8424+
8425+
if (!EVO)
8426+
continue;
8427+
8428+
if (EVO->getNumIndices() != 1 || EVO->getIndices()[0] != 0)
8429+
continue;
8430+
8431+
ValueExprMapType::iterator It =
8432+
ValueExprMap.find_as(static_cast<Value *>(EVO));
8433+
if (It != ValueExprMap.end()) {
8434+
eraseValueFromMap(It->first);
8435+
ToForget.push_back(It->second);
8436+
}
8437+
8438+
PushDefUseChildren(EVO, Worklist, Visited);
8439+
}
8440+
84168441
continue;
8442+
}
84178443

84188444
ValueExprMapType::iterator It =
84198445
ValueExprMap.find_as(static_cast<Value *>(I));

llvm/unittests/Analysis/ScalarEvolutionTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,4 +1589,40 @@ TEST_F(ScalarEvolutionsTest, ApplyLoopGuards) {
15891589
});
15901590
}
15911591

1592+
TEST_F(ScalarEvolutionsTest, ForgetValueWithOverflowInst) {
1593+
LLVMContext C;
1594+
SMDiagnostic Err;
1595+
std::unique_ptr<Module> M = parseAssemblyString(
1596+
"declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) "
1597+
"define void @foo(i32 %i) { "
1598+
"entry: "
1599+
" br label %loop.body "
1600+
"loop.body: "
1601+
" %iv = phi i32 [ %iv.next, %loop.body ], [ 0, %entry ] "
1602+
" %iv.next = add nsw i32 %iv, 1 "
1603+
" %call = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %iv, i32 -2) "
1604+
" %extractvalue = extractvalue {i32, i1} %call, 0 "
1605+
" %cmp = icmp eq i32 %iv.next, 16 "
1606+
" br i1 %cmp, label %exit, label %loop.body "
1607+
"exit: "
1608+
" ret void "
1609+
"} ",
1610+
Err, C);
1611+
1612+
ASSERT_TRUE(M && "Could not parse module?");
1613+
ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
1614+
1615+
runWithSE(*M, "foo", [](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
1616+
auto *ExtractValue = getInstructionByName(F, "extractvalue");
1617+
auto *IV = getInstructionByName(F, "iv");
1618+
1619+
auto *ExtractValueScev = SE.getSCEV(ExtractValue);
1620+
EXPECT_NE(ExtractValueScev, nullptr);
1621+
1622+
SE.forgetValue(IV);
1623+
auto *ExtractValueScevForgotten = SE.getExistingSCEV(ExtractValue);
1624+
EXPECT_EQ(ExtractValueScevForgotten, nullptr);
1625+
});
1626+
}
1627+
15921628
} // end namespace llvm

0 commit comments

Comments
 (0)