Index: lib/Target/Hexagon/HexagonTargetTransformInfo.cpp =================================================================== --- lib/Target/Hexagon/HexagonTargetTransformInfo.cpp +++ lib/Target/Hexagon/HexagonTargetTransformInfo.cpp @@ -41,6 +41,14 @@ void HexagonTTIImpl::getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP) { UP.Runtime = UP.Partial = true; + // Only try to peel innermost loops with small runtime trip counts. + if (L && L->empty() && + SE.getSmallConstantTripCount(L) == 0 && + SE.getSmallConstantMaxTripCount(L) > 0 && + SE.getSmallConstantMaxTripCount(L) <= 5) { + UP.PeelCount = 2; + UP.AllowPeeling = true; + } } unsigned HexagonTTIImpl::getNumberOfRegisters(bool vector) const { Index: lib/Transforms/Utils/LoopUnrollPeel.cpp =================================================================== --- lib/Transforms/Utils/LoopUnrollPeel.cpp +++ lib/Transforms/Utils/LoopUnrollPeel.cpp @@ -221,13 +221,16 @@ TargetTransformInfo::UnrollingPreferences &UP, unsigned &TripCount, ScalarEvolution &SE) { assert(LoopSize > 0 && "Zero loop size is not allowed!"); - UP.PeelCount = 0; - if (!canPeel(L)) + if (!canPeel(L)) { + UP.PeelCount = 0; return; + } // Only try to peel innermost loops. - if (!L->empty()) + if (!L->empty()) { + UP.PeelCount = 0; return; + } // Here we try to get rid of Phis which become invariants after 1, 2, ..., N // iterations of the loop. For this we compute the number for iterations after @@ -240,7 +243,9 @@ SmallDenseMap IterationsToInvariance; // Now go through all Phis to calculate their the number of iterations they // need to become invariants. - unsigned DesiredPeelCount = 0; + // Start the max computation with the UP.PeelCount value set by the target + // in TTI.getUnrollingPreferences or by the flag -unroll-peel-count. + unsigned DesiredPeelCount = UP.PeelCount; BasicBlock *BackEdge = L->getLoopLatch(); assert(BackEdge && "Loop is not in simplified form?"); for (auto BI = L->getHeader()->begin(); isa(&*BI); ++BI) { @@ -271,8 +276,10 @@ // Bail if we know the statically calculated trip count. // In this case we rather prefer partial unrolling. - if (TripCount) + if (TripCount) { + UP.PeelCount = 0; return; + } // If the user provided a peel count, use that. bool UserPeelCount = UnrollForcePeelCount.getNumOccurrences() > 0; @@ -290,8 +297,10 @@ // our estimates of the trip count are not reliable enough. if (UP.AllowPeeling && L->getHeader()->getParent()->hasProfileData()) { Optional PeelCount = getLoopEstimatedTripCount(L); - if (!PeelCount) + if (!PeelCount) { + UP.PeelCount = 0; return; + } DEBUG(dbgs() << "Profile-based estimated trip count is " << *PeelCount << "\n"); @@ -309,6 +318,7 @@ DEBUG(dbgs() << "Max peel cost: " << UP.Threshold << "\n"); } } + UP.PeelCount = 0; } /// \brief Update the branch weights of the latch of a peeled-off loop Index: test/Transforms/LoopUnroll/Hexagon/peel-small-loop.ll =================================================================== --- /dev/null +++ test/Transforms/LoopUnroll/Hexagon/peel-small-loop.ll @@ -0,0 +1,38 @@ +; RUN: opt -loop-unroll -mtriple=hexagon -S < %s | FileCheck %s +; Check that the loop is peeled twice for Hexagon. +; CHECK: while.body.peel +; CHECK: while.body.peel2 + +%struct.STREAM = type { %union.anon, i32, i32 } +%union.anon = type { i32* } + +define void @function(%struct.STREAM* nocapture readonly %b) local_unnamed_addr { +entry: + %bitPtr3 = getelementptr inbounds %struct.STREAM, %struct.STREAM* %b, i32 0, i32 2 + %0 = load i32, i32* %bitPtr3, align 4 + %cmp11 = icmp ult i32 %0, 32 + br i1 %cmp11, label %while.body.preheader, label %do.end + +while.body.preheader: + %value2 = getelementptr inbounds %struct.STREAM, %struct.STREAM* %b, i32 0, i32 1 + %1 = load i32, i32* %value2, align 4 + %w = getelementptr inbounds %struct.STREAM, %struct.STREAM* %b, i32 0, i32 0, i32 0 + %2 = load i32*, i32** %w, align 4 + br label %while.body + +while.body: + %bitPtr.014 = phi i32 [ %add, %while.body ], [ %0, %while.body.preheader ] + %value.013 = phi i32 [ %shl, %while.body ], [ %1, %while.body.preheader ] + %ptr.012 = phi i32* [ %incdec.ptr, %while.body ], [ %2, %while.body.preheader ] + %add = add nuw i32 %bitPtr.014, 8 + %shr = lshr i32 %value.013, 24 + %incdec.ptr = getelementptr inbounds i32, i32* %ptr.012, i32 1 + store i32 %shr, i32* %ptr.012, align 4 + %shl = shl i32 %value.013, 8 + %cmp = icmp ult i32 %add, 17 + br i1 %cmp, label %while.body, label %do.end + +do.end: + ret void +} +