]> granicus.if.org Git - llvm/commitdiff
[LoopPred] Be uniform about proving generated conditions
authorPhilip Reames <listmail@philipreames.com>
Mon, 1 Apr 2019 16:26:08 +0000 (16:26 +0000)
committerPhilip Reames <listmail@philipreames.com>
Mon, 1 Apr 2019 16:26:08 +0000 (16:26 +0000)
We'd been optimizing the case where the predicate was obviously true, do the same for the false case.  Mostly just for completeness sake, but also may improve compile time in loops which will exit through the guard.  Such loops are presumed rare in fastpath code, but may be present down untaken paths, so optimizing for them is still useful.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357408 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/LoopPredication.cpp
test/Transforms/LoopPredication/basic.ll

index 6257f419459f6964a7fea255e99ced4ecf87141d..ccecc80746efb47b9e8579bf159028fd6f401d6c 100644 (file)
@@ -396,6 +396,9 @@ Value *LoopPredication::expandCheck(SCEVExpander &Expander,
 
   if (SE->isLoopEntryGuardedByCond(L, Pred, LHS, RHS))
     return Builder.getTrue();
+  if (SE->isLoopEntryGuardedByCond(L, ICmpInst::getInversePredicate(Pred),
+                                   LHS, RHS))
+    return Builder.getFalse();
 
   Instruction *InsertAt = &*Builder.GetInsertPoint();
   Value *LHSV = Expander.expandCodeFor(LHS, Ty, InsertAt);
index 95de26a563280c71e438ea0db859b5032c6f6448..afb92f263cb656f14d1b300ce1d258b05bd9a762 100644 (file)
@@ -1544,3 +1544,52 @@ exit:
   %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
   ret i32 %result
 }
+
+
+; This is a case where the length information tells us that the guard
+; must trigger on some iteration.
+define i32 @provably_taken(i32* %array, i32* %length.ptr) {
+; CHECK-LABEL: @provably_taken(
+; CHECK-NEXT:  loop.preheader:
+; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !1
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i1 [[TMP0]], false
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; 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:    call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ]
+; 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
+; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
+; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
+; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200
+; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
+; CHECK-NEXT:    ret i32 [[RESULT]]
+;
+loop.preheader:
+  %length = load i32, i32* %length.ptr, !range !{i32 0, i32 50}
+  br label %loop
+
+loop:
+  %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
+  %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
+  %within.bounds = icmp ult i32 %i, %length
+  call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
+
+  %i.i64 = zext i32 %i to i64
+  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
+  %array.i = load i32, i32* %array.i.ptr, align 4
+  %loop.acc.next = add i32 %loop.acc, %array.i
+
+  %i.next = add nuw i32 %i, 1
+  %continue = icmp slt i32 %i.next, 200
+  br i1 %continue, label %loop, label %exit
+
+exit:
+  %result = phi i32 [ %loop.acc.next, %loop ]
+  ret i32 %result
+}