diff options
| -rw-r--r-- | llvm/include/llvm/IR/PatternMatch.h | 30 | ||||
| -rw-r--r-- | llvm/unittests/IR/PatternMatch.cpp | 29 |
2 files changed, 48 insertions, 11 deletions
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 6c51d487737..d310f07d336 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -667,18 +667,26 @@ template <typename Op_t> struct FNeg_match { FNeg_match(const Op_t &Op) : X(Op) {} template <typename OpTy> bool match(OpTy *V) { auto *FPMO = dyn_cast<FPMathOperator>(V); - if (!FPMO || FPMO->getOpcode() != Instruction::FSub) - return false; - if (FPMO->hasNoSignedZeros()) { - // With 'nsz', any zero goes. - if (!cstfp_pred_ty<is_any_zero_fp>().match(FPMO->getOperand(0))) - return false; - } else { - // Without 'nsz', we need fsub -0.0, X exactly. - if (!cstfp_pred_ty<is_neg_zero_fp>().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<is_any_zero_fp>().match(FPMO->getOperand(0))) + return false; + } else { + // Without 'nsz', we need fsub -0.0, X exactly. + if (!cstfp_pred_ty<is_neg_zero_fp>().match(FPMO->getOperand(0))) + return false; + } + + return X.match(FPMO->getOperand(1)); } - return X.match(FPMO->getOperand(1)); + + return false; } }; diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index e380fb90ad7..de47975e7c6 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/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<Instruction>(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 <typename T> struct MutableConstTest : PatternMatchTest { }; typedef ::testing::Types<std::tuple<Value*, Instruction*>, |

