diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 7c0583422655..dd30072ce571 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -659,11 +659,32 @@ inline BinaryOp_match m_FSub(const LHS &L, return BinaryOp_match(L, R); } +template struct FNeg_match { + Op_t X; + + 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; + } + return X.match(FPMO->getOperand(1)); + } +}; + /// Match 'fneg X' as 'fsub -0.0, X'. -template -inline BinaryOp_match, RHS, Instruction::FSub> -m_FNeg(const RHS &X) { - return m_FSub(m_NegZeroFP(), X); +template +inline FNeg_match +m_FNeg(const OpTy &X) { + return FNeg_match(X); } /// Match 'fneg X' as 'fsub +-0.0, X'. diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp index c4faab7c58c1..61b6d7ca2593 100644 --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -208,7 +208,7 @@ unsigned ReassociatePass::getRank(Value *V) { // If this is a 'not' or 'neg' instruction, do not count it for rank. This // assures us that X and ~X will have the same rank. if (!match(I, m_Not(m_Value())) && !match(I, m_Neg(m_Value())) && - !BinaryOperator::isFNeg(I)) + !match(I, m_FNeg(m_Value()))) ++Rank; LLVM_DEBUG(dbgs() << "Calculated Rank[" << V->getName() << "] = " << Rank @@ -575,7 +575,7 @@ static bool LinearizeExprTree(BinaryOperator *I, // multiplies by -1 so they can be reassociated. if (BinaryOperator *BO = dyn_cast(Op)) if ((Opcode == Instruction::Mul && match(BO, m_Neg(m_Value()))) || - (Opcode == Instruction::FMul && BinaryOperator::isFNeg(BO))) { + (Opcode == Instruction::FMul && match(BO, m_FNeg(m_Value())))) { LLVM_DEBUG(dbgs() << "MORPH LEAF: " << *Op << " (" << Weight << ") TO "); BO = LowerNegateToMultiply(BO); @@ -855,7 +855,7 @@ static Value *NegateValue(Value *V, Instruction *BI, // Okay, we need to materialize a negated version of V with an instruction. // Scan the use lists of V to see if we have one already. for (User *U : V->users()) { - if (!match(U, m_Neg(m_Value())) && !BinaryOperator::isFNeg(U)) + if (!match(U, m_Neg(m_Value())) && !match(U, m_FNeg(m_Value()))) continue; // We found one! Now we have to make sure that the definition dominates @@ -900,7 +900,7 @@ static Value *NegateValue(Value *V, Instruction *BI, /// Return true if we should break up this subtract of X-Y into (X + -Y). static bool ShouldBreakUpSubtract(Instruction *Sub) { // If this is a negation, we can't split it up! - if (match(Sub, m_Neg(m_Value())) || BinaryOperator::isFNeg(Sub)) + if (match(Sub, m_Neg(m_Value())) || match(Sub, m_FNeg(m_Value()))) return false; // Don't breakup X - undef. @@ -1463,19 +1463,16 @@ Value *ReassociatePass::OptimizeAdd(Instruction *I, // Check for X and -X or X and ~X in the operand list. Value *X; if (!match(TheOp, m_Neg(m_Value(X))) && !match(TheOp, m_Not(m_Value(X))) && - !BinaryOperator::isFNeg(TheOp)) + !match(TheOp, m_FNeg(m_Value(X)))) continue; - if (BinaryOperator::isFNeg(TheOp)) - X = BinaryOperator::getFNegArgument(TheOp); - unsigned FoundX = FindInOperandList(Ops, i, X); if (FoundX == i) continue; // Remove X and -X from the operand list. if (Ops.size() == 2 && - (match(TheOp, m_Neg(m_Value())) || BinaryOperator::isFNeg(TheOp))) + (match(TheOp, m_Neg(m_Value())) || match(TheOp, m_FNeg(m_Value())))) return Constant::getNullValue(X->getType()); // Remove X and ~X from the operand list. @@ -2081,7 +2078,7 @@ void ReassociatePass::OptimizeInst(Instruction *I) { RedoInsts.insert(I); MadeChange = true; I = NI; - } else if (BinaryOperator::isFNeg(I)) { + } else if (match(I, m_FNeg(m_Value()))) { // Otherwise, this is a negation. See if the operand is a multiply tree // and if this is not an inner node of a multiply tree. if (isReassociableOp(I->getOperand(1), Instruction::FMul) && diff --git a/llvm/test/Transforms/Reassociate/fp-expr.ll b/llvm/test/Transforms/Reassociate/fp-expr.ll index e616c52f28e6..dcbf835ba544 100644 --- a/llvm/test/Transforms/Reassociate/fp-expr.ll +++ b/llvm/test/Transforms/Reassociate/fp-expr.ll @@ -4,8 +4,8 @@ define void @test1() { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[T1:%.*]] = tail call <4 x float> @blam() -; CHECK-NEXT: [[T1_NEG:%.*]] = fsub fast <4 x float> , [[T1]] -; CHECK-NEXT: [[T24:%.*]] = fadd fast <4 x float> [[T1_NEG]], undef +; CHECK-NEXT: [[T23:%.*]] = fsub fast <4 x float> undef, [[T1]] +; CHECK-NEXT: [[T24:%.*]] = fadd fast <4 x float> [[T23]], undef ; CHECK-NEXT: tail call void @wombat(<4 x float> [[T24]]) ; CHECK-NEXT: ret void ;