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
This commit is contained in:
Cameron McInally 2019-05-03 21:19:12 +00:00
parent 93f15c922f
commit be7138b467
2 changed files with 48 additions and 11 deletions

View File

@ -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;
}
};

View File

@ -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*>,