From 8307f6c854b64d00bac3d621917ff11bec1afb32 Mon Sep 17 00:00:00 2001 From: Dmitry Makogon Date: Thu, 6 Oct 2022 16:30:48 +0700 Subject: [PATCH] [LoopPredication] Insert assumes of conditions of predicated guards As LoopPredication performs non-equivalent transforms removing some checks from loops, other passes may not be able to perform transforms they'd be able to do if the checks were left in loops. This patch makes LoopPredication insert assumes of the replaced conditions either after a guard call or in the true block of widenable condition branch. Differential Revision: https://reviews.llvm.org/D135354 --- llvm/lib/Transforms/Scalar/LoopPredication.cpp | 21 +++++ llvm/test/Transforms/LoopPredication/assumes.ll | 19 ++-- llvm/test/Transforms/LoopPredication/basic.ll | 62 +++++++++++++ .../basic_widenable_branch_guards.ll | 54 +++++++++++ .../Transforms/LoopPredication/invariant_load.ll | 6 ++ llvm/test/Transforms/LoopPredication/nested.ll | 13 ++- .../Transforms/LoopPredication/profitability.ll | 2 + llvm/test/Transforms/LoopPredication/reverse.ll | 12 +++ llvm/test/Transforms/LoopPredication/visited.ll | 100 +++++++++++++++++++++ llvm/test/Transforms/LoopPredication/widened.ll | 24 +++-- 10 files changed, 291 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopPredication.cpp b/llvm/lib/Transforms/Scalar/LoopPredication.cpp index b327d38..65abc8fb 100644 --- a/llvm/lib/Transforms/Scalar/LoopPredication.cpp +++ b/llvm/lib/Transforms/Scalar/LoopPredication.cpp @@ -233,6 +233,13 @@ static cl::opt PredicateWidenableBranchGuards( "expressed as widenable branches to deoptimize blocks"), cl::init(true)); +static cl::opt InsertAssumesOfPredicatedGuardsConditions( + "loop-predication-insert-assumes-of-predicated-guards-conditions", + cl::Hidden, + cl::desc("Whether or not we should insert assumes of conditions of " + "predicated guards"), + cl::init(true)); + namespace { /// Represents an induction variable check: /// icmp Pred, , @@ -817,6 +824,10 @@ bool LoopPredication::widenGuardConditions(IntrinsicInst *Guard, Value *AllChecks = Builder.CreateAnd(Checks); auto *OldCond = Guard->getOperand(0); Guard->setOperand(0, AllChecks); + if (InsertAssumesOfPredicatedGuardsConditions) { + Builder.SetInsertPoint(&*++BasicBlock::iterator(Guard)); + Builder.CreateAssumption(OldCond); + } RecursivelyDeleteTriviallyDeadInstructions(OldCond, nullptr /* TLI */, MSSAU); LLVM_DEBUG(dbgs() << "Widened checks = " << NumWidened << "\n"); @@ -829,6 +840,12 @@ bool LoopPredication::widenWidenableBranchGuardConditions( LLVM_DEBUG(dbgs() << "Processing guard:\n"); LLVM_DEBUG(BI->dump()); + Value *Cond, *WC; + BasicBlock *IfTrueBB, *IfFalseBB; + bool Parsed = parseWidenableBranch(BI, Cond, WC, IfTrueBB, IfFalseBB); + assert(Parsed && "Must be able to parse widenable branch"); + (void)Parsed; + TotalConsidered++; SmallVector Checks; unsigned NumWidened = collectChecks(Checks, BI->getCondition(), @@ -843,6 +860,10 @@ bool LoopPredication::widenWidenableBranchGuardConditions( Value *AllChecks = Builder.CreateAnd(Checks); auto *OldCond = BI->getCondition(); BI->setCondition(AllChecks); + if (InsertAssumesOfPredicatedGuardsConditions) { + Builder.SetInsertPoint(IfTrueBB, IfTrueBB->getFirstInsertionPt()); + Builder.CreateAssumption(Cond); + } RecursivelyDeleteTriviallyDeadInstructions(OldCond, nullptr /* TLI */, MSSAU); assert(isGuardAsWidenableBranch(BI) && "Stopped being a guard after transform?"); diff --git a/llvm/test/Transforms/LoopPredication/assumes.ll b/llvm/test/Transforms/LoopPredication/assumes.ll index 23f0aa7..5b23a1f 100644 --- a/llvm/test/Transforms/LoopPredication/assumes.ll +++ b/llvm/test/Transforms/LoopPredication/assumes.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -passes='loop-mssa(loop-predication),gvn,simplifycfg' < %s 2>&1 | FileCheck %s +; RUN: opt -S -passes='loop-mssa(loop-predication),gvn,simplifycfg' -loop-predication-insert-assumes-of-predicated-guards-conditions=true < %s 2>&1 | 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-ni:1-p2:32:8:8:32-ni:2" target triple = "x86_64-unknown-linux-gnu" @@ -23,25 +23,18 @@ define i32 @test0(i32* %p1, i8* %p2, i32* %p3, i8* %p4, i8* %p5, i1 %c, i32 %x) ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[IV_1_NEXT:%.*]], [[LATCH:%.*]] ], [ [[IV_1_START]], [[LOOP_PREHEADER]] ] -; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_2_NEXT:%.*]], [[LATCH]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[IV_1:%.*]] = phi i32 [ [[IV_1_NEXT:%.*]], [[LOOP_NEXT:%.*]] ], [ [[IV_1_START]], [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[IV_2:%.*]] = phi i32 [ [[IV_2_NEXT:%.*]], [[LOOP_NEXT]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[P2:%.*]], i32 [[IV_1]] ; CHECK-NEXT: [[VALUE:%.*]] = load i8, i8* [[GEP_1]], align 1 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[IV_1]], [[IV_1_END]] ; CHECK-NEXT: [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[WC]] -; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_NEXT:%.*]], label [[DEOPT:%.*]] +; CHECK-NEXT: br i1 [[TMP5]], label [[LOOP_NEXT]], label [[DEOPT:%.*]] ; CHECK: loop.next: -; CHECK-NEXT: br i1 [[COND_1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] -; CHECK: if.true: +; CHECK-NEXT: call void @llvm.assume(i1 [[COND_1]]) ; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[P4:%.*]], i32 [[IV_1]] ; CHECK-NEXT: store i8 [[VALUE]], i8* [[GEP_3]], align 1 -; CHECK-NEXT: br label [[LATCH]] -; CHECK: if.false: -; CHECK-NEXT: [[GEP_4:%.*]] = getelementptr i8, i8* [[P4]], i32 [[IV_2]] -; CHECK-NEXT: store i8 [[VALUE]], i8* [[GEP_4]], align 1 -; CHECK-NEXT: br label [[LATCH]] -; CHECK: latch: ; CHECK-NEXT: [[IV_1_NEXT]] = add nuw nsw i32 [[IV_1]], 1 ; CHECK-NEXT: [[IV_2_NEXT]] = add nuw nsw i32 [[IV_2]], 1 ; CHECK-NEXT: [[LATCH_COND:%.*]] = icmp ult i32 [[IV_2]], [[IV_2_END]] @@ -50,7 +43,7 @@ define i32 @test0(i32* %p1, i8* %p2, i32* %p3, i8* %p4, i8* %p5, i1 %c, i32 %x) ; CHECK-NEXT: [[DEOPT_RES:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPT_RES]] ; CHECK: exit: -; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_2]], [[LATCH]] ] +; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_2]], [[LOOP_NEXT]] ] ; CHECK-NEXT: ret i32 [[RES]] ; entry: diff --git a/llvm/test/Transforms/LoopPredication/basic.ll b/llvm/test/Transforms/LoopPredication/basic.ll index 18991b6..5b05a3b 100644 --- a/llvm/test/Transforms/LoopPredication/basic.ll +++ b/llvm/test/Transforms/LoopPredication/basic.ll @@ -17,7 +17,9 @@ define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -72,7 +74,9 @@ define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -127,7 +131,9 @@ define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ugt i32 [[LENGTH]], [[I]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -182,7 +188,9 @@ define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -237,7 +245,9 @@ define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %l ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -293,7 +303,9 @@ define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -348,7 +360,9 @@ define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -404,7 +418,9 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -461,7 +477,9 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_chec ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -517,7 +535,10 @@ define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %leng ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -573,7 +594,10 @@ define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i3 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -738,7 +762,9 @@ define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i3 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -800,7 +826,9 @@ define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START_I]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -981,7 +1009,11 @@ define i32 @two_range_checks(i32* %array.1, i32 %length.1, ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 @@ -1054,7 +1086,13 @@ define i32 @three_range_checks(i32* %array.1, i32 %length.1, ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]] +; CHECK-NEXT: [[WITHIN_BOUNDS_1_AND_2:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1_AND_2]], [[WITHIN_BOUNDS_3]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP10]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 @@ -1135,16 +1173,22 @@ define i32 @three_guards(i32* %array.1, i32 %length.1, ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_1]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_2]]) ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] +; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_3]]) ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] @@ -1216,9 +1260,12 @@ define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[UNRELATED_COND]] ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[GUARD_COND]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1447,7 +1494,10 @@ define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[LENGTH:%.*]] = zext i16 [[LENGTH_I16]] to i32 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1501,10 +1551,12 @@ define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH_UDIV]] ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]] ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1560,7 +1612,9 @@ define i32 @provably_taken(i32* %array, i32* %length.ptr) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1609,7 +1663,9 @@ define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]] ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] @@ -1646,7 +1702,9 @@ define i32 @ne_latch_zext_preinc(i32* %array, i32 %length, i16 %n16) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] @@ -1727,7 +1785,9 @@ define i32 @ne_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] @@ -1770,7 +1830,9 @@ define i32 @eq_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 ; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[I]], [[N]] ; CHECK-NEXT: br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]] diff --git a/llvm/test/Transforms/LoopPredication/basic_widenable_branch_guards.ll b/llvm/test/Transforms/LoopPredication/basic_widenable_branch_guards.ll index 52f1c38..55b6dbb 100644 --- a/llvm/test/Transforms/LoopPredication/basic_widenable_branch_guards.ll +++ b/llvm/test/Transforms/LoopPredication/basic_widenable_branch_guards.ll @@ -18,6 +18,7 @@ define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] @@ -25,6 +26,7 @@ define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -85,6 +87,7 @@ define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -92,6 +95,7 @@ define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -152,6 +156,7 @@ define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ugt i32 [[LENGTH]], [[I]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -159,6 +164,7 @@ define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) { ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -219,6 +225,7 @@ define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -226,6 +233,7 @@ define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -287,6 +295,7 @@ define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %l ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -294,6 +303,7 @@ define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %l ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -355,6 +365,7 @@ define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -362,6 +373,7 @@ define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -422,6 +434,7 @@ define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -429,6 +442,7 @@ define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -490,6 +504,7 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -497,6 +512,7 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -559,6 +575,7 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_chec ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -566,6 +583,7 @@ define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_chec ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -626,6 +644,8 @@ define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %leng ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -633,6 +653,7 @@ define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %leng ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -694,6 +715,8 @@ define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i3 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[I_OFFSET:%.*]] = add i32 [[I]], 1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -701,6 +724,7 @@ define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i3 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -895,6 +919,7 @@ define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i3 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -902,6 +927,7 @@ define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i3 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -968,6 +994,7 @@ define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ [[START_I]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ [[START_J]], [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -975,6 +1002,7 @@ define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1179,6 +1207,9 @@ define i32 @two_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %l ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP2]], [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[WIDENABLE_COND]] @@ -1187,6 +1218,7 @@ define i32 @two_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %l ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 @@ -1261,6 +1293,11 @@ define i32 @three_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]] +; CHECK-NEXT: [[WITHIN_BOUNDS_1_AND_2:%.*]] = and i1 [[WITHIN_BOUNDS_1]], [[WITHIN_BOUNDS_2]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = and i1 [[WITHIN_BOUNDS_1_AND_2]], [[WITHIN_BOUNDS_3]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP2]], [[TMP5]] ; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]] @@ -1270,6 +1307,7 @@ define i32 @three_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 @@ -1352,6 +1390,7 @@ define i32 @three_guards(i32* %array.1, i32 %length.1, i32* %array.2, i32 %lengt ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED6:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED6]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP9]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -1359,10 +1398,12 @@ define i32 @three_guards(i32* %array.1, i32 %length.1, i32* %array.2, i32 %lengt ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_1]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] +; CHECK-NEXT: [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]] ; CHECK-NEXT: [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP5]], [[WIDENABLE_COND4]] ; CHECK-NEXT: br i1 [[TMP10]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] @@ -1370,9 +1411,11 @@ define i32 @three_guards(i32* %array.1, i32 %length.1, i32* %array.2, i32 %lengt ; CHECK-NEXT: [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL3]] ; CHECK: guarded1: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_2]]) ; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] +; CHECK-NEXT: [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]] ; CHECK-NEXT: [[WIDENABLE_COND9:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP11:%.*]] = and i1 [[TMP8]], [[WIDENABLE_COND9]] ; CHECK-NEXT: br i1 [[TMP11]], label [[GUARDED6]], label [[DEOPT7:%.*]], !prof [[PROF0]] @@ -1380,6 +1423,7 @@ define i32 @three_guards(i32* %array.1, i32 %length.1, i32* %array.2, i32 %lengt ; CHECK-NEXT: [[DEOPTCALL8:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL8]] ; CHECK: guarded6: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS_3]]) ; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] @@ -1465,7 +1509,9 @@ define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] +; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[UNRELATED_COND]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]] ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]] @@ -1474,6 +1520,7 @@ define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[GUARD_COND]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1742,6 +1789,8 @@ define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[LENGTH:%.*]] = zext i16 [[LENGTH_I16]] to i32 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]] ; CHECK-NEXT: br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] @@ -1749,6 +1798,7 @@ define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1808,6 +1858,7 @@ define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH_UDIV]] ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]] @@ -1818,6 +1869,7 @@ define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -1939,11 +1991,13 @@ define i32 @swapped_wb(i32* %array, i32 %length, i32 %n) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]] ; CHECK: deopt: ; CHECK-NEXT: [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ] ; CHECK-NEXT: ret i32 [[DEOPTCALL]] ; CHECK: guarded: +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 diff --git a/llvm/test/Transforms/LoopPredication/invariant_load.ll b/llvm/test/Transforms/LoopPredication/invariant_load.ll index 6b7e18a..261d9a9 100644 --- a/llvm/test/Transforms/LoopPredication/invariant_load.ll +++ b/llvm/test/Transforms/LoopPredication/invariant_load.ll @@ -78,10 +78,12 @@ define i32 @invariant_load_guard_limit(i32* %array, i32* %length, i32 %n) { ; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN, align 1 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]] ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]] ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -330,10 +332,12 @@ define i32 @constant_memory(i32* %array, i32 %n) { ; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN, align 1 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* @Length, align 4 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]] ; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]] ; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -392,7 +396,9 @@ define i32 @constant_length(i32* %array, i32 %n) { ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN, align 1 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], 20 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 diff --git a/llvm/test/Transforms/LoopPredication/nested.ll b/llvm/test/Transforms/LoopPredication/nested.ll index 62be706..bb8d675 100644 --- a/llvm/test/Transforms/LoopPredication/nested.ll +++ b/llvm/test/Transforms/LoopPredication/nested.ll @@ -24,7 +24,9 @@ define i32 @signed_loop_0_to_n_nested_0_to_l_inner_index_check(i32* %array, i32 ; CHECK: inner.loop: ; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ 0, [[INNER_LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[J_I64:%.*]] = zext i32 [[J]] to i64 ; CHECK-NEXT: [[ARRAY_J_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[J_I64]] ; CHECK-NEXT: [[ARRAY_J:%.*]] = load i32, i32* [[ARRAY_J_PTR]], align 4 @@ -110,7 +112,9 @@ define i32 @signed_loop_0_to_n_nested_0_to_l_outer_index_check(i32* %array, i32 ; CHECK: inner.loop: ; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ 0, [[INNER_LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -194,12 +198,17 @@ define i32 @signed_loop_0_to_n_nested_i_to_l_inner_index_check(i32* %array, i32 ; CHECK-NEXT: br i1 [[TMP6]], label [[OUTER_LOOP_INC]], label [[INNER_LOOP_PREHEADER:%.*]] ; CHECK: inner.loop.preheader: ; CHECK-NEXT: [[TMP3:%.*]] = icmp sle i32 [[L]], [[LENGTH]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[I]], [[LENGTH]] +; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]] ; CHECK-NEXT: br label [[INNER_LOOP:%.*]] ; CHECK: inner.loop: ; CHECK-NEXT: [[INNER_LOOP_ACC:%.*]] = phi i32 [ [[INNER_LOOP_ACC_NEXT:%.*]], [[INNER_LOOP]] ], [ [[OUTER_LOOP_ACC]], [[INNER_LOOP_PREHEADER]] ] ; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[INNER_LOOP]] ], [ [[I]], [[INNER_LOOP_PREHEADER]] ] -; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]] -; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]] +; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP3]], [[TMP2]] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]]) +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[J_I64:%.*]] = zext i32 [[J]] to i64 ; CHECK-NEXT: [[ARRAY_J_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[J_I64]] ; CHECK-NEXT: [[ARRAY_J:%.*]] = load i32, i32* [[ARRAY_J_PTR]], align 4 diff --git a/llvm/test/Transforms/LoopPredication/profitability.ll b/llvm/test/Transforms/LoopPredication/profitability.ll index aae893b..c9c9397 100644 --- a/llvm/test/Transforms/LoopPredication/profitability.ll +++ b/llvm/test/Transforms/LoopPredication/profitability.ll @@ -74,7 +74,9 @@ define i64 @predicate(i64* nocapture readonly %arg, i32 %length, i64* nocapture ; CHECK: Header: ; CHECK-NEXT: [[RESULT_IN3:%.*]] = phi i64* [ [[ARG2:%.*]], [[ENTRY:%.*]] ], [ [[ARG:%.*]], [[LATCH:%.*]] ] ; CHECK-NEXT: [[J2:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[J_NEXT:%.*]], [[LATCH]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i64 [[J2]], [[LENGTH_EXT]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[INNERCMP:%.*]] = icmp eq i64 [[J2]], [[N_PRE]] ; CHECK-NEXT: [[J_NEXT]] = add nuw nsw i64 [[J2]], 1 ; CHECK-NEXT: br i1 [[INNERCMP]], label [[LATCH]], label [[EXIT:%.*]] diff --git a/llvm/test/Transforms/LoopPredication/reverse.ll b/llvm/test/Transforms/LoopPredication/reverse.ll index 2a6d9fa..51efb92 100644 --- a/llvm/test/Transforms/LoopPredication/reverse.ll +++ b/llvm/test/Transforms/LoopPredication/reverse.ll @@ -19,7 +19,9 @@ define i32 @signed_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 % ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -73,7 +75,9 @@ define i32 @unsigned_reverse_loop_n_to_lower_limit(i32* %array, i32 %length, i32 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -129,7 +133,9 @@ define i32 @unsigned_reverse_loop_n_to_0(i32* %array, i32 %length, i32 %n, i32 % ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -239,7 +245,9 @@ define i32 @signed_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %length, ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -293,7 +301,9 @@ define i32 @unsigned_reverse_loop_n_to_lower_limit_equal(i32* %array, i32 %lengt ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 @@ -349,7 +359,9 @@ define i32 @unsigned_reverse_loop_n_to_1(i32* %array, i32 %length, i32 %n, i32 % ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 diff --git a/llvm/test/Transforms/LoopPredication/visited.ll b/llvm/test/Transforms/LoopPredication/visited.ll index 6120ecb..e748f0c 100644 --- a/llvm/test/Transforms/LoopPredication/visited.ll +++ b/llvm/test/Transforms/LoopPredication/visited.ll @@ -17,9 +17,109 @@ define i32 @test_visited(i32* %array, i32 %length, i32 %n, i32 %x) { ; CHECK: loop: ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]] ; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp eq i32 [[X:%.*]], [[I]] +; CHECK-NEXT: [[GUARD_COND_2:%.*]] = and i1 [[WITHIN_BOUNDS]], [[UNRELATED_COND]] +; CHECK-NEXT: [[GUARD_COND_3:%.*]] = and i1 [[GUARD_COND_2]], [[UNRELATED_COND]] +; CHECK-NEXT: [[GUARD_COND_4:%.*]] = and i1 [[GUARD_COND_3]], [[GUARD_COND_2]] +; CHECK-NEXT: [[GUARD_COND_5:%.*]] = and i1 [[GUARD_COND_4]], [[GUARD_COND_3]] +; CHECK-NEXT: [[GUARD_COND_6:%.*]] = and i1 [[GUARD_COND_5]], [[GUARD_COND_4]] +; CHECK-NEXT: [[GUARD_COND_7:%.*]] = and i1 [[GUARD_COND_6]], [[GUARD_COND_5]] +; CHECK-NEXT: [[GUARD_COND_8:%.*]] = and i1 [[GUARD_COND_7]], [[GUARD_COND_6]] +; CHECK-NEXT: [[GUARD_COND_9:%.*]] = and i1 [[GUARD_COND_8]], [[GUARD_COND_7]] +; CHECK-NEXT: [[GUARD_COND_10:%.*]] = and i1 [[GUARD_COND_9]], [[GUARD_COND_8]] +; CHECK-NEXT: [[GUARD_COND_11:%.*]] = and i1 [[GUARD_COND_10]], [[GUARD_COND_9]] +; CHECK-NEXT: [[GUARD_COND_12:%.*]] = and i1 [[GUARD_COND_11]], [[GUARD_COND_10]] +; CHECK-NEXT: [[GUARD_COND_13:%.*]] = and i1 [[GUARD_COND_12]], [[GUARD_COND_11]] +; CHECK-NEXT: [[GUARD_COND_14:%.*]] = and i1 [[GUARD_COND_13]], [[GUARD_COND_12]] +; CHECK-NEXT: [[GUARD_COND_15:%.*]] = and i1 [[GUARD_COND_14]], [[GUARD_COND_13]] +; CHECK-NEXT: [[GUARD_COND_16:%.*]] = and i1 [[GUARD_COND_15]], [[GUARD_COND_14]] +; CHECK-NEXT: [[GUARD_COND_17:%.*]] = and i1 [[GUARD_COND_16]], [[GUARD_COND_15]] +; CHECK-NEXT: [[GUARD_COND_18:%.*]] = and i1 [[GUARD_COND_17]], [[GUARD_COND_16]] +; CHECK-NEXT: [[GUARD_COND_19:%.*]] = and i1 [[GUARD_COND_18]], [[GUARD_COND_17]] +; CHECK-NEXT: [[GUARD_COND_20:%.*]] = and i1 [[GUARD_COND_19]], [[GUARD_COND_18]] +; CHECK-NEXT: [[GUARD_COND_21:%.*]] = and i1 [[GUARD_COND_20]], [[GUARD_COND_19]] +; CHECK-NEXT: [[GUARD_COND_22:%.*]] = and i1 [[GUARD_COND_21]], [[GUARD_COND_20]] +; CHECK-NEXT: [[GUARD_COND_23:%.*]] = and i1 [[GUARD_COND_22]], [[GUARD_COND_21]] +; CHECK-NEXT: [[GUARD_COND_24:%.*]] = and i1 [[GUARD_COND_23]], [[GUARD_COND_22]] +; CHECK-NEXT: [[GUARD_COND_25:%.*]] = and i1 [[GUARD_COND_24]], [[GUARD_COND_23]] +; CHECK-NEXT: [[GUARD_COND_26:%.*]] = and i1 [[GUARD_COND_25]], [[GUARD_COND_24]] +; CHECK-NEXT: [[GUARD_COND_27:%.*]] = and i1 [[GUARD_COND_26]], [[GUARD_COND_25]] +; CHECK-NEXT: [[GUARD_COND_28:%.*]] = and i1 [[GUARD_COND_27]], [[GUARD_COND_26]] +; CHECK-NEXT: [[GUARD_COND_29:%.*]] = and i1 [[GUARD_COND_28]], [[GUARD_COND_27]] +; CHECK-NEXT: [[GUARD_COND_30:%.*]] = and i1 [[GUARD_COND_29]], [[GUARD_COND_28]] +; CHECK-NEXT: [[GUARD_COND_31:%.*]] = and i1 [[GUARD_COND_30]], [[GUARD_COND_29]] +; CHECK-NEXT: [[GUARD_COND_32:%.*]] = and i1 [[GUARD_COND_31]], [[GUARD_COND_30]] +; CHECK-NEXT: [[GUARD_COND_33:%.*]] = and i1 [[GUARD_COND_32]], [[GUARD_COND_31]] +; CHECK-NEXT: [[GUARD_COND_34:%.*]] = and i1 [[GUARD_COND_33]], [[GUARD_COND_32]] +; CHECK-NEXT: [[GUARD_COND_35:%.*]] = and i1 [[GUARD_COND_34]], [[GUARD_COND_33]] +; CHECK-NEXT: [[GUARD_COND_36:%.*]] = and i1 [[GUARD_COND_35]], [[GUARD_COND_34]] +; CHECK-NEXT: [[GUARD_COND_37:%.*]] = and i1 [[GUARD_COND_36]], [[GUARD_COND_35]] +; CHECK-NEXT: [[GUARD_COND_38:%.*]] = and i1 [[GUARD_COND_37]], [[GUARD_COND_36]] +; CHECK-NEXT: [[GUARD_COND_39:%.*]] = and i1 [[GUARD_COND_38]], [[GUARD_COND_37]] +; CHECK-NEXT: [[GUARD_COND_40:%.*]] = and i1 [[GUARD_COND_39]], [[GUARD_COND_38]] +; CHECK-NEXT: [[GUARD_COND_41:%.*]] = and i1 [[GUARD_COND_40]], [[GUARD_COND_39]] +; CHECK-NEXT: [[GUARD_COND_42:%.*]] = and i1 [[GUARD_COND_41]], [[GUARD_COND_40]] +; CHECK-NEXT: [[GUARD_COND_43:%.*]] = and i1 [[GUARD_COND_42]], [[GUARD_COND_41]] +; CHECK-NEXT: [[GUARD_COND_44:%.*]] = and i1 [[GUARD_COND_43]], [[GUARD_COND_42]] +; CHECK-NEXT: [[GUARD_COND_45:%.*]] = and i1 [[GUARD_COND_44]], [[GUARD_COND_43]] +; CHECK-NEXT: [[GUARD_COND_46:%.*]] = and i1 [[GUARD_COND_45]], [[GUARD_COND_44]] +; CHECK-NEXT: [[GUARD_COND_47:%.*]] = and i1 [[GUARD_COND_46]], [[GUARD_COND_45]] +; CHECK-NEXT: [[GUARD_COND_48:%.*]] = and i1 [[GUARD_COND_47]], [[GUARD_COND_46]] +; CHECK-NEXT: [[GUARD_COND_49:%.*]] = and i1 [[GUARD_COND_48]], [[GUARD_COND_47]] +; CHECK-NEXT: [[GUARD_COND_50:%.*]] = and i1 [[GUARD_COND_49]], [[GUARD_COND_48]] +; CHECK-NEXT: [[GUARD_COND_51:%.*]] = and i1 [[GUARD_COND_50]], [[GUARD_COND_49]] +; CHECK-NEXT: [[GUARD_COND_52:%.*]] = and i1 [[GUARD_COND_51]], [[GUARD_COND_50]] +; CHECK-NEXT: [[GUARD_COND_53:%.*]] = and i1 [[GUARD_COND_52]], [[GUARD_COND_51]] +; CHECK-NEXT: [[GUARD_COND_54:%.*]] = and i1 [[GUARD_COND_53]], [[GUARD_COND_52]] +; CHECK-NEXT: [[GUARD_COND_55:%.*]] = and i1 [[GUARD_COND_54]], [[GUARD_COND_53]] +; CHECK-NEXT: [[GUARD_COND_56:%.*]] = and i1 [[GUARD_COND_55]], [[GUARD_COND_54]] +; CHECK-NEXT: [[GUARD_COND_57:%.*]] = and i1 [[GUARD_COND_56]], [[GUARD_COND_55]] +; CHECK-NEXT: [[GUARD_COND_58:%.*]] = and i1 [[GUARD_COND_57]], [[GUARD_COND_56]] +; CHECK-NEXT: [[GUARD_COND_59:%.*]] = and i1 [[GUARD_COND_58]], [[GUARD_COND_57]] +; CHECK-NEXT: [[GUARD_COND_60:%.*]] = and i1 [[GUARD_COND_59]], [[GUARD_COND_58]] +; CHECK-NEXT: [[GUARD_COND_61:%.*]] = and i1 [[GUARD_COND_60]], [[GUARD_COND_59]] +; CHECK-NEXT: [[GUARD_COND_62:%.*]] = and i1 [[GUARD_COND_61]], [[GUARD_COND_60]] +; CHECK-NEXT: [[GUARD_COND_63:%.*]] = and i1 [[GUARD_COND_62]], [[GUARD_COND_61]] +; CHECK-NEXT: [[GUARD_COND_64:%.*]] = and i1 [[GUARD_COND_63]], [[GUARD_COND_62]] +; CHECK-NEXT: [[GUARD_COND_65:%.*]] = and i1 [[GUARD_COND_64]], [[GUARD_COND_63]] +; CHECK-NEXT: [[GUARD_COND_66:%.*]] = and i1 [[GUARD_COND_65]], [[GUARD_COND_64]] +; CHECK-NEXT: [[GUARD_COND_67:%.*]] = and i1 [[GUARD_COND_66]], [[GUARD_COND_65]] +; CHECK-NEXT: [[GUARD_COND_68:%.*]] = and i1 [[GUARD_COND_67]], [[GUARD_COND_66]] +; CHECK-NEXT: [[GUARD_COND_69:%.*]] = and i1 [[GUARD_COND_68]], [[GUARD_COND_67]] +; CHECK-NEXT: [[GUARD_COND_70:%.*]] = and i1 [[GUARD_COND_69]], [[GUARD_COND_68]] +; CHECK-NEXT: [[GUARD_COND_71:%.*]] = and i1 [[GUARD_COND_70]], [[GUARD_COND_69]] +; CHECK-NEXT: [[GUARD_COND_72:%.*]] = and i1 [[GUARD_COND_71]], [[GUARD_COND_70]] +; CHECK-NEXT: [[GUARD_COND_73:%.*]] = and i1 [[GUARD_COND_72]], [[GUARD_COND_71]] +; CHECK-NEXT: [[GUARD_COND_74:%.*]] = and i1 [[GUARD_COND_73]], [[GUARD_COND_72]] +; CHECK-NEXT: [[GUARD_COND_75:%.*]] = and i1 [[GUARD_COND_74]], [[GUARD_COND_73]] +; CHECK-NEXT: [[GUARD_COND_76:%.*]] = and i1 [[GUARD_COND_75]], [[GUARD_COND_74]] +; CHECK-NEXT: [[GUARD_COND_77:%.*]] = and i1 [[GUARD_COND_76]], [[GUARD_COND_75]] +; CHECK-NEXT: [[GUARD_COND_78:%.*]] = and i1 [[GUARD_COND_77]], [[GUARD_COND_76]] +; CHECK-NEXT: [[GUARD_COND_79:%.*]] = and i1 [[GUARD_COND_78]], [[GUARD_COND_77]] +; CHECK-NEXT: [[GUARD_COND_80:%.*]] = and i1 [[GUARD_COND_79]], [[GUARD_COND_78]] +; CHECK-NEXT: [[GUARD_COND_81:%.*]] = and i1 [[GUARD_COND_80]], [[GUARD_COND_79]] +; CHECK-NEXT: [[GUARD_COND_82:%.*]] = and i1 [[GUARD_COND_81]], [[GUARD_COND_80]] +; CHECK-NEXT: [[GUARD_COND_83:%.*]] = and i1 [[GUARD_COND_82]], [[GUARD_COND_81]] +; CHECK-NEXT: [[GUARD_COND_84:%.*]] = and i1 [[GUARD_COND_83]], [[GUARD_COND_82]] +; CHECK-NEXT: [[GUARD_COND_85:%.*]] = and i1 [[GUARD_COND_84]], [[GUARD_COND_83]] +; CHECK-NEXT: [[GUARD_COND_86:%.*]] = and i1 [[GUARD_COND_85]], [[GUARD_COND_84]] +; CHECK-NEXT: [[GUARD_COND_87:%.*]] = and i1 [[GUARD_COND_86]], [[GUARD_COND_85]] +; CHECK-NEXT: [[GUARD_COND_88:%.*]] = and i1 [[GUARD_COND_87]], [[GUARD_COND_86]] +; CHECK-NEXT: [[GUARD_COND_89:%.*]] = and i1 [[GUARD_COND_88]], [[GUARD_COND_87]] +; CHECK-NEXT: [[GUARD_COND_90:%.*]] = and i1 [[GUARD_COND_89]], [[GUARD_COND_88]] +; CHECK-NEXT: [[GUARD_COND_91:%.*]] = and i1 [[GUARD_COND_90]], [[GUARD_COND_89]] +; CHECK-NEXT: [[GUARD_COND_92:%.*]] = and i1 [[GUARD_COND_91]], [[GUARD_COND_90]] +; CHECK-NEXT: [[GUARD_COND_93:%.*]] = and i1 [[GUARD_COND_92]], [[GUARD_COND_91]] +; CHECK-NEXT: [[GUARD_COND_94:%.*]] = and i1 [[GUARD_COND_93]], [[GUARD_COND_92]] +; CHECK-NEXT: [[GUARD_COND_95:%.*]] = and i1 [[GUARD_COND_94]], [[GUARD_COND_93]] +; CHECK-NEXT: [[GUARD_COND_96:%.*]] = and i1 [[GUARD_COND_95]], [[GUARD_COND_94]] +; CHECK-NEXT: [[GUARD_COND_97:%.*]] = and i1 [[GUARD_COND_96]], [[GUARD_COND_95]] +; CHECK-NEXT: [[GUARD_COND_98:%.*]] = and i1 [[GUARD_COND_97]], [[GUARD_COND_96]] +; CHECK-NEXT: [[GUARD_COND_99:%.*]] = and i1 [[GUARD_COND_98]], [[GUARD_COND_97]] ; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[GUARD_COND_99]]) ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 diff --git a/llvm/test/Transforms/LoopPredication/widened.ll b/llvm/test/Transforms/LoopPredication/widened.ll index 0cb5921..4624ab6 100644 --- a/llvm/test/Transforms/LoopPredication/widened.ll +++ b/llvm/test/Transforms/LoopPredication/widened.ll @@ -29,13 +29,17 @@ define i64 @iv_wider_type_rc_two_narrow_types(i32 %offA, i16 %offB, i8* %arrA, i ; CHECK-NEXT: [[IV_TRUNC_16:%.*]] = trunc i64 [[IV]] to i16 ; CHECK-NEXT: [[INDEXA:%.*]] = add i32 [[IV_TRUNC_32]], [[OFFA]] ; CHECK-NEXT: [[INDEXB:%.*]] = add i16 [[IV_TRUNC_16]], [[OFFB]] +; CHECK-NEXT: [[RCA:%.*]] = icmp ult i32 [[INDEXA]], [[LENGTHA]] +; CHECK-NEXT: [[RCB:%.*]] = icmp ult i16 [[INDEXB]], [[LENGTHB]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[RCA]], [[RCB]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WIDE_CHK]]) ; CHECK-NEXT: [[INDEXA_EXT:%.*]] = zext i32 [[INDEXA]] to i64 ; CHECK-NEXT: [[ADDRA:%.*]] = getelementptr inbounds i8, i8* [[ARRA]], i64 [[INDEXA_EXT]] -; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]] +; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]], align 1 ; CHECK-NEXT: [[INDEXB_EXT:%.*]] = zext i16 [[INDEXB]] to i64 ; CHECK-NEXT: [[ADDRB:%.*]] = getelementptr inbounds i8, i8* [[ARRB]], i64 [[INDEXB_EXT]] -; CHECK-NEXT: store i8 [[ELTA]], i8* [[ADDRB]] +; CHECK-NEXT: store i8 [[ELTA]], i8* [[ADDRB]], align 1 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[LATCH_CHECK:%.*]] = icmp ult i64 [[IV_NEXT]], 16 ; CHECK-NEXT: br i1 [[LATCH_CHECK]], label [[LOOP]], label [[EXIT:%.*]] @@ -102,15 +106,21 @@ define i64 @iv_rc_different_types(i32 %offA, i32 %offB, i8* %arrA, i8* %arrB, i6 ; CHECK-NEXT: [[IV_TRUNC:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT: [[INDEXA:%.*]] = add i32 [[IV_TRUNC]], [[OFFA]] ; CHECK-NEXT: [[INDEXB:%.*]] = add i32 [[IV_TRUNC]], [[OFFB]] +; CHECK-NEXT: [[RCA:%.*]] = icmp ult i32 [[INDEXA]], [[LENGTHA]] +; CHECK-NEXT: [[RCIV:%.*]] = icmp ult i64 [[IV]], [[MAX]] +; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[RCA]], [[RCIV]] +; CHECK-NEXT: [[RCB:%.*]] = icmp ult i32 [[INDEXB]], [[LENGTHB]] +; CHECK-NEXT: [[WIDE_CHK_FINAL:%.*]] = and i1 [[WIDE_CHK]], [[RCB]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP15]], i32 9) [ "deopt"() ] +; CHECK-NEXT: call void @llvm.assume(i1 [[WIDE_CHK_FINAL]]) ; CHECK-NEXT: [[INDEXA_EXT:%.*]] = zext i32 [[INDEXA]] to i64 ; CHECK-NEXT: [[ADDRA:%.*]] = getelementptr inbounds i8, i8* [[ARRA]], i64 [[INDEXA_EXT]] -; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]] +; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]], align 1 ; CHECK-NEXT: [[INDEXB_EXT:%.*]] = zext i32 [[INDEXB]] to i64 ; CHECK-NEXT: [[ADDRB:%.*]] = getelementptr inbounds i8, i8* [[ARRB]], i64 [[INDEXB_EXT]] -; CHECK-NEXT: [[ELTB:%.*]] = load i8, i8* [[ADDRB]] +; CHECK-NEXT: [[ELTB:%.*]] = load i8, i8* [[ADDRB]], align 1 ; CHECK-NEXT: [[RESULT:%.*]] = xor i8 [[ELTA]], [[ELTB]] -; CHECK-NEXT: store i8 [[RESULT]], i8* [[ADDRA]] +; CHECK-NEXT: store i8 [[RESULT]], i8* [[ADDRA]], align 1 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[LATCH_CHECK:%.*]] = icmp ult i64 [[IV]], 15 ; CHECK-NEXT: br i1 [[LATCH_CHECK]], label [[LOOP]], label [[EXIT:%.*]] @@ -167,9 +177,9 @@ define i64 @iv_rc_different_type(i32 %offA, i8* %arrA) { ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[RCA]], i32 9) [ "deopt"() ] ; CHECK-NEXT: [[INDEXA_EXT:%.*]] = zext i32 [[INDEXA]] to i64 ; CHECK-NEXT: [[ADDRA:%.*]] = getelementptr inbounds i8, i8* [[ARRA]], i64 [[INDEXA_EXT]] -; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]] +; CHECK-NEXT: [[ELTA:%.*]] = load i8, i8* [[ADDRA]], align 1 ; CHECK-NEXT: [[RES:%.*]] = add i8 [[ELTA]], 2 -; CHECK-NEXT: store i8 [[ELTA]], i8* [[ADDRA]] +; CHECK-NEXT: store i8 [[ELTA]], i8* [[ADDRA]], align 1 ; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 ; CHECK-NEXT: [[LATCH_CHECK:%.*]] = icmp sge i64 [[IV_NEXT]], 2 ; CHECK-NEXT: br i1 [[LATCH_CHECK]], label [[LOOP]], label [[EXIT:%.*]] -- 2.7.4