Skip to content

Commit d73684e

Browse files
committed
[LoopFlatten] Fix crash if the inner loop trip count comes from a sext instruction.
If we look through a truncate in matchLinearIVUser, it's possible we find a sext/zext instruction that didn't come from widening. This will fail the MatchedItCount->getType() == InnerInductionPHI->getType() assertion. Fix this by checking that we did not look through a truncate already. Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D127149
1 parent fdd5843 commit d73684e

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

llvm/lib/Transforms/Scalar/LoopFlatten.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,9 @@ struct FlattenInfo {
211211
if (!MatchedItCount)
212212
return false;
213213

214-
// Look through extends if the IV has been widened.
215-
if (Widened &&
214+
// Look through extends if the IV has been widened. Don't look through
215+
// extends if we already looked through a trunc.
216+
if (Widened && IsAdd &&
216217
(isa<SExtInst>(MatchedItCount) || isa<ZExtInst>(MatchedItCount))) {
217218
assert(MatchedItCount->getType() == InnerInductionPHI->getType() &&
218219
"Unexpected type mismatch in types after widening");

llvm/test/Transforms/LoopFlatten/widen-iv.ll

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,83 @@ i.loopdone:
755755
ret i32 0
756756
}
757757

758+
; Same as @foo, but M is sext from i16. This used to assert because we thought
759+
; this sext was from widening and try to look through it.
760+
define void @foo_M_sext(i32* %A, i32 %N, i16 %M) {
761+
; CHECK-LABEL: @foo_M_sext(
762+
; CHECK-NEXT: entry:
763+
; CHECK-NEXT: [[M2:%.*]] = sext i16 [[M:%.*]] to i32
764+
; CHECK-NEXT: [[CMP17:%.*]] = icmp sgt i32 [[N:%.*]], 0
765+
; CHECK-NEXT: br i1 [[CMP17]], label [[FOR_COND1_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]]
766+
; CHECK: for.cond1.preheader.lr.ph:
767+
; CHECK-NEXT: [[CMP215:%.*]] = icmp sgt i32 [[M2]], 0
768+
; CHECK-NEXT: br i1 [[CMP215]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND_CLEANUP]]
769+
; CHECK: for.cond1.preheader.us.preheader:
770+
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[M2]] to i64
771+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[N]] to i64
772+
; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]]
773+
; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]]
774+
; CHECK: for.cond1.preheader.us:
775+
; CHECK-NEXT: [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ]
776+
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR1]] to i32
777+
; CHECK-NEXT: [[MUL_US:%.*]] = mul nsw i32 [[TMP2]], [[M2]]
778+
; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR1]] to i32
779+
; CHECK-NEXT: br label [[FOR_BODY4_US:%.*]]
780+
; CHECK: for.body4.us:
781+
; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ]
782+
; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i32
783+
; CHECK-NEXT: [[ADD_US:%.*]] = add nsw i32 [[TMP3]], [[MUL_US]]
784+
; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[FLATTEN_TRUNCIV]] to i64
785+
; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM_US]]
786+
; CHECK-NEXT: tail call void @f(i32* [[ARRAYIDX_US]])
787+
; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1
788+
; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]]
789+
; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]]
790+
; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us:
791+
; CHECK-NEXT: [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1
792+
; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]]
793+
; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]]
794+
; CHECK: for.cond.cleanup.loopexit:
795+
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
796+
; CHECK: for.cond.cleanup:
797+
; CHECK-NEXT: ret void
798+
;
799+
entry:
800+
%M2 = sext i16 %M to i32
801+
%cmp17 = icmp sgt i32 %N, 0
802+
br i1 %cmp17, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup
803+
804+
for.cond1.preheader.lr.ph:
805+
%cmp215 = icmp sgt i32 %M2, 0
806+
br i1 %cmp215, label %for.cond1.preheader.us.preheader, label %for.cond.cleanup
807+
808+
for.cond1.preheader.us.preheader:
809+
br label %for.cond1.preheader.us
810+
811+
for.cond1.preheader.us:
812+
%i.018.us = phi i32 [ %inc6.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %for.cond1.preheader.us.preheader ]
813+
%mul.us = mul nsw i32 %i.018.us, %M2
814+
br label %for.body4.us
815+
816+
for.body4.us:
817+
%j.016.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ]
818+
%add.us = add nsw i32 %j.016.us, %mul.us
819+
%idxprom.us = sext i32 %add.us to i64
820+
%arrayidx.us = getelementptr inbounds i32, i32* %A, i64 %idxprom.us
821+
tail call void @f(i32* %arrayidx.us) #2
822+
%inc.us = add nuw nsw i32 %j.016.us, 1
823+
%cmp2.us = icmp slt i32 %inc.us, %M2
824+
br i1 %cmp2.us, label %for.body4.us, label %for.cond1.for.cond.cleanup3_crit_edge.us
825+
826+
for.cond1.for.cond.cleanup3_crit_edge.us:
827+
%inc6.us = add nuw nsw i32 %i.018.us, 1
828+
%cmp.us = icmp slt i32 %inc6.us, %N
829+
br i1 %cmp.us, label %for.cond1.preheader.us, label %for.cond.cleanup
830+
831+
for.cond.cleanup:
832+
ret void
833+
}
834+
758835
declare void @payload()
759836
declare dso_local i32 @use_32(i32)
760837
declare dso_local i32 @use_16(i16)

0 commit comments

Comments
 (0)