From 80fb24a66f54bd305b9c32f8f257447a14a78629 Mon Sep 17 00:00:00 2001 From: Cameron McInally Date: Fri, 3 May 2019 21:19:12 +0000 Subject: [PATCH] Update PatternMatcher for FNeg Match both FNeg(X) and FSub(+-0.0, X) in FNeg_match Differential Revision: https://reviews.llvm.org/D61520 llvm-svn: 359936 --- include/llvm/IR/PatternMatch.h | 30 +++++++++++++++++++----------- unittests/IR/PatternMatch.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 6c51d487737..d310f07d336 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -667,18 +667,26 @@ template struct FNeg_match { FNeg_match(const Op_t &Op) : X(Op) {} template bool match(OpTy *V) { auto *FPMO = dyn_cast(V); - if (!FPMO || FPMO->getOpcode() != Instruction::FSub) - return false; - if (FPMO->hasNoSignedZeros()) { - // With 'nsz', any zero goes. - if (!cstfp_pred_ty().match(FPMO->getOperand(0))) - return false; - } else { - // Without 'nsz', we need fsub -0.0, X exactly. - if (!cstfp_pred_ty().match(FPMO->getOperand(0))) - return false; + if (!FPMO) return false; + + if (FPMO->getOpcode() == Instruction::FNeg) + return X.match(FPMO->getOperand(0)); + + if (FPMO->getOpcode() == Instruction::FSub) { + if (FPMO->hasNoSignedZeros()) { + // With 'nsz', any zero goes. + if (!cstfp_pred_ty().match(FPMO->getOperand(0))) + return false; + } else { + // Without 'nsz', we need fsub -0.0, X exactly. + if (!cstfp_pred_ty().match(FPMO->getOperand(0))) + return false; + } + + return X.match(FPMO->getOperand(1)); } - return X.match(FPMO->getOperand(1)); + + return false; } }; diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp index e380fb90ad7..de47975e7c6 100644 --- a/unittests/IR/PatternMatch.cpp +++ b/unittests/IR/PatternMatch.cpp @@ -589,6 +589,35 @@ TEST_F(PatternMatchTest, VectorUndefFloat) { EXPECT_TRUE(match(VectorZeroUndef, m_AnyZeroFP())); } +TEST_F(PatternMatchTest, FloatingPointFNeg) { + Type *FltTy = IRB.getFloatTy(); + Value *One = ConstantFP::get(FltTy, 1.0); + Value *Z = ConstantFP::get(FltTy, 0.0); + Value *NZ = ConstantFP::get(FltTy, -0.0); + Value *V = IRB.CreateFNeg(One); + Value *V1 = IRB.CreateFSub(NZ, One); + Value *V2 = IRB.CreateFSub(Z, One); + Value *V3 = IRB.CreateFAdd(NZ, One); + Value *Match; + + // Test FNeg(1.0) + EXPECT_TRUE(match(V, m_FNeg(m_Value(Match)))); + EXPECT_EQ(One, Match); + + // Test FSub(-0.0, 1.0) + EXPECT_TRUE(match(V1, m_FNeg(m_Value(Match)))); + EXPECT_EQ(One, Match); + + // Test FSub(0.0, 1.0) + EXPECT_FALSE(match(V2, m_FNeg(m_Value(Match)))); + cast(V2)->setHasNoSignedZeros(true); + EXPECT_TRUE(match(V2, m_FNeg(m_Value(Match)))); + EXPECT_EQ(One, Match); + + // Test FAdd(-0.0, 1.0) + EXPECT_FALSE(match(V3, m_FNeg(m_Value(Match)))); +} + template struct MutableConstTest : PatternMatchTest { }; typedef ::testing::Types,