@@ -88,7 +88,7 @@ static Instruction *lookThroughAnd(PHINode *Phi, Type *&RT,
88
88
}
89
89
90
90
// / Compute the minimal bit width needed to represent a reduction whose exit
91
- // / instruction is given by Exit.
91
+ // / instruction is given by Exit, along with its signedness .
92
92
static std::pair<Type *, bool > computeRecurrenceType (Instruction *Exit,
93
93
DemandedBits *DB,
94
94
AssumptionCache *AC,
@@ -255,7 +255,7 @@ bool RecurrenceDescriptor::AddReductionVar(
255
255
SmallPtrSet<Instruction *, 4 > CastInsts;
256
256
unsigned MinWidthCastToRecurrenceType;
257
257
Instruction *Start = Phi;
258
- bool IsSigned = false ;
258
+ bool IsResultSigned = false , IsReduxSigned = false ;
259
259
260
260
SmallPtrSet<Instruction *, 8 > VisitedInsts;
261
261
SmallVector<Instruction *, 8 > Worklist;
@@ -396,6 +396,7 @@ bool RecurrenceDescriptor::AddReductionVar(
396
396
// state accurate while processing the worklist?
397
397
if (ReduxDesc.getRecKind () != RecurKind::None)
398
398
Kind = ReduxDesc.getRecKind ();
399
+ IsReduxSigned = ReduxDesc.isSigned ();
399
400
}
400
401
401
402
bool IsASelect = isa<SelectInst>(Cur);
@@ -565,7 +566,7 @@ bool RecurrenceDescriptor::AddReductionVar(
565
566
// smaller type. We should just generate a correctly typed expression
566
567
// to begin with.
567
568
Type *ComputedType;
568
- std::tie (ComputedType, IsSigned ) =
569
+ std::tie (ComputedType, IsResultSigned ) =
569
570
computeRecurrenceType (ExitInstruction, DB, AC, DT);
570
571
if (ComputedType != RecurrenceType)
571
572
return false ;
@@ -595,8 +596,9 @@ bool RecurrenceDescriptor::AddReductionVar(
595
596
596
597
// Save the description of this reduction variable.
597
598
RecurrenceDescriptor RD (RdxStart, ExitInstruction, IntermediateStore, Kind,
598
- FMF, ExactFPMathInst, RecurrenceType, IsSigned,
599
- IsOrdered, CastInsts, MinWidthCastToRecurrenceType);
599
+ FMF, ExactFPMathInst, RecurrenceType, IsResultSigned,
600
+ IsReduxSigned, IsOrdered, CastInsts,
601
+ MinWidthCastToRecurrenceType);
600
602
RedDes = RD;
601
603
602
604
return true ;
@@ -700,47 +702,59 @@ RecurrenceDescriptor::isFindLastIVPattern(Loop *TheLoop, PHINode *OrigPhi,
700
702
m_Value (NonRdxPhi)))))
701
703
return InstDesc (false , I);
702
704
703
- auto IsIncreasingLoopInduction = [&](Value *V) {
705
+ // Returns a non-nullopt boolean indicating the signedness of the recurrence
706
+ // when a valid FindLastIV pattern is found.
707
+ auto GetInductionSignedness = [&](Value *V) -> std::optional<bool > {
704
708
Type *Ty = V->getType ();
705
709
if (!SE.isSCEVable (Ty))
706
- return false ;
710
+ return std::nullopt ;
707
711
708
712
auto *AR = dyn_cast<SCEVAddRecExpr>(SE.getSCEV (V));
709
713
if (!AR || AR->getLoop () != TheLoop)
710
- return false ;
714
+ return std::nullopt ;
711
715
712
716
const SCEV *Step = AR->getStepRecurrence (SE);
713
717
if (!SE.isKnownPositive (Step))
714
- return false ;
718
+ return std::nullopt ;
715
719
716
- const ConstantRange IVRange = SE.getSignedRange (AR);
717
- unsigned NumBits = Ty->getIntegerBitWidth ();
718
720
// Keep the minimum value of the recurrence type as the sentinel value.
719
721
// The maximum acceptable range for the increasing induction variable,
720
722
// called the valid range, will be defined as
721
723
// [<sentinel value> + 1, <sentinel value>)
722
- // where <sentinel value> is SignedMin (<recurrence type>)
724
+ // where <sentinel value> is [Signed|Unsigned]Min (<recurrence type>)
723
725
// TODO: This range restriction can be lifted by adding an additional
724
726
// virtual OR reduction.
725
- const APInt Sentinel = APInt::getSignedMinValue (NumBits);
726
- const ConstantRange ValidRange =
727
- ConstantRange::getNonEmpty (Sentinel + 1 , Sentinel);
728
- LLVM_DEBUG (dbgs () << " LV: FindLastIV valid range is " << ValidRange
729
- << " , and the signed range of " << *AR << " is "
730
- << IVRange << " \n " );
731
- // Ensure the induction variable does not wrap around by verifying that its
732
- // range is fully contained within the valid range.
733
- return ValidRange.contains (IVRange);
727
+ auto CheckRange = [&](bool IsSigned) {
728
+ const ConstantRange IVRange =
729
+ IsSigned ? SE.getSignedRange (AR) : SE.getUnsignedRange (AR);
730
+ unsigned NumBits = Ty->getIntegerBitWidth ();
731
+ const APInt Sentinel = IsSigned ? APInt::getSignedMinValue (NumBits)
732
+ : APInt::getMinValue (NumBits);
733
+ const ConstantRange ValidRange =
734
+ ConstantRange::getNonEmpty (Sentinel + 1 , Sentinel);
735
+ LLVM_DEBUG (dbgs () << " LV: FindLastIV valid range is " << ValidRange
736
+ << " , and the range of " << *AR << " is " << IVRange
737
+ << " \n " );
738
+
739
+ // Ensure the induction variable does not wrap around by verifying that
740
+ // its range is fully contained within the valid range.
741
+ return ValidRange.contains (IVRange);
742
+ };
743
+ if (CheckRange (true ))
744
+ return true ;
745
+ if (CheckRange (false ))
746
+ return false ;
747
+ return std::nullopt;
734
748
};
735
749
736
750
// We are looking for selects of the form:
737
751
// select(cmp(), phi, increasing_loop_induction) or
738
752
// select(cmp(), increasing_loop_induction, phi)
739
753
// TODO: Support for monotonically decreasing induction variable
740
- if (! IsIncreasingLoopInduction (NonRdxPhi))
741
- return InstDesc (false , I );
754
+ if (auto IsSigned = GetInductionSignedness (NonRdxPhi))
755
+ return InstDesc (I, RecurKind::FindLastIV, *IsSigned );
742
756
743
- return InstDesc (I, RecurKind::FindLastIV );
757
+ return InstDesc (false , I );
744
758
}
745
759
746
760
RecurrenceDescriptor::InstDesc
0 commit comments