For a min and max reduction idioms, the identity (i.e. neutral) element
should be datatype's highest and lowest possible values respectively.
Current implementation in IVDescriptors incorrectly returns -Inf for FMin
reduction and +Inf for FMax reduction. This patch fixes this bug which
was causing incorrect reduction computation results in loops vectorized
by LV.
Details
Diff Detail
Event Timeline
Do we have any tests for Max as well as Min? It looks like the llvm/test/Transforms/LoopVectorize/AArch64/scalable-reduction-inloop-cond.ll test may need updating.
Should these be guarded with an FMF check?
The enum definition says:
FMin, ///< FP min implemented in terms of select(cmp()). FMax, ///< FP max implemented in terms of select(cmp()).
So if we have a NaN input:
fmin(NaN, Inf) --> select (fcmp olt NaN, Inf), NaN, Inf --> Inf (so the NaN input did not survive)
Is it possible to write unit-tests to check these directly? I see a llvm/unittests/Analysis/IVDescriptorsTest.cpp test file...
Thanks for the reviews! I've addressed the comments below -
I've added new tests in llvm/unittests/Analysis/IVDescriptorsTest.cpp to cover both FMin and FMax reductions. Updated the LIT test as well.
Do you mean that identity value computation for FMin/FMax should be guarded with a FMF.noNaNs() check? What would be the identity value when the flag is absent?
Is it possible to write unit-tests to check these directly? I see a llvm/unittests/Analysis/IVDescriptorsTest.cpp test file...
I've updated the test file with new tests, I can extend this for testing missing nnan flag scenario as well.
Do you mean that identity value computation for FMin/FMax should be guarded with a FMF.noNaNs() check? What would be the identity value when the flag is absent?
Yes, I'm not sure what it means if we don't have FMF.noNaNs(). Is it possible to create this recurrence without that FMF? If not, can we assert that FMF.noNaNs() is set?
Looks like the following code in RecurrenceDescriptor::isRecurrenceInstr guarantees that nnan flag is set for FMin/FMax reductions -
case Instruction::FCmp: case Instruction::ICmp: case Instruction::Call: if (isSelectCmpRecurrenceKind(Kind)) return isSelectCmpPattern(L, OrigPhi, I, Prev); if (isIntMinMaxRecurrenceKind(Kind) || (((FuncFMF.noNaNs() && FuncFMF.noSignedZeros()) || (isa<FPMathOperator>(I) && I->hasNoNaNs() && I->hasNoSignedZeros())) && isFPMinMaxRecurrenceKind(Kind))) return isMinMaxPattern(I, Kind, Prev);
I've added asserts in the latest diff to check that FMF.noNaNs() is set.
Yes, I think it would be better to keep this assert in-sync with the checks in RecurrenceDescriptor::isRecurrenceInstr. I have updated the asserts and unit-tests in latest diff.
Thanks for the reviews and approval! I don't have access to commit this change. @spatel can you commit this revision to llvm trunk?