Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -1362,10 +1362,21 @@ MDNode *FPMathTag = nullptr) { if (auto *VC = dyn_cast(V)) return Insert(Folder.CreateFNeg(VC), Name); - return Insert(setFPAttrs(BinaryOperator::CreateFNeg(V), FPMathTag, FMF), - Name); + return Insert(setFPAttrs(UnaryOperator::CreateFNeg(V, Name), FPMathTag, + FMF), Name); } + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFNegFMF(Value *V, Instruction *FMFSource, + const Twine &Name = "") { + if (auto *VC = dyn_cast(V)) + return Insert(Folder.CreateFNeg(VC), Name); + Instruction *I = setFPAttrs(UnaryOperator::CreateFNeg(V, Name), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + Value *CreateNot(Value *V, const Twine &Name = "") { if (auto *VC = dyn_cast(V)) return Insert(Folder.CreateNot(VC), Name); Index: include/llvm/IR/InstrTypes.h =================================================================== --- include/llvm/IR/InstrTypes.h +++ include/llvm/IR/InstrTypes.h @@ -304,10 +304,12 @@ Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); +#if 0 static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", Instruction *InsertBefore = nullptr); static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); +#endif static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNot(Value *Op, const Twine &Name, Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -1196,6 +1196,20 @@ UnaryOps getOpcode() const { return static_cast(Instruction::getOpcode()); } + + static UnaryOperator *CreateFNegFMF(Value *Op, Instruction *FMFSource, + const Twine &Name = "") { + UnaryOperator *UO = Create(Instruction::FNeg, Op, Name); + UO->copyIRFlags(FMFSource); + return UO; + } + +#if 0 + static UnaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = nullptr); + static UnaryOperator *CreateFNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); +#endif }; //===----------------------------------------------------------------------===// Index: include/llvm/IR/NoFolder.h =================================================================== --- include/llvm/IR/NoFolder.h +++ include/llvm/IR/NoFolder.h @@ -196,7 +196,7 @@ } Instruction *CreateFNeg(Constant *C) const { - return BinaryOperator::CreateFNeg(C); + return UnaryOperator::CreateFNeg(C); } Instruction *CreateNot(Constant *C) const { Index: include/llvm/IR/PatternMatch.h =================================================================== --- include/llvm/IR/PatternMatch.h +++ include/llvm/IR/PatternMatch.h @@ -667,22 +667,31 @@ FNeg_match(const Op_t &Op) : X(Op) {} template bool match(OpTy *V) { auto *FPMO = dyn_cast(V); - if (!FPMO || FPMO->getOpcode() != Instruction::FSub) + if (!FPMO) 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; + else + if (FPMO->getOpcode() != Instruction::FSub && + FPMO->getOpcode() != Instruction::FNeg) + return false; + 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)); + else + return X.match(FPMO->getOperand(0)); } }; -/// Match 'fneg X' as 'fsub -0.0, X'. +/// Match 'fneg X' as 'fsub -0.0, X'. Also match 'fneg X'. template inline FNeg_match m_FNeg(const OpTy &X) { Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -388,6 +388,13 @@ "NumOperands not set up?"); setCalledOperand(Func); + for (unsigned i = 0; i != Args.size(); ++i) { + Type *ftyptype = FTy->getParamType(i); + Type *argtype = Args[i]->getType(); + if (ftyptype != argtype) { + argtype = nullptr; + } + } #ifndef NDEBUG assert((Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && @@ -2210,6 +2217,22 @@ #endif } +#if 0 +UnaryOperator *UnaryOperator::CreateFNeg(Value *Op, const Twine &Name, + Instruction *InsertBefore) { + Value *zero = ConstantFP::getZeroValueForNegation(Op->getType()); + return new BinaryOperator(Instruction::FSub, zero, Op, + Op->getType(), Name, InsertBefore); +} + +BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd) { + Value *zero = ConstantFP::getZeroValueForNegation(Op->getType()); + return new BinaryOperator(Instruction::FSub, zero, Op, + Op->getType(), Name, InsertAtEnd); +} +#endif + //===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// @@ -2364,6 +2387,7 @@ return BinaryOperator::CreateNUWSub(zero, Op, Name, InsertAtEnd); } +#if 0 BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name, Instruction *InsertBefore) { Value *zero = ConstantFP::getZeroValueForNegation(Op->getType()); @@ -2377,6 +2401,7 @@ return new BinaryOperator(Instruction::FSub, zero, Op, Op->getType(), Name, InsertAtEnd); } +#endif BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name, Instruction *InsertBefore) { Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -663,10 +663,9 @@ } Value *FAddCombine::createFNeg(Value *V) { - Value *Zero = cast(ConstantFP::getZeroValueForNegation(V->getType())); - Value *NewV = createFSub(Zero, V); + Value *NewV = Builder.CreateFNeg(V); if (Instruction *I = dyn_cast(NewV)) - createInstPostProc(I, true); // fneg's don't receive instruction numbers. + createInstPostProc(I); return NewV; } @@ -1830,7 +1829,7 @@ // fsub nsz 0, X ==> fsub nsz -0.0, X Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (I.hasNoSignedZeros() && match(Op0, m_PosZeroFP())) - return BinaryOperator::CreateFNegFMF(Op1, &I); + return UnaryOperator::CreateFNegFMF(Op1, &I); Value *X, *Y; Constant *C; @@ -1892,12 +1891,12 @@ if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { // (Y - X) - Y --> -X if (match(Op0, m_FSub(m_Specific(Op1), m_Value(X)))) - return BinaryOperator::CreateFNegFMF(X, &I); + return UnaryOperator::CreateFNegFMF(X, &I); // Y - (X + Y) --> -X // Y - (Y + X) --> -X if (match(Op1, m_c_FAdd(m_Specific(Op0), m_Value(X)))) - return BinaryOperator::CreateFNegFMF(X, &I); + return UnaryOperator::CreateFNegFMF(X, &I); // (X * C) - X --> X * (C - 1.0) if (match(Op0, m_FMul(m_Specific(Op1), m_Constant(C)))) { @@ -1923,3 +1922,19 @@ return nullptr; } + +Instruction *InstCombiner::visitFNeg(UnaryOperator &I) { + Value *Op0 = I.getOperand(0); + Value *X; + + // -(-X) -> X + if (match(Op0, m_FNeg(m_Value(X)))) + if (auto *XI = dyn_cast(X)) { + if (XI->getOpcode() == Instruction::FSub) + return replaceInstUsesWith(I, XI->getOperand(1)); + else if (XI->getOpcode() == Instruction::FNeg) + return replaceInstUsesWith(I, XI->getOperand(0)); + } + + return nullptr; +} Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2268,7 +2268,7 @@ llvm_unreachable("unexpected intrinsic ID"); } Value *NewCall = Builder.CreateBinaryIntrinsic(NewIID, X, Y, II); - Instruction *FNeg = BinaryOperator::CreateFNeg(NewCall); + Instruction *FNeg = UnaryOperator::CreateFNeg(NewCall); FNeg->copyIRFlags(II); return FNeg; } @@ -2396,7 +2396,7 @@ if (match(II->getArgOperand(0), m_OneUse(m_FNeg(m_Value(X))))) { // sin(-x) --> -sin(x) Value *NewSin = Builder.CreateUnaryIntrinsic(Intrinsic::sin, X, II); - Instruction *FNeg = BinaryOperator::CreateFNeg(NewSin); + Instruction *FNeg = UnaryOperator::CreateFNeg(NewSin); FNeg->copyFastMathFlags(II); return FNeg; } Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1622,7 +1622,7 @@ Value *X; if (match(OpI, m_FNeg(m_Value(X)))) { Value *InnerTrunc = Builder.CreateFPTrunc(X, Ty); - return BinaryOperator::CreateFNegFMF(InnerTrunc, OpI); + return UnaryOperator::CreateFNegFMF(InnerTrunc, OpI); } } Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -352,6 +352,7 @@ Value *OptimizePointerDifference(Value *LHS, Value *RHS, Type *Ty); Instruction *visitSub(BinaryOperator &I); Instruction *visitFSub(BinaryOperator &I); + Instruction *visitFNeg(UnaryOperator &I); Instruction *visitMul(BinaryOperator &I); Instruction *visitFMul(BinaryOperator &I); Instruction *visitURem(BinaryOperator &I); Index: lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -361,7 +361,7 @@ // X * -1.0 --> -X Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (match(Op1, m_SpecificFP(-1.0))) - return BinaryOperator::CreateFNegFMF(Op0, &I); + return UnaryOperator::CreateFNegFMF(Op0, &I); // -X * -Y --> X * Y Value *X, *Y; @@ -375,11 +375,11 @@ // Sink negation: -X * Y --> -(X * Y) if (match(Op0, m_OneUse(m_FNeg(m_Value(X))))) - return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op1, &I), &I); + return UnaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op1, &I), &I); // Sink negation: Y * -X --> -(X * Y) if (match(Op1, m_OneUse(m_FNeg(m_Value(X))))) - return BinaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op0, &I), &I); + return UnaryOperator::CreateFNegFMF(Builder.CreateFMulFMF(X, Op0, &I), &I); // fabs(X) * fabs(X) -> X * X if (Op0 == Op1 && match(Op0, m_Intrinsic(m_Value(X)))) Index: lib/Transforms/Scalar/Reassociate.cpp =================================================================== --- lib/Transforms/Scalar/Reassociate.cpp +++ lib/Transforms/Scalar/Reassociate.cpp @@ -253,12 +253,12 @@ } } -static BinaryOperator *CreateNeg(Value *S1, const Twine &Name, - Instruction *InsertBefore, Value *FlagsOp) { +static Instruction *CreateNeg(Value *S1, const Twine &Name, + Instruction *InsertBefore, Value *FlagsOp) { if (S1->getType()->isIntOrIntVectorTy()) return BinaryOperator::CreateNeg(S1, Name, InsertBefore); else { - BinaryOperator *Res = BinaryOperator::CreateFNeg(S1, Name, InsertBefore); + UnaryInstruction *Res = UnaryOperator::CreateFNeg(S1, Name, InsertBefore); Res->setFastMathFlags(cast(FlagsOp)->getFastMathFlags()); return Res; } @@ -855,7 +855,7 @@ // this use. We do this by moving it to the entry block (if it is a // non-instruction value) or right after the definition. These negates will // be zapped by reassociate later, so we don't need much finesse here. - BinaryOperator *TheNeg = cast(U); + Instruction *TheNeg = cast(U); // Verify that the negate is in this function, V might be a constant expr. if (TheNeg->getParent()->getParent() != BI->getParent()->getParent()) @@ -885,7 +885,7 @@ // Insert a 'neg' instruction that subtracts the value from zero to get the // negation. - BinaryOperator *NewNeg = CreateNeg(V, V->getName() + ".neg", BI, BI); + Instruction *NewNeg = CreateNeg(V, V->getName() + ".neg", BI, BI); ToRedo.insert(NewNeg); return NewNeg; } Index: test/Transforms/InstCombine/cos-1.ll =================================================================== --- test/Transforms/InstCombine/cos-1.ll +++ test/Transforms/InstCombine/cos-1.ll @@ -24,7 +24,7 @@ ; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) ; ANY-NEXT: ret double [[COS]] ; - %neg = fsub double -0.0, %x + %neg = fneg double %x %r = call double @cos(double %neg) ret double %r } @@ -34,7 +34,7 @@ ; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) ; ANY-NEXT: ret float [[COS]] ; - %neg = fsub float -0.0, %x + %neg = fneg float %x %r = call float @cosf(float %neg) ret float %r } @@ -44,7 +44,7 @@ ; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) ; ANY-NEXT: ret float [[COS]] ; - %neg = fsub float -0.0, %x + %neg = fneg float %x %r = call nnan reassoc float @cosf(float %neg) ret float %r } @@ -54,10 +54,10 @@ define double @sin_negated_arg(double %x) { ; ANY-LABEL: @sin_negated_arg( ; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) -; ANY-NEXT: [[TMP2:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; ANY-NEXT: [[TMP2:%.*]] = fneg double [[TMP1]] ; ANY-NEXT: ret double [[TMP2]] ; - %neg = fsub double -0.0, %x + %neg = fneg double %x %r = call double @sin(double %neg) ret double %r } @@ -65,10 +65,10 @@ define float @sinf_negated_arg(float %x) { ; ANY-LABEL: @sinf_negated_arg( ; ANY-NEXT: [[TMP1:%.*]] = call float @sinf(float [[X:%.*]]) -; ANY-NEXT: [[TMP2:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; ANY-NEXT: [[TMP2:%.*]] = fneg float [[TMP1]] ; ANY-NEXT: ret float [[TMP2]] ; - %neg = fsub float -0.0, %x + %neg = fneg float %x %r = call float @sinf(float %neg) ret float %r } @@ -76,10 +76,10 @@ define float @sinf_negated_arg_FMF(float %x) { ; ANY-LABEL: @sinf_negated_arg_FMF( ; ANY-NEXT: [[TMP1:%.*]] = call nnan afn float @sinf(float [[X:%.*]]) -; ANY-NEXT: [[TMP2:%.*]] = fsub nnan afn float -0.000000e+00, [[TMP1]] +; ANY-NEXT: [[TMP2:%.*]] = fneg nnan afn float [[TMP1]] ; ANY-NEXT: ret float [[TMP2]] ; - %neg = fsub ninf float -0.0, %x + %neg = fneg ninf float %x %r = call afn nnan float @sinf(float %neg) ret float %r } @@ -88,12 +88,12 @@ define double @sin_negated_arg_extra_use(double %x) { ; ANY-LABEL: @sin_negated_arg_extra_use( -; ANY-NEXT: [[NEG:%.*]] = fsub double -0.000000e+00, [[X:%.*]] +; ANY-NEXT: [[NEG:%.*]] = fneg double [[X:%.*]] ; ANY-NEXT: [[R:%.*]] = call double @sin(double [[NEG]]) ; ANY-NEXT: call void @use(double [[NEG]]) ; ANY-NEXT: ret double [[R]] ; - %neg = fsub double -0.0, %x + %neg = fneg double %x %r = call double @sin(double %neg) call void @use(double %neg) ret double %r @@ -107,9 +107,9 @@ ; ANY-NEXT: [[TMP1:%.*]] = call double @sin(double [[X:%.*]]) ; ANY-NEXT: ret double [[TMP1]] ; - %neg = fsub double -0.0, %x + %neg = fneg double %x %r = call double @sin(double %neg) - %rn = fsub double -0.0, %r + %rn = fneg double %r ret double %rn } @@ -118,10 +118,10 @@ define double @tan_negated_arg(double %x) { ; ANY-LABEL: @tan_negated_arg( ; ANY-NEXT: [[TMP1:%.*]] = call double @tan(double [[X:%.*]]) -; ANY-NEXT: [[TMP2:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; ANY-NEXT: [[TMP2:%.*]] = fneg double [[TMP1]] ; ANY-NEXT: ret double [[TMP2]] ; - %neg = fsub double -0.0, %x + %neg = fneg double %x %r = call double @tan(double %neg) ret double %r } @@ -131,10 +131,10 @@ define fp128 @tanl_negated_arg(fp128 %x) { ; ANY-LABEL: @tanl_negated_arg( ; ANY-NEXT: [[TMP1:%.*]] = call fp128 @tanl(fp128 [[X:%.*]]) -; ANY-NEXT: [[TMP2:%.*]] = fsub fp128 0xL00000000000000008000000000000000, [[TMP1]] +; ANY-NEXT: [[TMP2:%.*]] = fneg fp128 [[TMP1]] ; ANY-NEXT: ret fp128 [[TMP2]] ; - %neg = fsub fp128 0xL00000000000000008000000000000000, %x + %neg = fneg fp128 %x %r = call fp128 @tanl(fp128 %neg) ret fp128 %r } @@ -151,7 +151,7 @@ ; DO-FLOAT-SHRINK-NEXT: ret float [[COSF]] ; %conv1 = fpext float %f to double - %neg = fsub double -0.0, %conv1 + %neg = fneg double %conv1 %cos = call double @cos(double %neg) %conv2 = fptrunc double %cos to float ret float %conv2 @@ -167,7 +167,7 @@ ; ANY-NEXT: ret float [[CONV2]] ; %conv1 = fpext float %f to double - %neg = fsub double -0.0, %conv1 + %neg = fneg double %conv1 %cos = call double @llvm.cos.f64(double %neg) %conv2 = fptrunc double %cos to float ret float %conv2 Index: test/Transforms/InstCombine/cos-sin-intrinsic.ll =================================================================== --- test/Transforms/InstCombine/cos-sin-intrinsic.ll +++ test/Transforms/InstCombine/cos-sin-intrinsic.ll @@ -99,7 +99,7 @@ define <2 x float> @fneg_sin(<2 x float> %x){ ; CHECK-LABEL: @fneg_sin( ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.sin.v2f32(<2 x float> [[X:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %negx = fsub <2 x float> , %x @@ -112,7 +112,7 @@ define <2 x float> @fneg_sin_fmf(<2 x float> %x){ ; CHECK-LABEL: @fneg_sin_fmf( ; CHECK-NEXT: [[TMP1:%.*]] = call nnan arcp afn <2 x float> @llvm.sin.v2f32(<2 x float> [[X:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub nnan arcp afn <2 x float> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg nnan arcp afn <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %negx = fsub fast <2 x float> , %x Index: test/Transforms/InstCombine/fast-math.ll =================================================================== --- test/Transforms/InstCombine/fast-math.ll +++ test/Transforms/InstCombine/fast-math.ll @@ -269,7 +269,7 @@ define float @fsub_fadd_common_op_fneg(float %x, float %y) { ; CHECK-LABEL: @fsub_fadd_common_op_fneg( -; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg fast float [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %a = fadd float %x, %y @@ -283,7 +283,7 @@ define float @fsub_fadd_common_op_fneg_reassoc_nsz(float %x, float %y) { ; CHECK-LABEL: @fsub_fadd_common_op_fneg_reassoc_nsz( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz float [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %a = fadd float %x, %y @@ -295,7 +295,7 @@ define <2 x float> @fsub_fadd_common_op_fneg_vec(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @fsub_fadd_common_op_fneg_vec( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> , [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %a = fadd <2 x float> %x, %y @@ -308,7 +308,7 @@ define float @fsub_fadd_common_op_fneg_commute(float %x, float %y) { ; CHECK-LABEL: @fsub_fadd_common_op_fneg_commute( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz float [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %a = fadd float %y, %x @@ -320,7 +320,7 @@ define <2 x float> @fsub_fadd_common_op_fneg_commute_vec(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @fsub_fadd_common_op_fneg_commute_vec( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> , [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %a = fadd <2 x float> %y, %x @@ -333,7 +333,7 @@ define float @fsub_fsub_common_op_fneg(float %x, float %y) { ; CHECK-LABEL: @fsub_fsub_common_op_fneg( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz float [[X:%.*]] ; CHECK-NEXT: ret float [[R]] ; %s = fsub float %y, %x @@ -345,7 +345,7 @@ define <2 x float> @fsub_fsub_common_op_fneg_vec(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @fsub_fsub_common_op_fneg_vec( -; CHECK-NEXT: [[R:%.*]] = fsub reassoc nsz <2 x float> , [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = fneg reassoc nsz <2 x float> [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %s = fsub <2 x float> %y, %x @@ -429,7 +429,7 @@ define double @fail2(double %f1, double %f2) { ; CHECK-LABEL: @fail2( ; CHECK-NEXT: [[TMP1:%.*]] = fadd fast double [[F2:%.*]], [[F2]] -; CHECK-NEXT: [[TMP2:%.*]] = fsub fast double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = fneg fast double [[TMP1]] ; CHECK-NEXT: ret double [[TMP2]] ; %t1 = fsub fast double %f1, %f2 @@ -504,7 +504,7 @@ define float @fold16(float %x, float %y) { ; CHECK-LABEL: @fold16( ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = fsub float -0.000000e+00, [[Y]] +; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[Y]] ; CHECK-NEXT: [[R_P:%.*]] = select i1 [[CMP]], float [[Y]], float [[TMP1]] ; CHECK-NEXT: [[R:%.*]] = fadd float [[R_P]], [[X]] ; CHECK-NEXT: ret float [[R]] @@ -534,7 +534,7 @@ define float @fneg2(float %x) { ; CHECK-LABEL: @fneg2( -; CHECK-NEXT: [[SUB:%.*]] = fsub nsz float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = fneg nsz float [[X:%.*]] ; CHECK-NEXT: ret float [[SUB]] ; %sub = fsub nsz float 0.0, %x @@ -543,7 +543,7 @@ define <2 x float> @fneg2_vec_undef(<2 x float> %x) { ; CHECK-LABEL: @fneg2_vec_undef( -; CHECK-NEXT: [[SUB:%.*]] = fsub nsz <2 x float> , [[X:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = fneg nsz <2 x float> [[X:%.*]] ; CHECK-NEXT: ret <2 x float> [[SUB]] ; %sub = fsub nsz <2 x float> , %x Index: test/Transforms/InstCombine/fmul.ll =================================================================== --- test/Transforms/InstCombine/fmul.ll +++ test/Transforms/InstCombine/fmul.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -instcombine < %s | FileCheck %s -; (-0.0 - X) * C => X * -C +; -X * C => X * -C define float @neg_constant(float %x) { ; CHECK-LABEL: @neg_constant( ; CHECK-NEXT: [[MUL:%.*]] = fmul ninf float [[X:%.*]], -2.000000e+01 @@ -32,7 +32,7 @@ ret <2 x float> %mul } -; (0.0 - X) * C => X * -C +; -X * C => X * -C define float @neg_nsz_constant(float %x) { ; CHECK-LABEL: @neg_nsz_constant( ; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[X:%.*]], -2.000000e+01 @@ -43,7 +43,7 @@ ret float %mul } -; (-0.0 - X) * (-0.0 - Y) => X * Y +; -X * -Y => X * Y define float @neg_neg(float %x, float %y) { ; CHECK-LABEL: @neg_neg( ; CHECK-NEXT: [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]] @@ -77,7 +77,7 @@ ret <2 x float> %mul } -; (0.0 - X) * (0.0 - Y) => X * Y +; -X * -Y => X * Y define float @neg_neg_nsz(float %x, float %y) { ; CHECK-LABEL: @neg_neg_nsz( ; CHECK-NEXT: [[MUL:%.*]] = fmul afn float [[X:%.*]], [[Y:%.*]] @@ -108,11 +108,11 @@ ret float %mul } -; (-0.0 - X) * Y => -0.0 - (X * Y) +; -X * Y => -(X * Y) define float @neg_sink(float %x, float %y) { ; CHECK-LABEL: @neg_sink( ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: ret float [[MUL]] ; %sub = fsub float -0.0, %x @@ -123,7 +123,7 @@ define <2 x float> @neg_sink_vec(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @neg_sink_vec( ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[MUL:%.*]] = fneg <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[MUL]] ; %sub = fsub <2 x float> , %x @@ -134,7 +134,7 @@ define <2 x float> @neg_sink_vec_undef(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @neg_sink_vec_undef( ; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[MUL:%.*]] = fneg <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[MUL]] ; %sub = fsub <2 x float> , %x @@ -142,11 +142,11 @@ ret <2 x float> %mul } -; (0.0 - X) * Y => 0.0 - (X * Y) +; -X * Y => -(X * Y) define float @neg_sink_nsz(float %x, float %y) { ; CHECK-LABEL: @neg_sink_nsz( ; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: ret float [[MUL]] ; %sub1 = fsub nsz float 0.0, %x @@ -154,7 +154,7 @@ ret float %mul } -; "(-0.0 - X) * Y => -0.0 - (X * Y)" is disabled if expression "-0.0 - X" +; "-X * Y => -(X * Y)" is disabled if expression "-X" ; has multiple uses. define float @neg_sink_multi_use(float %x, float %y) { ; CHECK-LABEL: @neg_sink_multi_use( @@ -204,10 +204,10 @@ ret void } -; X * -1.0 => -0.0 - X +; X * -1.0 => -X define float @test9(float %x) { ; CHECK-LABEL: @test9( -; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[X:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fneg float [[X:%.*]] ; CHECK-NEXT: ret float [[MUL]] ; %mul = fmul float %x, -1.0 @@ -217,7 +217,7 @@ ; PR18532 define <4 x float> @test10(<4 x float> %x) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[MUL:%.*]] = fsub arcp afn <4 x float> , [[X:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fneg arcp afn <4 x float> [[X:%.*]] ; CHECK-NEXT: ret <4 x float> [[MUL]] ; %mul = fmul arcp afn <4 x float> %x, Index: test/Transforms/InstCombine/fpcast.ll =================================================================== --- test/Transforms/InstCombine/fpcast.ll +++ test/Transforms/InstCombine/fpcast.ll @@ -32,7 +32,7 @@ define half @fneg_fptrunc(float %a) { ; CHECK-LABEL: @fneg_fptrunc( ; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half -; CHECK-NEXT: [[C:%.*]] = fsub half 0xH8000, [[TMP1]] +; CHECK-NEXT: [[C:%.*]] = fneg half [[TMP1]] ; CHECK-NEXT: ret half [[C]] ; %b = fsub float -0.0, %a @@ -43,7 +43,7 @@ define <2 x half> @fneg_fptrunc_vec_undef(<2 x float> %a) { ; CHECK-LABEL: @fneg_fptrunc_vec_undef( ; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half> -; CHECK-NEXT: [[C:%.*]] = fsub <2 x half> , [[TMP1]] +; CHECK-NEXT: [[C:%.*]] = fneg <2 x half> [[TMP1]] ; CHECK-NEXT: ret <2 x half> [[C]] ; %b = fsub <2 x float> , %a @@ -54,7 +54,7 @@ define half @test4-fast(float %a) { ; CHECK-LABEL: @test4-fast( ; CHECK-NEXT: [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half -; CHECK-NEXT: [[C:%.*]] = fsub fast half 0xH8000, [[TMP1]] +; CHECK-NEXT: [[C:%.*]] = fneg fast half [[TMP1]] ; CHECK-NEXT: ret half [[C]] ; %b = fsub fast float -0.0, %a Index: test/Transforms/InstCombine/fsub.ll =================================================================== --- test/Transforms/InstCombine/fsub.ll +++ test/Transforms/InstCombine/fsub.ll @@ -226,7 +226,7 @@ define float @neg_trunc_op1_extra_use(double %a, float %b) { ; CHECK-LABEL: @neg_trunc_op1_extra_use( ; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[A:%.*]] to float -; CHECK-NEXT: [[T2:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[T2:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: [[T3:%.*]] = fadd float [[TMP1]], [[B:%.*]] ; CHECK-NEXT: call void @use(float [[T2]]) ; CHECK-NEXT: ret float [[T3]] Index: test/Transforms/InstCombine/maximum.ll =================================================================== --- test/Transforms/InstCombine/maximum.ll +++ test/Transforms/InstCombine/maximum.ll @@ -217,7 +217,7 @@ define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @neg_neg( ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %negx = fsub <2 x float> , %x @@ -231,7 +231,7 @@ define float @neg_neg_vec_fmf(float %x, float %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( ; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] ; CHECK-NEXT: ret float [[R]] ; %negx = fsub arcp float -0.0, %x @@ -248,7 +248,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGX]]) ; CHECK-NEXT: ret float [[R]] ; @@ -263,7 +263,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]]) -; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGY]]) ; CHECK-NEXT: ret float [[R]] ; Index: test/Transforms/InstCombine/maxnum.ll =================================================================== --- test/Transforms/InstCombine/maxnum.ll +++ test/Transforms/InstCombine/maxnum.ll @@ -217,7 +217,7 @@ define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @neg_neg( ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minnum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg <2 x float> [[TMP1]] ; CHECK-NEXT: ret <2 x float> [[R]] ; %negx = fsub <2 x float> , %x @@ -231,7 +231,7 @@ define float @neg_neg_vec_fmf(float %x, float %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( ; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minnum.f32(float [[X:%.*]], float [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg fast float [[TMP1]] ; CHECK-NEXT: ret float [[R]] ; %negx = fsub arcp float -0.0, %x @@ -248,7 +248,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X]], float [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGX]]) ; CHECK-NEXT: ret float [[R]] ; @@ -263,7 +263,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float [[Y]]) -; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg float [[TMP1]] ; CHECK-NEXT: call void @use(float [[NEGY]]) ; CHECK-NEXT: ret float [[R]] ; Index: test/Transforms/InstCombine/minimum.ll =================================================================== --- test/Transforms/InstCombine/minimum.ll +++ test/Transforms/InstCombine/minimum.ll @@ -241,7 +241,7 @@ define double @neg_neg(double %x, double %y) { ; CHECK-LABEL: @neg_neg( ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X:%.*]], double [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: ret double [[R]] ; %negx = fsub double -0.0, %x @@ -256,7 +256,7 @@ define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( ; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maximum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg nnan ninf <2 x double> [[TMP1]] ; CHECK-NEXT: ret <2 x double> [[R]] ; %negx = fsub reassoc <2 x double> , %x @@ -273,7 +273,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X]], double [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGX]]) ; CHECK-NEXT: ret double [[R]] ; @@ -288,7 +288,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X:%.*]], double [[Y]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGY]]) ; CHECK-NEXT: ret double [[R]] ; Index: test/Transforms/InstCombine/minnum.ll =================================================================== --- test/Transforms/InstCombine/minnum.ll +++ test/Transforms/InstCombine/minnum.ll @@ -241,7 +241,7 @@ define double @neg_neg(double %x, double %y) { ; CHECK-LABEL: @neg_neg( ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: ret double [[R]] ; %negx = fsub double -0.0, %x @@ -256,7 +256,7 @@ define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { ; CHECK-LABEL: @neg_neg_vec_fmf( ; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maxnum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> , [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg nnan ninf <2 x double> [[TMP1]] ; CHECK-NEXT: ret <2 x double> [[R]] ; %negx = fsub reassoc <2 x double> , %x @@ -273,7 +273,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_x( ; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X]], double [[Y:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGX]]) ; CHECK-NEXT: ret double [[R]] ; @@ -288,7 +288,7 @@ ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maxnum.f64(double [[X:%.*]], double [[Y]]) -; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = fneg double [[TMP1]] ; CHECK-NEXT: call void @use(double [[NEGY]]) ; CHECK-NEXT: ret double [[R]] ; Index: test/Transforms/InstCombine/pow-1.ll =================================================================== --- test/Transforms/InstCombine/pow-1.ll +++ test/Transforms/InstCombine/pow-1.ll @@ -170,7 +170,7 @@ define <2 x float> @test_simplify4vn(<2 x float> %x) { ; CHECK-LABEL: @test_simplify4vn( -; ANY-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[X:%.*]] +; ANY-NEXT: [[MUL:%.*]] = fneg <2 x float> [[X:%.*]] ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] ; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) Index: test/Transforms/InstCombine/select-crash.ll =================================================================== --- test/Transforms/InstCombine/select-crash.ll +++ test/Transforms/InstCombine/select-crash.ll @@ -4,7 +4,7 @@ define fastcc double @gimp_operation_color_balance_map(float %value, double %highlights) nounwind readnone inlinehint { entry: ; CHECK: gimp_operation_color_balance_map -; CHECK: fsub double -0.000000 +; CHECK: fneg double %conv = fpext float %value to double %div = fdiv double %conv, 1.600000e+01 %add = fadd double %div, 1.000000e+00 @@ -22,7 +22,7 @@ ; PR10180: same crash, but with vectors define <4 x float> @foo(i1 %b, <4 x float> %x, <4 x float> %y, <4 x float> %z) { ; CHECK-LABEL: @foo( -; CHECK: fsub <4 x float> +; CHECK: fneg <4 x float> ; CHECK: select ; CHECK: fadd <4 x float> %a = fadd <4 x float> %x, %y Index: test/Transforms/Reassociate/fast-SubReassociate.ll =================================================================== --- test/Transforms/Reassociate/fast-SubReassociate.ll +++ test/Transforms/Reassociate/fast-SubReassociate.ll @@ -84,7 +84,7 @@ ; %Q = fsub fast float %D, %sum1 ; ret i32 %Q ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[B_NEG:%.*]] = fsub fast float -0.000000e+00, %B +; CHECK-NEXT: [[B_NEG:%.*]] = fneg fast float %B ; CHECK-NEXT: [[O_NEG:%.*]] = fsub fast float [[B_NEG]], %A ; CHECK-NEXT: [[P:%.*]] = fsub fast float [[O_NEG]], %C ; CHECK-NEXT: [[Q:%.*]] = fadd fast float [[P]], %D Index: test/Transforms/Reassociate/fast-basictest.ll =================================================================== --- test/Transforms/Reassociate/fast-basictest.ll +++ test/Transforms/Reassociate/fast-basictest.ll @@ -4,7 +4,7 @@ ; With reassociation, constant folding can eliminate the 12 and -12 constants. define float @test1(float %arg) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[ARG_NEG:%.*]] = fsub fast float -0.000000e+00, [[ARG:%.*]] +; CHECK-NEXT: [[ARG_NEG:%.*]] = fneg fast float [[ARG:%.*]] ; CHECK-NEXT: ret float [[ARG_NEG]] ; %t1 = fsub fast float -1.200000e+01, %arg @@ -16,7 +16,7 @@ ; Both 'reassoc' and 'nsz' are required. define float @test1_minimal(float %arg) { ; CHECK-LABEL: @test1_minimal( -; CHECK-NEXT: [[ARG_NEG:%.*]] = fsub reassoc nsz float -0.000000e+00, [[ARG:%.*]] +; CHECK-NEXT: [[ARG_NEG:%.*]] = fneg reassoc nsz float [[ARG:%.*]] ; CHECK-NEXT: ret float [[ARG_NEG]] ; %t1 = fsub reassoc nsz float -1.200000e+01, %arg @@ -581,7 +581,7 @@ ; %sum = fadd fast float %c, %b ; %t7 = fsub fast float 0, %sum ; CHECK-LABEL: @test20( -; CHECK-NEXT: [[B_NEG:%.*]] = fsub fast float -0.000000e+00, [[B:%.*]] +; CHECK-NEXT: [[B_NEG:%.*]] = fneg fast float [[B:%.*]] ; CHECK-NEXT: [[T7:%.*]] = fsub fast float [[B_NEG]], [[C:%.*]] ; CHECK-NEXT: ret float [[T7]] ; Index: test/Transforms/Reassociate/fp-expr.ll =================================================================== --- test/Transforms/Reassociate/fp-expr.ll +++ test/Transforms/Reassociate/fp-expr.ll @@ -4,7 +4,7 @@ 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: [[T1_NEG:%.*]] = fneg fast <4 x float> [[T1]] ; CHECK-NEXT: [[T24:%.*]] = fadd fast <4 x float> [[T1_NEG]], undef ; CHECK-NEXT: tail call void @wombat(<4 x float> [[T24]]) ; CHECK-NEXT: ret void @@ -19,7 +19,7 @@ define half @test2() { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[T15:%.*]] = fsub fast half undef, undef -; CHECK-NEXT: [[T15_NEG:%.*]] = fsub fast half 0xH8000, [[T15]] +; CHECK-NEXT: [[T15_NEG:%.*]] = fneg fast half [[T15]] ; CHECK-NEXT: [[T18:%.*]] = fadd fast half [[T15_NEG]], undef ; CHECK-NEXT: ret half [[T18]] ; Index: unittests/IR/IRBuilderTest.cpp =================================================================== --- unittests/IR/IRBuilderTest.cpp +++ unittests/IR/IRBuilderTest.cpp @@ -205,7 +205,7 @@ TEST_F(IRBuilderTest, FastMathFlags) { IRBuilder<> Builder(BB); Value *F, *FC; - Instruction *FDiv, *FAdd, *FCmp, *FCall; + Instruction *FDiv, *FAdd, *FNeg, *FCmp, *FCall; F = Builder.CreateLoad(GV->getValueType(), GV); F = Builder.CreateFAdd(F, F); @@ -215,6 +215,12 @@ FAdd = cast(F); EXPECT_FALSE(FAdd->hasNoNaNs()); + F = Builder.CreateFNeg(F); + ASSERT_TRUE(isa(F)); + FNeg = cast(F); + EXPECT_FALSE(FNeg->hasNoNaNs()); + EXPECT_TRUE(FNeg->getOpcode() == Instruction::FNeg); + FastMathFlags FMF; Builder.setFastMathFlags(FMF);