Skip to content

Commit 48ae614

Browse files
dtcxzywnikic
andauthored
[InstCombine] Avoid infinite loop when negating phi nodes (#104581)
Closes #96012 --------- Co-authored-by: Nikita Popov <[email protected]>
1 parent aad27bf commit 48ae614

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,11 +780,14 @@ class Negator final {
780780
using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>;
781781
BuilderTy Builder;
782782

783+
const DominatorTree &DT;
784+
783785
const bool IsTrulyNegation;
784786

785787
SmallDenseMap<Value *, Value *> NegationsCache;
786788

787-
Negator(LLVMContext &C, const DataLayout &DL, bool IsTrulyNegation);
789+
Negator(LLVMContext &C, const DataLayout &DL, const DominatorTree &DT,
790+
bool IsTrulyNegation);
788791

789792
#if LLVM_ENABLE_STATS
790793
unsigned NumValuesVisitedInThisNegator = 0;

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,14 @@ static cl::opt<unsigned>
9090
cl::desc("What is the maximal lookup depth when trying to "
9191
"check for viability of negation sinking."));
9292

93-
Negator::Negator(LLVMContext &C, const DataLayout &DL, bool IsTrulyNegation_)
93+
Negator::Negator(LLVMContext &C, const DataLayout &DL, const DominatorTree &DT_,
94+
bool IsTrulyNegation_)
9495
: Builder(C, TargetFolder(DL),
9596
IRBuilderCallbackInserter([&](Instruction *I) {
9697
++NegatorNumInstructionsCreatedTotal;
9798
NewInstructions.push_back(I);
9899
})),
99-
IsTrulyNegation(IsTrulyNegation_) {}
100+
DT(DT_), IsTrulyNegation(IsTrulyNegation_) {}
100101

101102
#if LLVM_ENABLE_STATS
102103
Negator::~Negator() {
@@ -309,6 +310,9 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
309310
auto *PHI = cast<PHINode>(I);
310311
SmallVector<Value *, 4> NegatedIncomingValues(PHI->getNumOperands());
311312
for (auto I : zip(PHI->incoming_values(), NegatedIncomingValues)) {
313+
// Don't negate indvars to avoid infinite loops.
314+
if (DT.dominates(PHI->getParent(), std::get<0>(I)))
315+
return nullptr;
312316
if (!(std::get<1>(I) =
313317
negate(std::get<0>(I), IsNSW, Depth + 1))) // Early return.
314318
return nullptr;
@@ -537,7 +541,8 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
537541
if (!NegatorEnabled || !DebugCounter::shouldExecute(NegatorCounter))
538542
return nullptr;
539543

540-
Negator N(Root->getContext(), IC.getDataLayout(), LHSIsZero);
544+
Negator N(Root->getContext(), IC.getDataLayout(), IC.getDominatorTree(),
545+
LHSIsZero);
541546
std::optional<Result> Res = N.run(Root, IsNSW);
542547
if (!Res) { // Negation failed.
543548
LLVM_DEBUG(dbgs() << "Negator: failed to sink negation into " << *Root
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
5+
6+
; Make sure we don't hang here.
7+
define i32 @pr96012() {
8+
; CHECK-LABEL: define i32 @pr96012() {
9+
; CHECK-NEXT: [[ENTRY:.*:]]
10+
; CHECK-NEXT: br label %[[FOR_COND:.*]]
11+
; CHECK: [[FOR_COND]]:
12+
; CHECK-NEXT: br label %[[FOR_COND]]
13+
;
14+
entry:
15+
br label %for.cond
16+
17+
for.cond:
18+
%indvar = phi i32 [ 1, %entry ], [ %shl, %for.cond ]
19+
%conv1 = trunc i32 %indvar to i8
20+
%neg = sub i8 0, %conv1
21+
%conv2 = zext i8 %neg to i32
22+
%shl = shl nuw i32 %conv2, 24
23+
br label %for.cond
24+
}

0 commit comments

Comments
 (0)