llvm / llvm/llvm-project

Infinite compile in InstCombine

Open
#182,475 2 comments 0 reactions 0 assignees View on GitHub
hang llvm:instcombine
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

InstCombine causes an infinite compile after https://github.com/llvm/llvm-project/pull/154336. The issue seems to be an oscillation between a new freeze being created in foldOpIntoPhi and then later in pushFreezeToPreventPoisonFromPropagating the same freeze is removed. Following is a snippet from the debug output:

```
IC: Visiting: %.fr = freeze i32 %71
...
ADD DEFERRED: %68 = freeze i32 %67
ADD DEFERRED: %72 = phi i32
IC: Replacing %.fr = freeze i32 %73
with %72 = phi i32 [ 52, %42 ], [ %68, %43 ]
...
ADD: %.fr = phi i32 [ 52, %42 ], [ %68, %43 ]
ADD: %68 = freeze i32 %67
IC: Visiting: %68 = freeze i32 %67
...
IC: Replacing %68 = freeze i32 %67
with %67 = select i1 %65, i32 54, i32 %66
IC: ERASE %68 = freeze i32 %67
ADD DEFERRED: %.fr = phi i32 [ 52, %42 ], [ %67, %43 ]
...
IC: Visiting: %.fr1 = freeze i32 %.fr
...
IC: Replacing %.fr1 = freeze i32 %72
with %.fr = phi i32 [ 52, %42 ], [ %68, %43 ]
...
ADD: %68 = freeze i32 %67
IC: Visiting: %68 = freeze i32 %67
IC: Replacing %68 = freeze i32 %67
with %67 = select i1 %65, i32 54, i32 %66
IC: ERASE %68 = freeze i32 %67
```

This issue was found while running spec2000/crafty with Ofast and thin-lto (in the function InitializeRandomHash from evaluate.c during the lto step).

I have been trying to get a reduced test case but I haven't had much success there. I currently have the following patch for this which I will be uploading soon after some testing:

```
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c4beacdd1268..3a44253f8ecb 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1980,6 +1980,12 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN,
Value *InVal = PN->getIncomingValue(i);
BasicBlock *InBB = PN->getIncomingBlock(i);

+ // Avoid repeatedly sinking a freeze into a PHI only for some of the newly
+ // created incoming freezes to be trivially removable again. That pattern
+ // can cause oscillation between freeze(phi(...)) and phi(..., freeze(x), ...).
+ if (isa(&I) && isGuaranteedNotToBeUndefOrPoison(InVal))
+ return nullptr;
+
if (auto *NewVal = simplifyInstructionWithPHI(I, PN, InVal, InBB, DL, SQ)) {
NewPhiValues.push_back(NewVal);
continue;
@@ -5214,6 +5220,11 @@ InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating(FreezeInst &OrigFI) {
if (!isa(V) || isa(V))
return false;

+ // Don't push through an existing freeze. Otherwise we can repeatedly
+ // create redundant freeze instructions during instcombine iterations.
+ if (isa(V))
+ return false;
+
// We can't push the freeze through an instruction which can itself create
// poison. If the only source of new poison is flags, we can simply
```

Contributor guide

Open the contributing guide

Research direction

Start in llvm/lib/Transforms/InstCombine/InstructionCombining.cpp, focusing on foldOpIntoPhi and pushFreezeToPreventPoisonFromPropagating. Reproduce the issue with spec2000/crafty using Ofast and thin-LTO, then inspect the InstCombine debug output for the freeze oscillation. Done means the infinite compile no longer occurs and the affected compilation completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.