[SimpleLoopUnswitch] Ignore inner loops when injecting invariant conditions. PR60736
authorMax Kazantsev <mkazantsev@azul.com>
Tue, 14 Feb 2023 12:26:15 +0000 (19:26 +0700)
committerMax Kazantsev <mkazantsev@azul.com>
Tue, 14 Feb 2023 12:35:34 +0000 (19:35 +0700)
The transform and all related updates don't expect the situation when candidate
is from an inner loop. I think we *might* still do something in this case, but
the current implementation doesn't expect this and does incorrect loop info
updates in this situation.

Details: https://github.com/llvm/llvm-project/issues/60736

llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
llvm/test/Transforms/SimpleLoopUnswitch/pr60736.ll

index 3ce3e00..9304d16 100644 (file)
@@ -2963,6 +2963,8 @@ injectPendingInvariantConditions(NonTrivialUnswitchCandidate Candidate, Loop &L,
   assert(Candidate.hasPendingInjection() && "Nothing to inject!");
   BasicBlock *Preheader = L.getLoopPreheader();
   assert(Preheader && "Loop is not in simplified form?");
+  assert(LI.getLoopFor(Candidate.TI->getParent()) == &L &&
+         "Unswitching branch of inner loop!");
 
   auto Pred = Candidate.PendingInjection->Pred;
   auto *LHS = Candidate.PendingInjection->LHS;
@@ -3112,6 +3114,9 @@ static bool collectUnswitchCandidatesWithInjections(
     Value *LHS = nullptr, *RHS = nullptr;
     BasicBlock *IfTrue = nullptr, *IfFalse = nullptr;
     auto *BB = DTN->getBlock();
+    // Ignore inner loops.
+    if (LI.getLoopFor(BB) != &L)
+      continue;
     auto *Term = BB->getTerminator();
     if (!match(Term, m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)),
                           m_BasicBlock(IfTrue), m_BasicBlock(IfFalse))))
index 5407d2c..16255cb 100644 (file)
@@ -1,9 +1,57 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -simple-loop-unswitch-inject-invariant-conditions=true -passes='loop(simple-loop-unswitch<nontrivial>,loop-instsimplify)' -S | FileCheck %s
-; REQUIRES: asserts
-; XFAIL: *
 
 define void @test() {
-; CHECK-LABEL: test
+; CHECK-LABEL: @test(
+; CHECK-NEXT:  bb:
+; CHECK-NEXT:    [[TMP:%.*]] = call i1 @llvm.experimental.widenable.condition()
+; CHECK-NEXT:    [[TMP1:%.*]] = load atomic i32, ptr addrspace(1) poison unordered, align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load atomic i32, ptr addrspace(1) poison unordered, align 8
+; CHECK-NEXT:    br label [[BB3:%.*]]
+; CHECK:       bb3:
+; CHECK-NEXT:    [[TMP_FR:%.*]] = freeze i1 [[TMP]]
+; CHECK-NEXT:    br i1 [[TMP_FR]], label [[BB3_SPLIT:%.*]], label [[BB3_SPLIT_US:%.*]]
+; CHECK:       bb3.split.us:
+; CHECK-NEXT:    br label [[BB4_US:%.*]]
+; CHECK:       bb4.us:
+; CHECK-NEXT:    [[TMP5_US:%.*]] = phi i32 [ poison, [[BB3_SPLIT_US]] ]
+; CHECK-NEXT:    [[TMP6_US:%.*]] = phi i32 [ poison, [[BB3_SPLIT_US]] ]
+; CHECK-NEXT:    [[TMP7_US:%.*]] = add nuw nsw i32 [[TMP6_US]], 2
+; CHECK-NEXT:    [[TMP8_US:%.*]] = icmp ult i32 [[TMP7_US]], [[TMP2]]
+; CHECK-NEXT:    br i1 [[TMP8_US]], label [[BB9_US:%.*]], label [[BB16_SPLIT_US:%.*]], !prof [[PROF0:![0-9]+]]
+; CHECK:       bb9.us:
+; CHECK-NEXT:    br label [[BB17_SPLIT_US:%.*]]
+; CHECK:       bb16.split.us:
+; CHECK-NEXT:    br label [[BB16:%.*]]
+; CHECK:       bb17.split.us:
+; CHECK-NEXT:    br label [[BB17:%.*]]
+; CHECK:       bb3.split:
+; CHECK-NEXT:    br label [[BB4:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    [[TMP5:%.*]] = phi i32 [ poison, [[BB3_SPLIT]] ], [ [[TMP14:%.*]], [[BB13:%.*]] ]
+; CHECK-NEXT:    [[TMP6:%.*]] = phi i32 [ poison, [[BB3_SPLIT]] ], [ [[TMP5]], [[BB13]] ]
+; CHECK-NEXT:    [[TMP7:%.*]] = add nuw nsw i32 [[TMP6]], 2
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ult i32 [[TMP7]], [[TMP2]]
+; CHECK-NEXT:    br i1 [[TMP8]], label [[BB9:%.*]], label [[BB16_SPLIT:%.*]], !prof [[PROF0]]
+; CHECK:       bb9:
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp ult i32 [[TMP7]], [[TMP1]]
+; CHECK-NEXT:    br i1 [[TMP10]], label [[BB12:%.*]], label [[BB17_SPLIT:%.*]], !prof [[PROF0]]
+; CHECK:       bb12:
+; CHECK-NEXT:    br i1 true, label [[BB15:%.*]], label [[BB13]]
+; CHECK:       bb13:
+; CHECK-NEXT:    [[TMP14]] = add nuw nsw i32 [[TMP5]], 1
+; CHECK-NEXT:    br label [[BB4]]
+; CHECK:       bb15:
+; CHECK-NEXT:    br label [[BB3]]
+; CHECK:       bb16.split:
+; CHECK-NEXT:    br label [[BB16]]
+; CHECK:       bb16:
+; CHECK-NEXT:    ret void
+; CHECK:       bb17.split:
+; CHECK-NEXT:    br label [[BB17]]
+; CHECK:       bb17:
+; CHECK-NEXT:    ret void
+;
 bb:
   %tmp = call i1 @llvm.experimental.widenable.condition()
   %tmp1 = load atomic i32, ptr addrspace(1) poison unordered, align 8