From d47b5c7bedf2c2439628c4ba7212c00db5f97854 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 28 Sep 2018 21:36:43 +0000 Subject: [PATCH] [ValueTracking] Allow select patterns to work on FP vectors Summary: This CL allows constant vectors of floats to be recognized as non-NaN and non-zero in select patterns. This change makes `matchSelectPattern` more powerful generally, but was motivated specifically because I wanted fminnan and fmaxnan to be created for vector versions of the scalar patterns they are created for. Tested with check-all on all targets. A testcase in the WebAssembly backend that tests the non-nan codepath is in an upcoming CL. Reviewers: aheejin, dschuff Subscribers: sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D52324 llvm-svn: 343364 --- llvm/lib/Analysis/ValueTracking.cpp | 22 ++++++++++ llvm/unittests/Analysis/ValueTrackingTest.cpp | 58 +++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 495324f..02d0717 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4397,12 +4397,34 @@ static bool isKnownNonNaN(const Value *V, FastMathFlags FMF) { if (auto *C = dyn_cast(V)) return !C->isNaN(); + + if (auto *C = dyn_cast(V)) { + if (!C->getElementType()->isFloatingPointTy()) + return false; + for (unsigned I = 0, E = C->getNumElements(); I < E; ++I) { + if (C->getElementAsAPFloat(I).isNaN()) + return false; + } + return true; + } + return false; } static bool isKnownNonZero(const Value *V) { if (auto *C = dyn_cast(V)) return !C->isZero(); + + if (auto *C = dyn_cast(V)) { + if (!C->getElementType()->isFloatingPointTy()) + return false; + for (unsigned I = 0, E = C->getNumElements(); I < E; ++I) { + if (C->getElementAsAPFloat(I).isZero()) + return false; + } + return true; + } + return false; } diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index cfdf264..f391ca1 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -149,6 +149,64 @@ TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) { expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); } +TEST_F(MatchSelectPatternTest, VectorFMinNaN) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " \n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> \n" + " ret <4 x float> %A\n" + "}\n"); + // Check that pattern matching works on vectors where each lane has the same + // unordered pattern. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ole <4 x float> %a, \n" + " \n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> \n" + " ret <4 x float> %A\n" + "}\n"); + // Check that pattern matching works on vectors where each lane has the same + // ordered pattern. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, VectorNotFMinNaN) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " \n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> \n" + " ret <4 x float> %A\n" + "}\n"); + // The lane that contains a NaN (0x7ff80...) behaves like a + // non-NaN-propagating min and the other lines behave like a NaN-propagating + // min, so check that neither is returned. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + +TEST_F(MatchSelectPatternTest, VectorNotFMinZero) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " \n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> \n" + " ret <4 x float> %A\n" + "}\n"); + // Always selects the second lane of %a if it is positive or negative zero, so + // this is stricter than a min. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + TEST_F(MatchSelectPatternTest, DoubleCastU) { parseAssembly( "define i32 @test(i8 %a, i8 %b) {\n" -- 2.7.4