Skip to content

Commit d1fb13c

Browse files
committedJan 22, 2015
Fix crashes in IRCE caused by mismatched types
There are places where the inductive range check elimination pass depends on two llvm::Values or llvm::SCEVs to be of the same llvm::Type when they do not need to be. This patch relaxes those restrictions (by bailing out of the optimization if the types mismatch), and adds test cases to trigger those paths. These issues were found by bootstrapping clang with IRCE running in the -O3 pass ordering. Differential Revision: http://reviews.llvm.org/D7082 llvm-svn: 226793
1 parent 96cfb9c commit d1fb13c

File tree

2 files changed

+101
-7
lines changed

2 files changed

+101
-7
lines changed
 

‎llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp

+35-7
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,9 @@ class LoopConstrainer {
489489
// Compute a safe set of limits for the main loop to run in -- effectively the
490490
// intersection of `Range' and the iteration space of the original loop.
491491
// Return the header count (1 + the latch taken count) in `HeaderCount'.
492+
// Return None if unable to compute the set of subranges.
492493
//
493-
SubRanges calculateSubRanges(Value *&HeaderCount) const;
494+
Optional<SubRanges> calculateSubRanges(Value *&HeaderCount) const;
494495

495496
// Clone `OriginalLoop' and return the result in CLResult. The IR after
496497
// running `cloneLoop' is well formed except for the PHI nodes in CLResult --
@@ -660,8 +661,14 @@ bool LoopConstrainer::recognizeLoop(LoopStructure &LoopStructureOut,
660661
return false;
661662
}
662663

664+
// IndVarSimplify will sometimes leave behind (in SCEV's cache) backedge-taken
665+
// counts that are narrower than the canonical induction variable. These
666+
// values are still accurate, and we could probably use them after sign/zero
667+
// extension; but for now we just bail out of the transformation to keep
668+
// things simple.
663669
const SCEV *CIVComparedToSCEV = SE.getSCEV(CIVComparedTo);
664-
if (isa<SCEVCouldNotCompute>(CIVComparedToSCEV)) {
670+
if (isa<SCEVCouldNotCompute>(CIVComparedToSCEV) ||
671+
CIVComparedToSCEV->getType() != LatchCount->getType()) {
665672
FailureReason = "could not relate CIV to latch expression";
666673
return false;
667674
}
@@ -699,10 +706,15 @@ bool LoopConstrainer::recognizeLoop(LoopStructure &LoopStructureOut,
699706
return true;
700707
}
701708

702-
LoopConstrainer::SubRanges
709+
Optional<LoopConstrainer::SubRanges>
703710
LoopConstrainer::calculateSubRanges(Value *&HeaderCountOut) const {
704711
IntegerType *Ty = cast<IntegerType>(LatchTakenCount->getType());
705712

713+
assert(Range.first->getType() == Range.second->getType() &&
714+
"ill-typed range!");
715+
if (Range.first->getType() != Ty)
716+
return None;
717+
706718
SCEVExpander Expander(SE, "irce");
707719
Instruction *InsertPt = OriginalPreheader->getTerminator();
708720

@@ -999,7 +1011,12 @@ bool LoopConstrainer::run() {
9991011
OriginalPreheader = Preheader;
10001012
MainLoopPreheader = Preheader;
10011013

1002-
SubRanges SR = calculateSubRanges(OriginalHeaderCount);
1014+
Optional<SubRanges> MaybeSR = calculateSubRanges(OriginalHeaderCount);
1015+
if (!MaybeSR.hasValue()) {
1016+
DEBUG(dbgs() << "irce: could not compute subranges\n");
1017+
return false;
1018+
}
1019+
SubRanges SR = MaybeSR.getValue();
10031020

10041021
// It would have been better to make `PreLoop' and `PostLoop'
10051022
// `Optional<ClonedLoop>'s, but `ValueToValueMapTy' does not have a copy
@@ -1113,13 +1130,20 @@ InductiveRangeCheck::computeSafeIterationSpace(ScalarEvolution &SE,
11131130
return std::make_pair(Begin, End);
11141131
}
11151132

1116-
static InductiveRangeCheck::Range
1133+
static Optional<InductiveRangeCheck::Range>
11171134
IntersectRange(const Optional<InductiveRangeCheck::Range> &R1,
11181135
const InductiveRangeCheck::Range &R2, IRBuilder<> &B) {
1136+
assert(R2.first->getType() == R2.second->getType() && "ill-typed range!");
1137+
11191138
if (!R1.hasValue())
11201139
return R2;
11211140
auto &R1Value = R1.getValue();
11221141

1142+
// TODO: we could widen the smaller range and have this work; but for now we
1143+
// bail out to keep things simple.
1144+
if (R1Value.first->getType() != R2.first->getType())
1145+
return None;
1146+
11231147
Value *NewMin = ConstructSMaxOf(R1Value.first, R2.first, B);
11241148
Value *NewMax = ConstructSMinOf(R1Value.second, R2.second, B);
11251149
return std::make_pair(NewMin, NewMax);
@@ -1167,8 +1191,12 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
11671191
for (InductiveRangeCheck *IRC : RangeChecks) {
11681192
auto Result = IRC->computeSafeIterationSpace(SE, B);
11691193
if (Result.hasValue()) {
1170-
SafeIterRange = IntersectRange(SafeIterRange, Result.getValue(), B);
1171-
RangeChecksToEliminate.push_back(IRC);
1194+
auto MaybeSafeIterRange =
1195+
IntersectRange(SafeIterRange, Result.getValue(), B);
1196+
if (MaybeSafeIterRange.hasValue()) {
1197+
RangeChecksToEliminate.push_back(IRC);
1198+
SafeIterRange = MaybeSafeIterRange.getValue();
1199+
}
11721200
}
11731201
}
11741202

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; RUN: opt -irce -S < %s
2+
3+
; These test cases don't check the correctness of the transform, but
4+
; that the -irce does not crash in the presence of certain things in
5+
; the IR:
6+
7+
define void @mismatched_types_1() {
8+
; In this test case, the safe range for the only range check in the
9+
; loop is of type [i32, i32) while the backedge taken count is of type
10+
; i64.
11+
12+
; CHECK-LABEL: mismatched_types_1
13+
entry:
14+
br label %for.body
15+
16+
for.body:
17+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
18+
%0 = trunc i64 %indvars.iv to i32
19+
%1 = icmp ult i32 %0, 7
20+
br i1 %1, label %switch.lookup, label %for.inc
21+
22+
switch.lookup:
23+
br label %for.inc
24+
25+
for.inc:
26+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
27+
%cmp55 = icmp slt i64 %indvars.iv.next, 11
28+
br i1 %cmp55, label %for.body, label %for.end
29+
30+
for.end:
31+
unreachable
32+
}
33+
34+
define void @mismatched_types_2() {
35+
; In this test case, there are two range check in the loop, one with a
36+
; safe range of type [i32, i32) and one with a safe range of type
37+
; [i64, i64).
38+
39+
; CHECK-LABEL: mismatched_types_2
40+
entry:
41+
br label %for.body.a
42+
43+
for.body.a:
44+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
45+
%cond.a = icmp ult i64 %indvars.iv, 7
46+
br i1 %cond.a, label %switch.lookup.a, label %for.body.b
47+
48+
switch.lookup.a:
49+
br label %for.body.b
50+
51+
for.body.b:
52+
%truncated = trunc i64 %indvars.iv to i32
53+
%cond.b = icmp ult i32 %truncated, 7
54+
br i1 %cond.b, label %switch.lookup.b, label %for.inc
55+
56+
switch.lookup.b:
57+
br label %for.inc
58+
59+
for.inc:
60+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
61+
%cmp55 = icmp slt i64 %indvars.iv.next, 11
62+
br i1 %cmp55, label %for.body.a, label %for.end
63+
64+
for.end:
65+
unreachable
66+
}

0 commit comments

Comments
 (0)
Please sign in to comment.