namespace llvm {
class GlobalValue;
+class Loop;
class Type;
class User;
class Value;
/// incurs significant execution cost.
virtual bool isLoweredToCall(const Function *F) const;
+ /// Parameters that control the generic loop unrolling transformation.
+ struct UnrollingPreferences {
+ /// The cost threshold for the unrolled loop, compared to
+ /// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body.
+ /// The unrolling factor is set such that the unrolled loop body does not
+ /// exceed this cost. Set this to UINT_MAX to disable the loop body cost
+ /// restriction.
+ unsigned Threshold;
+ /// The cost threshold for the unrolled loop when optimizing for size (set
+ /// to UINT_MAX to disable).
+ unsigned OptSizeThreshold;
+ /// A forced unrolling factor (the number of concatenated bodies of the
+ /// original loop in the unrolled loop body). When set to 0, the unrolling
+ /// transformation will select an unrolling factor based on the current cost
+ /// threshold and other factors.
+ unsigned Count;
+ /// Allow partial unrolling (unrolling of loops to expand the size of the
+ /// loop body, not only to eliminate small constant-trip-count loops).
+ bool Partial;
+ /// Allow runtime unrolling (unrolling of loops to expand the size of the
+ /// loop body even when the number of loop iterations is not known at compile
+ /// time).
+ bool Runtime;
+ };
+
+ /// \brief Get target-customized preferences for the generic loop unrolling
+ /// transformation. The caller will initialize UP with the current
+ /// target-independent defaults.
+ virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const;
+
/// @}
/// \name Scalar Target Information
CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P;
UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0);
+ UserAllowPartial = (P != -1) ||
+ (UnrollAllowPartial.getNumOccurrences() > 0);
+ UserCount = (C != -1) || (UnrollCount.getNumOccurrences() > 0);
initializeLoopUnrollPass(*PassRegistry::getPassRegistry());
}
unsigned CurrentCount;
unsigned CurrentThreshold;
bool CurrentAllowPartial;
+ bool UserCount; // CurrentCount is user-specified.
bool UserThreshold; // CurrentThreshold is user-specified.
+ bool UserAllowPartial; // CurrentAllowPartial is user-specified.
bool runOnLoop(Loop *L, LPPassManager &LPM);
<< "] Loop %" << Header->getName() << "\n");
(void)Header;
+ TargetTransformInfo::UnrollingPreferences UP;
+ UP.Threshold = CurrentThreshold;
+ UP.OptSizeThreshold = OptSizeUnrollThreshold;
+ UP.Count = CurrentCount;
+ UP.Partial = CurrentAllowPartial;
+ UP.Runtime = UnrollRuntime;
+ TTI.getUnrollingPreferences(L, UP);
+
// Determine the current unrolling threshold. While this is normally set
// from UnrollThreshold, it is overridden to a smaller value if the current
// function is marked as optimize-for-size, and the unroll threshold was
// not user specified.
- unsigned Threshold = CurrentThreshold;
+ unsigned Threshold = UserThreshold ? CurrentThreshold : UP.Threshold;
if (!UserThreshold &&
Header->getParent()->getAttributes().
hasAttribute(AttributeSet::FunctionIndex,
Attribute::OptimizeForSize))
- Threshold = OptSizeUnrollThreshold;
+ Threshold = UP.OptSizeThreshold;
// Find trip count and trip multiple if count is not available
unsigned TripCount = 0;
TripCount = SE->getSmallConstantTripCount(L, LatchBlock);
TripMultiple = SE->getSmallConstantTripMultiple(L, LatchBlock);
}
+
+ bool Runtime = UnrollRuntime.getNumOccurrences() == 0 ?
+ UP.Runtime : UnrollRuntime;
+
// Use a default unroll-count if the user doesn't specify a value
// and the trip count is a run-time value. The default is different
// for run-time or compile-time trip count loops.
- unsigned Count = CurrentCount;
- if (UnrollRuntime && CurrentCount == 0 && TripCount == 0)
+ unsigned Count = UserCount ? CurrentCount : UP.Count;
+ if (Runtime && Count == 0 && TripCount == 0)
Count = UnrollRuntimeCount;
if (Count == 0) {
if (TripCount != 1 && Size > Threshold) {
DEBUG(dbgs() << " Too large to fully unroll with count: " << Count
<< " because size: " << Size << ">" << Threshold << "\n");
- if (!CurrentAllowPartial && !(UnrollRuntime && TripCount == 0)) {
+ bool AllowPartial = UserAllowPartial ? CurrentAllowPartial : UP.Partial;
+ if (!AllowPartial && !(Runtime && TripCount == 0)) {
DEBUG(dbgs() << " will not try to unroll partially because "
<< "-unroll-allow-partial not given\n");
return false;
while (Count != 0 && TripCount%Count != 0)
Count--;
}
- else if (UnrollRuntime) {
+ else if (Runtime) {
// Reduce unroll count to be a lower power-of-two value
while (Count != 0 && Size > Threshold) {
Count >>= 1;
}
// Unroll the loop.
- if (!UnrollLoop(L, Count, TripCount, UnrollRuntime, TripMultiple, LI, &LPM))
+ if (!UnrollLoop(L, Count, TripCount, Runtime, TripMultiple, LI, &LPM))
return false;
return true;