Issue 181273
Summary [SCCP] Crash on optimized codegen due to undefined if condition
Labels new issue
Assignees
Reporter namikukr-qc
    Hi,

When compiling code with optimization level higher than -O0, there's a crash in the following simple test:
```
#include <stdio.h>

int main() {
  puts("starting");
  goto test;
  int a = 1;
test: if (a == 1) {
    puts("undefined behavior");
 }
  puts("unreachable on any optimization level");
  return 0;
}
```
The condition in the if is undefined. Here is llvm IR for main, before IPSCCP:
```
define dso_local i32 @main() #0 {
entry:
  %call = call i32 @puts(ptr noundef @.str)
  br i1 undef, label %if.then, label %if.end

if.then:                                          ; preds = %entry
  %call1 = call i32 @puts(ptr noundef @.str.1)
  br label %if.end

if.end:                                           ; preds = %if.then, %entry
  %call2 = call i32 @puts(ptr noundef @.str.2)
  ret i32 0
}
```
After IPSCCP:
```
define dso_local i32 @main() #0 {
entry:
 %call = call i32 @puts(ptr noundef @.str)
  unreachable
}
```
It seems like anything after the if gets eaten away. I looked through `llvm/lib/Transforms/IPO/SCCP.cpp` and `llvm/lib/Transforms/Utils/SCCPSolver.cpp`, and the culprit seems to be the function `SCCPInstVisitor::getFeasibleSuccessors`, where it is determined that an if statement with an unknown condition has no successors. This domino-effects into any code in the same function succeeding the if not existing. 
Specifically, line 1265 in `SCCPSolver.cpp`:
```
      if (!BCValue.isUnknownOrUndef())
        Succs[0] = Succs[1] = true;
 return;
```
All feasible successors are marked executable in `SCCPInstVisitor::visitTerminator`:
```
  // Mark all feasible successors executable.
  for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i)
 if (SuccFeasible[i])
      markEdgeExecutable(BB, TI.getSuccessor(i));
```
If the condition is undefined, both successors are not marked executable, in which case this happens in `SCCP.cpp`:
```
 for (BasicBlock &BB : F) {
      if (!Solver.isBlockExecutable(&BB)) {
 LLVM_DEBUG(dbgs() << "  BasicBlock Dead:" << BB);
 ++NumDeadBlocks;

        MadeChanges = true;

        if (&BB != &F.front())
          BlocksToErase.push_back(&BB);
        continue;
 }
      ...

```
Since each succeeding block after the if is a successor of `if.end`, the entire remainder of the function vanishes.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to