diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp index e706a6f83b1e7..4d0e5a61db9a4 100644 --- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -265,8 +265,9 @@ bool InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI, ScalarEvolution &SE, const SCEVAddRecExpr *&Index, const SCEV *&End) { - auto IsLoopInvariant = [&SE, L](Value *V) { - return SE.isLoopInvariant(SE.getSCEV(V), L); + auto IsLoopInvariantAndNotUndef = [&SE, L](Value *V) { + const SCEV *S = SE.getSCEV(V); + return SE.isLoopInvariant(S, L) && !SE.containsUndefs(S); }; ICmpInst::Predicate Pred = ICI->getPredicate(); @@ -277,10 +278,10 @@ bool InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI, return false; // Canonicalize to the `Index Pred Invariant` comparison - if (IsLoopInvariant(LHS)) { + if (IsLoopInvariantAndNotUndef(LHS)) { std::swap(LHS, RHS); Pred = CmpInst::getSwappedPredicate(Pred); - } else if (!IsLoopInvariant(RHS)) + } else if (!IsLoopInvariantAndNotUndef(RHS)) // Both LHS and RHS are loop variant return false; diff --git a/llvm/test/Transforms/IRCE/undef.ll b/llvm/test/Transforms/IRCE/undef.ll new file mode 100644 index 0000000000000..22d6c32a02347 --- /dev/null +++ b/llvm/test/Transforms/IRCE/undef.ll @@ -0,0 +1,58 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=irce -S < %s 2>&1 | FileCheck %s + +; Make sure we don't crash. +define swiftcc void @wombat() { +; CHECK-LABEL: define swiftcc void @wombat() { +; CHECK-NEXT: [[BB:.*]]: +; CHECK-NEXT: br label %[[BB1:.*]] +; CHECK: [[BB1]]: +; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[ADD:%.*]], %[[BB7:.*]] ], [ 1, %[[BB]] ] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ult i64 [[PHI]], undef +; CHECK-NEXT: br i1 [[ICMP]], label %[[BB3:.*]], label %[[BB2:.*]] +; CHECK: [[BB2]]: +; CHECK-NEXT: unreachable +; CHECK: [[BB3]]: +; CHECK-NEXT: [[CALL5:%.*]] = call token (...) @llvm.gc_preserve_begin(ptr null) +; CHECK-NEXT: br i1 true, label %[[BB7]], label %[[BB6:.*]] +; CHECK: [[BB6]]: +; CHECK-NEXT: call void @llvm.gc_preserve_end(token [[CALL5]]) +; CHECK-NEXT: unreachable +; CHECK: [[BB7]]: +; CHECK-NEXT: [[ICMP8:%.*]] = icmp eq i64 [[PHI]], 1 +; CHECK-NEXT: [[ADD]] = add i64 [[PHI]], 1 +; CHECK-NEXT: br i1 [[ICMP8]], label %[[BB9:.*]], label %[[BB1]] +; CHECK: [[BB9]]: +; CHECK-NEXT: unreachable +; +bb: + br label %bb1 + +bb1: ; preds = %bb7, %bb + %phi = phi i64 [ %add, %bb7 ], [ 1, %bb ] + %icmp = icmp ult i64 %phi, undef + br i1 %icmp, label %bb3, label %bb2 + +bb2: ; preds = %bb1 + unreachable + +bb3: ; preds = %bb1 + %call5 = call token (...) @llvm.gc_preserve_begin(ptr null) + br i1 false, label %bb6, label %bb7 + +bb6: ; preds = %bb3 + call void @llvm.gc_preserve_end(token %call5) + unreachable + +bb7: ; preds = %bb3 + %icmp8 = icmp eq i64 %phi, 1 + %add = add i64 %phi, 1 + br i1 %icmp8, label %bb9, label %bb1 + +bb9: ; preds = %bb7 + unreachable +} + +declare token @llvm.gc_preserve_begin(...) + +declare void @llvm.gc_preserve_end(token)