summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Analysis
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2015-08-11 09:12:57 +0000
committerJames Molloy <james.molloy@arm.com>2015-08-11 09:12:57 +0000
commit134bec27226ab1d37cff44b04cef73b67321601b (patch)
tree694344ed69bba87532061b2dcfcdae634aee2dd6 /llvm/unittests/Analysis
parent1c78ca6a09cec862d6aad04e820dae98b71be9fc (diff)
downloadbcm5719-llvm-134bec27226ab1d37cff44b04cef73b67321601b.tar.gz
bcm5719-llvm-134bec27226ab1d37cff44b04cef73b67321601b.zip
Add support for floating-point minnum and maxnum
The select pattern recognition in ValueTracking (as used by InstCombine and SelectionDAGBuilder) only knew about integer patterns. This teaches it about minimum and maximum operations. matchSelectPattern() has been extended to return a struct containing the existing Flavor and a new enum defining the pattern's behavior when given one NaN operand. C minnum() is defined to return the non-NaN operand in this case, but the idiomatic C "a < b ? a : b" would return the NaN operand. ARM and AArch64 at least have different instructions for these different cases. llvm-svn: 244580
Diffstat (limited to 'llvm/unittests/Analysis')
-rw-r--r--llvm/unittests/Analysis/CMakeLists.txt1
-rw-r--r--llvm/unittests/Analysis/ValueTrackingTest.cpp148
2 files changed, 149 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index 35a6d92ce17..28d35ceec92 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -13,4 +13,5 @@ add_llvm_unittest(AnalysisTests
LazyCallGraphTest.cpp
ScalarEvolutionTest.cpp
MixedTBAATest.cpp
+ ValueTrackingTest.cpp
)
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
new file mode 100644
index 00000000000..b5ad01968b9
--- /dev/null
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -0,0 +1,148 @@
+//===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MatchSelectPatternTest : public testing::Test {
+protected:
+ void parseAssembly(const char *Assembly) {
+ SMDiagnostic Error;
+ M = parseAssemblyString(Assembly, Error, getGlobalContext());
+
+ std::string errMsg;
+ raw_string_ostream os(errMsg);
+ Error.print("", os);
+
+ // A failure here means that the test itself is buggy.
+ if (!M)
+ report_fatal_error(os.str());
+
+ Function *F = M->getFunction("test");
+ if (F == nullptr)
+ report_fatal_error("Test must have a function named @test");
+
+ A = nullptr;
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if (I->hasName()) {
+ if (I->getName() == "A")
+ A = &*I;
+ }
+ }
+ if (A == nullptr)
+ report_fatal_error("@test must have an instruction %A");
+ }
+
+ void expectPattern(const SelectPatternResult &P) {
+ Value *LHS, *RHS;
+ Instruction::CastOps CastOp;
+ SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
+ EXPECT_EQ(P.Flavor, R.Flavor);
+ EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
+ EXPECT_EQ(P.Ordered, R.Ordered);
+ }
+
+ std::unique_ptr<Module> M;
+ Instruction *A, *B;
+};
+
+}
+
+TEST_F(MatchSelectPatternTest, SimpleFMin) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ult float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
+}
+
+TEST_F(MatchSelectPatternTest, SimpleFMax) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ogt float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp olt float 5.0, %a\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax2) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp olt float %a, 5.0\n"
+ " %A = select i1 %1, float 5.0, float %a\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax3) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ult float %a, 5.0\n"
+ " %A = select i1 %1, float 5.0, float %a\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
+}
+
+TEST_F(MatchSelectPatternTest, FastFMin) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp nnan olt float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
+}
+
+TEST_F(MatchSelectPatternTest, FMinConstantZero) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ole float %a, 0.0\n"
+ " %A = select i1 %1, float %a, float 0.0\n"
+ " ret float %A\n"
+ "}\n");
+ // This shouldn't be matched, as %a could be -0.0.
+ expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp nsz ole float %a, 0.0\n"
+ " %A = select i1 %1, float %a, float 0.0\n"
+ " ret float %A\n"
+ "}\n");
+ // But this should be, because we've ignored signed zeroes.
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
+}
OpenPOWER on IntegriCloud