The add from the IV in the inner loop was always checking for 2 uses, the phi and the compare. The compare could be based on the phi though, leaving one valid use of the compare. In the testcase we could be left with the phi and a lcssa phi as the two users, invalidly allowing flattening where we shouldn't. Fixes 58441 Differential Revision: https://reviews.llvm.org/D138404
100 lines
4.9 KiB
LLVM
100 lines
4.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes="loop-flatten" -verify-scev -S < %s | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
|
|
|
; This shouldn't flatten, as the inner add is used by a lcssa.
|
|
|
|
define i32 @test() {
|
|
; CHECK-LABEL: @test(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_I:%.*]]
|
|
; CHECK: for.cond1.preheader.i:
|
|
; CHECK-NEXT: [[L_011_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD6_I:%.*]], [[FOR_INC5_I:%.*]] ]
|
|
; CHECK-NEXT: br label [[WHILE_COND_I_PREHEADER_I:%.*]]
|
|
; CHECK: while.cond.i.preheader.i:
|
|
; CHECK-NEXT: [[STOREMERGE9_I:%.*]] = phi i32 [ 0, [[FOR_COND1_PREHEADER_I]] ], [ [[ADD_I:%.*]], [[WHILE_COND_I_PREHEADER_I]] ]
|
|
; CHECK-NEXT: [[ADD_I]] = add nuw nsw i32 [[STOREMERGE9_I]], 1
|
|
; CHECK-NEXT: [[CMP2_I:%.*]] = icmp ult i32 [[STOREMERGE9_I]], 5
|
|
; CHECK-NEXT: br i1 [[CMP2_I]], label [[WHILE_COND_I_PREHEADER_I]], label [[FOR_INC5_I]]
|
|
; CHECK: for.inc5.i:
|
|
; CHECK-NEXT: [[ADD_I_LCSSA:%.*]] = phi i32 [ [[ADD_I]], [[WHILE_COND_I_PREHEADER_I]] ]
|
|
; CHECK-NEXT: [[ADD6_I]] = add nuw nsw i32 [[L_011_I]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_I:%.*]] = icmp eq i32 [[ADD6_I]], 6
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_I]], label [[E_EXIT:%.*]], label [[FOR_COND1_PREHEADER_I]]
|
|
; CHECK: e.exit:
|
|
; CHECK-NEXT: [[ADD_I_LCSSA_LCSSA:%.*]] = phi i32 [ [[ADD_I_LCSSA]], [[FOR_INC5_I]] ]
|
|
; CHECK-NEXT: ret i32 [[ADD_I_LCSSA_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %for.cond1.preheader.i
|
|
|
|
for.cond1.preheader.i: ; preds = %for.inc5.i, %entry
|
|
%l.011.i = phi i32 [ 0, %entry ], [ %add6.i, %for.inc5.i ]
|
|
br label %while.cond.i.preheader.i
|
|
|
|
while.cond.i.preheader.i: ; preds = %while.cond.i.preheader.i, %for.cond1.preheader.i
|
|
%storemerge9.i = phi i32 [ 0, %for.cond1.preheader.i ], [ %add.i, %while.cond.i.preheader.i ]
|
|
%add.i = add nuw nsw i32 %storemerge9.i, 1
|
|
%cmp2.i = icmp ult i32 %storemerge9.i, 5
|
|
br i1 %cmp2.i, label %while.cond.i.preheader.i, label %for.inc5.i
|
|
|
|
for.inc5.i: ; preds = %while.cond.i.preheader.i
|
|
%add.i.lcssa = phi i32 [ %add.i, %while.cond.i.preheader.i ]
|
|
%add6.i = add nuw nsw i32 %l.011.i, 1
|
|
%exitcond.not.i = icmp eq i32 %add6.i, 6
|
|
br i1 %exitcond.not.i, label %e.exit, label %for.cond1.preheader.i
|
|
|
|
e.exit: ; preds = %for.inc5.i
|
|
%add.i.lcssa.lcssa = phi i32 [ %add.i.lcssa, %for.inc5.i ]
|
|
ret i32 %add.i.lcssa.lcssa
|
|
}
|
|
|
|
|
|
define i32 @test64() {
|
|
; CHECK-LABEL: @test64(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_I:%.*]]
|
|
; CHECK: for.cond1.preheader.i:
|
|
; CHECK-NEXT: [[L_011_I:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD6_I:%.*]], [[FOR_INC5_I:%.*]] ]
|
|
; CHECK-NEXT: br label [[WHILE_COND_I_PREHEADER_I:%.*]]
|
|
; CHECK: while.cond.i.preheader.i:
|
|
; CHECK-NEXT: [[STOREMERGE9_I:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_I]] ], [ [[ADD_I:%.*]], [[WHILE_COND_I_PREHEADER_I]] ]
|
|
; CHECK-NEXT: [[ADD_I]] = add nuw nsw i64 [[STOREMERGE9_I]], 1
|
|
; CHECK-NEXT: [[CMP2_I:%.*]] = icmp ult i64 [[STOREMERGE9_I]], 5
|
|
; CHECK-NEXT: br i1 [[CMP2_I]], label [[WHILE_COND_I_PREHEADER_I]], label [[FOR_INC5_I]]
|
|
; CHECK: for.inc5.i:
|
|
; CHECK-NEXT: [[ADD_I_LCSSA_WIDEN:%.*]] = phi i64 [ [[ADD_I]], [[WHILE_COND_I_PREHEADER_I]] ]
|
|
; CHECK-NEXT: [[ADD_I_LCSSA:%.*]] = trunc i64 [[ADD_I_LCSSA_WIDEN]] to i32
|
|
; CHECK-NEXT: [[ADD6_I]] = add nuw nsw i64 [[L_011_I]], 1
|
|
; CHECK-NEXT: [[EXITCOND_NOT_I:%.*]] = icmp eq i64 [[ADD6_I]], 6
|
|
; CHECK-NEXT: br i1 [[EXITCOND_NOT_I]], label [[E_EXIT:%.*]], label [[FOR_COND1_PREHEADER_I]]
|
|
; CHECK: e.exit:
|
|
; CHECK-NEXT: [[ADD_I_LCSSA_LCSSA:%.*]] = phi i32 [ [[ADD_I_LCSSA]], [[FOR_INC5_I]] ]
|
|
; CHECK-NEXT: ret i32 [[ADD_I_LCSSA_LCSSA]]
|
|
;
|
|
entry:
|
|
br label %for.cond1.preheader.i
|
|
|
|
for.cond1.preheader.i: ; preds = %for.inc5.i, %entry
|
|
%l.011.i = phi i64 [ 0, %entry ], [ %add6.i, %for.inc5.i ]
|
|
br label %while.cond.i.preheader.i
|
|
|
|
while.cond.i.preheader.i: ; preds = %while.cond.i.preheader.i, %for.cond1.preheader.i
|
|
%storemerge9.i = phi i64 [ 0, %for.cond1.preheader.i ], [ %add.i, %while.cond.i.preheader.i ]
|
|
%add.i = add nuw nsw i64 %storemerge9.i, 1
|
|
%cmp2.i = icmp ult i64 %storemerge9.i, 5
|
|
br i1 %cmp2.i, label %while.cond.i.preheader.i, label %for.inc5.i
|
|
|
|
for.inc5.i: ; preds = %while.cond.i.preheader.i
|
|
%add.i.lcssa.widen = phi i64 [ %add.i, %while.cond.i.preheader.i ]
|
|
%add.i.lcssa = trunc i64 %add.i.lcssa.widen to i32
|
|
%add6.i = add nuw nsw i64 %l.011.i, 1
|
|
%exitcond.not.i = icmp eq i64 %add6.i, 6
|
|
br i1 %exitcond.not.i, label %e.exit, label %for.cond1.preheader.i
|
|
|
|
e.exit: ; preds = %for.inc5.i
|
|
%add.i.lcssa.lcssa = phi i32 [ %add.i.lcssa, %for.inc5.i ]
|
|
ret i32 %add.i.lcssa.lcssa
|
|
}
|