Skip to content

[LoopInterchange] Can only replace phis iff the uses are in the loop nest exit or ... #163954

@sjoerdmeijer

Description

@sjoerdmeijer

This assert is triggered:

 assert(all_of(P.users(),
                  [OuterHeader, OuterExit, IncI, InnerHeader](User *U) {
                    return (cast<PHINode>(U)->getParent() == OuterHeader &&
                            IncI->getParent() == InnerHeader) ||
                           cast<PHINode>(U)->getParent() == OuterExit;
                  }) &&
           "Can only replace phis iff the uses are in the loop nest exit or "
           "the incoming value is defined in the inner header (it will "
           "dominate all loop blocks after interchanging)");

with this reproducer:

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-linux-gnu"

define void @_Z1cPA9_i() {
entry:
  br label %for.cond1.preheader

for.cond1.preheader:                              ; preds = %for.cond.cleanup3, %entry
  %.lcssa4950 = phi i8 [ 0, %entry ], [ %1, %for.cond.cleanup3 ]
  br label %for.body4

for.cond.cleanup:                                 ; preds = %for.cond.cleanup3
  ret void

for.cond.cleanup3:                                ; preds = %for.cond.cleanup11
  br i1 true, label %for.cond.cleanup, label %for.cond1.preheader

for.body4:                                        ; preds = %for.cond.cleanup11, %for.cond1.preheader
  %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.cond.cleanup11 ]
  %0 = phi i8 [ %.lcssa4950, %for.cond1.preheader ], [ %1, %for.cond.cleanup11 ]
  br label %for.cond13.preheader

for.cond13.preheader:                             ; preds = %for.cond13.preheader, %for.body4
  br i1 true, label %for.cond.cleanup11, label %for.cond13.preheader

for.cond.cleanup11:                               ; preds = %for.cond13.preheader
  %1 = or i8 %0, 0
  %indvars.iv.next = add i64 %indvars.iv, 1
  br i1 true, label %for.cond.cleanup3, label %for.body4

; uselistorder directives
  uselistorder i8 %1, { 1, 0 }
}

Compiled with:

-passes=loop-interchange -S -disable-output -loop-interchange-profitabilities=ignore

See also: https://godbolt.org/z/reccs67nE

The stack trace is:

opt: /root/llvm-project/llvm/lib/Transforms/Scalar/LoopInterchange.cpp:1808: void moveLCSSAPhis(llvm::BasicBlock*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::BasicBlock*, llvm::Loop*, llvm::LoopInfo*): Assertion `all_of(P.users(), [OuterHeader, OuterExit, IncI, InnerHeader](User *U) { return (cast<PHINode>(U)->getParent() == OuterHeader && IncI->getParent() == InnerHeader) || cast<PHINode>(U)->getParent() == OuterExit; }) && "Can only replace phis iff the uses are in the loop nest exit or " "the incoming value is defined in the inner header (it will " "dominate all loop blocks after interchanging)"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -passes=loop-interchange -S -disable-output -loop-interchange-profitabilities=ignore <source>
1.	Running pass "function(loop(loop-interchange))" on module "<source>"
2.	Running pass "loop(loop-interchange)" on function "_Z1cPA9_i"
 #0 0x0000000005955838 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5955838)
 #1 0x00000000059526e4 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #2 0x0000784442e42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x0000784442e969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
 #4 0x0000784442e42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
 #5 0x0000784442e287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
 #6 0x0000784442e2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
 #7 0x0000784442e39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
 #8 0x000000000469e345 (anonymous namespace)::LoopInterchangeTransform::transform(llvm::ArrayRef<llvm::Instruction*>) LoopInterchange.cpp:0:0

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions