On Mon, Oct 1, 2012 at 9:45 PM, Lang Hames <[email protected]> wrote: > Author: lhames > Date: Mon Oct 1 23:45:10 2012 > New Revision: 164989 > > URL: http://llvm.org/viewvc/llvm-project?rev=164989&view=rev > Log: > Add FP_CONTRACT support for clang. > > Clang will now honor the FP_CONTRACT pragma and emit LLVM > fmuladd intrinsics for expressions of the form A * B + C (when they occur in a > single statement).
Hooray \o/ I think you were telling me that the pragma can be applied at the file scope. Is that tested somewhere? - David > > > Added: > cfe/trunk/test/CodeGen/ffp-contract-option.c > - copied unchanged from r164952, cfe/trunk/test/CodeGen/fp-contract.c > cfe/trunk/test/CodeGen/fp-contract-pragma.cpp > Removed: > cfe/trunk/test/CodeGen/fp-contract.c > Modified: > cfe/trunk/include/clang/AST/Expr.h > cfe/trunk/include/clang/AST/ExprCXX.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/AST/ASTImporter.cpp > cfe/trunk/lib/Analysis/BodyFarm.cpp > cfe/trunk/lib/CodeGen/CGExprScalar.cpp > cfe/trunk/lib/CodeGen/CGObjC.cpp > cfe/trunk/lib/Parse/ParseStmt.cpp > cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp > cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp > cfe/trunk/lib/Sema/SemaDeclCXX.cpp > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/lib/Sema/SemaExprCXX.cpp > cfe/trunk/lib/Sema/SemaOverload.cpp > cfe/trunk/lib/Sema/SemaPseudoObject.cpp > cfe/trunk/lib/Sema/TreeTransform.h > cfe/trunk/lib/Serialization/ASTReaderStmt.cpp > cfe/trunk/lib/Serialization/ASTWriterStmt.cpp > cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl > > Modified: cfe/trunk/include/clang/AST/Expr.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/Expr.h (original) > +++ cfe/trunk/include/clang/AST/Expr.h Mon Oct 1 23:45:10 2012 > @@ -2785,6 +2785,12 @@ > > private: > unsigned Opc : 6; > + > + // Records the FP_CONTRACT pragma status at the point that this binary > + // operator was parsed. This bit is only meaningful for operations on > + // floating point types. For all other types it should default to > + // false. > + unsigned FPContractable : 1; > SourceLocation OpLoc; > > enum { LHS, RHS, END_EXPR }; > @@ -2793,7 +2799,7 @@ > > BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, > ExprValueKind VK, ExprObjectKind OK, > - SourceLocation opLoc) > + SourceLocation opLoc, bool fpContractable) > : Expr(BinaryOperatorClass, ResTy, VK, OK, > lhs->isTypeDependent() || rhs->isTypeDependent(), > lhs->isValueDependent() || rhs->isValueDependent(), > @@ -2801,7 +2807,7 @@ > rhs->isInstantiationDependent()), > (lhs->containsUnexpandedParameterPack() || > rhs->containsUnexpandedParameterPack())), > - Opc(opc), OpLoc(opLoc) { > + Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { > SubExprs[LHS] = lhs; > SubExprs[RHS] = rhs; > assert(!isCompoundAssignmentOp() && > @@ -2902,10 +2908,18 @@ > return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); > } > > + // Set the FP contractability status of this operator. Only meaningful for > + // operations on floating point types. > + void setFPContractable(bool FPC) { FPContractable = FPC; } > + > + // Get the FP contractability status of this operator. Only meaningful for > + // operations on floating point types. > + bool isFPContractable() const { return FPContractable; } > + > protected: > BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, > ExprValueKind VK, ExprObjectKind OK, > - SourceLocation opLoc, bool dead) > + SourceLocation opLoc, bool fpContractable, bool dead2) > : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, > lhs->isTypeDependent() || rhs->isTypeDependent(), > lhs->isValueDependent() || rhs->isValueDependent(), > @@ -2913,7 +2927,7 @@ > rhs->isInstantiationDependent()), > (lhs->containsUnexpandedParameterPack() || > rhs->containsUnexpandedParameterPack())), > - Opc(opc), OpLoc(opLoc) { > + Opc(opc), FPContractable(fpContractable), OpLoc(opLoc) { > SubExprs[LHS] = lhs; > SubExprs[RHS] = rhs; > } > @@ -2935,8 +2949,9 @@ > CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, > ExprValueKind VK, ExprObjectKind OK, > QualType CompLHSType, QualType CompResultType, > - SourceLocation OpLoc) > - : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, true), > + SourceLocation OpLoc, bool fpContractable) > + : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, fpContractable, > + true), > ComputationLHSType(CompLHSType), > ComputationResultType(CompResultType) { > assert(isCompoundAssignmentOp() && > > Modified: cfe/trunk/include/clang/AST/ExprCXX.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/ExprCXX.h (original) > +++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Oct 1 23:45:10 2012 > @@ -53,14 +53,19 @@ > OverloadedOperatorKind Operator; > SourceRange Range; > > + // Record the FP_CONTRACT state that applies to this operator call. Only > + // meaningful for floating point types. For other types this value can be > + // set to false. > + unsigned FPContractable : 1; > + > SourceRange getSourceRangeImpl() const LLVM_READONLY; > public: > CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, > ArrayRef<Expr*> args, QualType t, ExprValueKind VK, > - SourceLocation operatorloc) > + SourceLocation operatorloc, bool fpContractable) > : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK, > operatorloc), > - Operator(Op) { > + Operator(Op), FPContractable(fpContractable) { > Range = getSourceRangeImpl(); > } > explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : > @@ -85,6 +90,14 @@ > } > static bool classof(const CXXOperatorCallExpr *) { return true; } > > + // Set the FP contractability status of this operator. Only meaningful for > + // operations on floating point types. > + void setFPContractable(bool FPC) { FPContractable = FPC; } > + > + // Get the FP contractability status of this operator. Only meaningful for > + // operations on floating point types. > + bool isFPContractable() const { return FPContractable; } > + > friend class ASTStmtReader; > friend class ASTStmtWriter; > }; > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 1 23:45:10 2012 > @@ -735,6 +735,20 @@ > /// should not be used elsewhere. > void EmitCurrentDiagnostic(unsigned DiagID); > > + /// Records and restores the FP_CONTRACT state on entry/exit of compound > + /// statements. > + class FPContractStateRAII { > + public: > + FPContractStateRAII(Sema& S) > + : S(S), OldFPContractState(S.FPFeatures.fp_contract) {} > + ~FPContractStateRAII() { > + S.FPFeatures.fp_contract = OldFPContractState; > + } > + private: > + Sema& S; > + bool OldFPContractState : 1; > + }; > + > public: > Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, > TranslationUnitKind TUKind = TU_Complete, > > Modified: cfe/trunk/lib/AST/ASTImporter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ASTImporter.cpp (original) > +++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Oct 1 23:45:10 2012 > @@ -4082,7 +4082,8 @@ > return new (Importer.getToContext()) BinaryOperator(LHS, RHS, > E->getOpcode(), > T, E->getValueKind(), > E->getObjectKind(), > - > Importer.Import(E->getOperatorLoc())); > + > Importer.Import(E->getOperatorLoc()), > + E->isFPContractable()); > } > > Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator > *E) { > @@ -4111,7 +4112,8 @@ > T, E->getValueKind(), > E->getObjectKind(), > CompLHSType, CompResultType, > - > Importer.Import(E->getOperatorLoc())); > + > Importer.Import(E->getOperatorLoc()), > + E->isFPContractable()); > } > > static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { > > Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original) > +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Mon Oct 1 23:45:10 2012 > @@ -70,7 +70,7 @@ > QualType Ty) { > return new (C) BinaryOperator(const_cast<Expr*>(LHS), > const_cast<Expr*>(RHS), > BO_Assign, Ty, VK_RValue, > - OK_Ordinary, SourceLocation()); > + OK_Ordinary, SourceLocation(), false); > } > > DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) { > > Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Oct 1 23:45:10 2012 > @@ -45,6 +45,7 @@ > Value *RHS; > QualType Ty; // Computation Type. > BinaryOperator::Opcode Opcode; // Opcode of BinOp to perform > + bool FPContractable; > const Expr *E; // Entire expr, for error unsupported. May not be > binop. > }; > > @@ -1654,6 +1655,7 @@ > Result.RHS = Visit(E->getRHS()); > Result.Ty = E->getType(); > Result.Opcode = E->getOpcode(); > + Result.FPContractable = E->isFPContractable(); > Result.E = E; > return Result; > } > @@ -1982,6 +1984,77 @@ > return CGF.Builder.CreateInBoundsGEP(pointer, index, "add.ptr"); > } > > +// Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and > +// Addend. Use negMul and negAdd to negate the first operand of the Mul or > +// the add operand respectively. This allows fmuladd to represent a*b-c, or > +// c-a*b. Patterns in LLVM should catch the negated forms and translate them > to > +// efficient operations. > +static Value* buildFMulAdd(llvm::BinaryOperator *MulOp, Value *Addend, > + const CodeGenFunction &CGF, CGBuilderTy &Builder, > + bool negMul, bool negAdd) { > + assert(!(negMul && negAdd) && "Only one of negMul and negAdd should be > set."); > + > + Value *MulOp0 = MulOp->getOperand(0); > + Value *MulOp1 = MulOp->getOperand(1); > + if (negMul) { > + MulOp0 = > + Builder.CreateFSub( > + llvm::ConstantFP::getZeroValueForNegation(MulOp0->getType()), MulOp0, > + "neg"); > + } else if (negAdd) { > + Addend = > + Builder.CreateFSub( > + llvm::ConstantFP::getZeroValueForNegation(Addend->getType()), Addend, > + "neg"); > + } > + > + Value *FMulAdd = > + Builder.CreateCall3( > + CGF.CGM.getIntrinsic(llvm::Intrinsic::fmuladd, Addend->getType()), > + MulOp0, MulOp1, Addend); > + MulOp->eraseFromParent(); > + > + return FMulAdd; > +} > + > +// Check whether it would be legal to emit an fmuladd intrinsic call to > +// represent op and if so, build the fmuladd. > +// > +// Checks that (a) the operation is fusable, and (b) -ffp-contract=on. > +// Does NOT check the type of the operation - it's assumed that this function > +// will be called from contexts where it's known that the type is > contractable. > +static Value* tryEmitFMulAdd(const BinOpInfo &op, > + const CodeGenFunction &CGF, CGBuilderTy &Builder, > + bool isSub=false) { > + > + assert((op.Opcode == BO_Add || op.Opcode == BO_AddAssign || > + op.Opcode == BO_Sub || op.Opcode == BO_SubAssign) && > + "Only fadd/fsub can be the root of an fmuladd."); > + > + // Check whether this op is marked as fusable. > + if (!op.FPContractable) > + return 0; > + > + // Check whether -ffp-contract=on. (If -ffp-contract=off/fast, fusing is > + // either disabled, or handled entirely by the LLVM backend). > + if (CGF.getContext().getLangOpts().getFPContractMode() != > LangOptions::FPC_On) > + return 0; > + > + // We have a potentially fusable op. Look for a mul on one of the operands. > + if (llvm::BinaryOperator* LHSBinOp = > dyn_cast<llvm::BinaryOperator>(op.LHS)) { > + if (LHSBinOp->getOpcode() == llvm::Instruction::FMul) { > + return buildFMulAdd(LHSBinOp, op.RHS, CGF, Builder, false, isSub); > + } > + } else if (llvm::BinaryOperator* RHSBinOp = > + dyn_cast<llvm::BinaryOperator>(op.RHS)) { > + if (RHSBinOp->getOpcode() == llvm::Instruction::FMul) { > + return buildFMulAdd(RHSBinOp, op.LHS, CGF, Builder, isSub, false); > + } > + } > + > + return 0; > +} > + > Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &op) { > if (op.LHS->getType()->isPointerTy() || > op.RHS->getType()->isPointerTy()) > @@ -2000,8 +2073,13 @@ > } > } > > - if (op.LHS->getType()->isFPOrFPVectorTy()) > + if (op.LHS->getType()->isFPOrFPVectorTy()) { > + // Try to form an fmuladd. > + if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder)) > + return FMulAdd; > + > return Builder.CreateFAdd(op.LHS, op.RHS, "add"); > + } > > return Builder.CreateAdd(op.LHS, op.RHS, "add"); > } > @@ -2022,8 +2100,12 @@ > } > } > > - if (op.LHS->getType()->isFPOrFPVectorTy()) > + if (op.LHS->getType()->isFPOrFPVectorTy()) { > + // Try to form an fmuladd. > + if (Value *FMulAdd = tryEmitFMulAdd(op, CGF, Builder, true)) > + return FMulAdd; > return Builder.CreateFSub(op.LHS, op.RHS, "sub"); > + } > > return Builder.CreateSub(op.LHS, op.RHS, "sub"); > } > > Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Oct 1 23:45:10 2012 > @@ -1213,7 +1213,7 @@ > > BinaryOperator assign(&ivarRef, finalArg, BO_Assign, > ivarRef.getType(), VK_RValue, OK_Ordinary, > - SourceLocation()); > + SourceLocation(), false); > EmitStmt(&assign); > } > > @@ -2850,7 +2850,7 @@ > CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment()); > CXXOperatorCallExpr TheCall(C, OO_Equal, CalleeExp->getCallee(), > Args, DestTy->getPointeeType(), > - VK_LValue, SourceLocation()); > + VK_LValue, SourceLocation(), false); > > EmitStmt(&TheCall); > > > Modified: cfe/trunk/lib/Parse/ParseStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseStmt.cpp (original) > +++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Oct 1 23:45:10 2012 > @@ -679,6 +679,11 @@ > PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), > Tok.getLocation(), > "in compound statement ('{}')"); > + > + // Record the state of the FP_CONTRACT pragma, restore on leaving the > + // compound statement. > + Sema::FPContractStateRAII SaveFPContractState(Actions); > + > InMessageExpressionRAIIObject InMessage(*this, false); > BalancedDelimiterTracker T(*this, tok::l_brace); > if (T.consumeOpen()) > > Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp (original) > +++ cfe/trunk/lib/Rewrite/Frontend/RewriteModernObjC.cpp Mon Oct 1 23:45:10 > 2012 > @@ -3576,7 +3576,8 @@ > SourceLocation()); > BinaryOperator *lessThanExpr = > new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, > - VK_RValue, OK_Ordinary, SourceLocation()); > + VK_RValue, OK_Ordinary, SourceLocation(), > + false); > // (sizeof(returnType) <= 8 ? objc_msgSend(...) : > objc_msgSend_stret(...)) > ConditionalOperator *CondExpr = > new (Context) ConditionalOperator(lessThanExpr, > @@ -7473,7 +7474,7 @@ > BinaryOperator *addExpr = > new (Context) BinaryOperator(castExpr, DRE, BO_Add, > > Context->getPointerType(Context->CharTy), > - VK_RValue, OK_Ordinary, > SourceLocation()); > + VK_RValue, OK_Ordinary, > SourceLocation(), false); > // Don't forget the parens to enforce the proper binding. > ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), > SourceLocation(), > > Modified: cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp (original) > +++ cfe/trunk/lib/Rewrite/Frontend/RewriteObjC.cpp Mon Oct 1 23:45:10 2012 > @@ -3078,7 +3078,8 @@ > SourceLocation()); > BinaryOperator *lessThanExpr = > new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, > - VK_RValue, OK_Ordinary, SourceLocation()); > + VK_RValue, OK_Ordinary, SourceLocation(), > + false); > // (sizeof(returnType) <= 8 ? objc_msgSend(...) : > objc_msgSend_stret(...)) > ConditionalOperator *CondExpr = > new (Context) ConditionalOperator(lessThanExpr, > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Oct 1 23:45:10 2012 > @@ -7504,7 +7504,7 @@ > = new (S.Context) BinaryOperator(IterationVarRefRVal, > IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), > BO_NE, S.Context.BoolTy, > - VK_RValue, OK_Ordinary, Loc); > + VK_RValue, OK_Ordinary, Loc, false); > > // Create the pre-increment of the iteration variable. > Expr *Increment > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct 1 23:45:10 2012 > @@ -8416,7 +8416,8 @@ > > if (CompResultTy.isNull()) > return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc, > - ResultTy, VK, OK, OpLoc)); > + ResultTy, VK, OK, OpLoc, > + FPFeatures.fp_contract)); > if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != > OK_ObjCProperty) { > VK = VK_LValue; > @@ -8424,7 +8425,8 @@ > } > return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), > Opc, > ResultTy, VK, OK, > CompLHSTy, > - CompResultTy, OpLoc)); > + CompResultTy, OpLoc, > + FPFeatures.fp_contract)); > } > > /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct 1 23:45:10 2012 > @@ -4833,7 +4833,8 @@ > BO_Comma, BO->getType(), > BO->getValueKind(), > BO->getObjectKind(), > - BO->getOperatorLoc())); > + BO->getOperatorLoc(), > + BO->isFPContractable())); > } > } > > > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Oct 1 23:45:10 2012 > @@ -9981,7 +9981,7 @@ > llvm::makeArrayRef(Args, > NumArgs), > Context.DependentTy, > VK_RValue, > - OpLoc)); > + OpLoc, false)); > } > > // Build an empty overload set. > @@ -10058,7 +10058,7 @@ > CallExpr *TheCall = > new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), > llvm::makeArrayRef(Args, NumArgs), > - ResultTy, VK, OpLoc); > + ResultTy, VK, OpLoc, false); > > if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, > FnDecl)) > @@ -10159,7 +10159,8 @@ > return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, > Context.DependentTy, > VK_RValue, OK_Ordinary, > - OpLoc)); > + OpLoc, > + FPFeatures.fp_contract)); > > return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], > Opc, > Context.DependentTy, > @@ -10167,7 +10168,8 @@ > OK_Ordinary, > Context.DependentTy, > Context.DependentTy, > - OpLoc)); > + OpLoc, > + > FPFeatures.fp_contract)); > } > > // FIXME: save results of ADL from here? > @@ -10179,11 +10181,9 @@ > NestedNameSpecifierLoc(), OpNameInfo, > /*ADL*/ true, IsOverloaded(Fns), > Fns.begin(), Fns.end()); > - return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, > - Args, > - Context.DependentTy, > - VK_RValue, > - OpLoc)); > + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, > + Context.DependentTy, > VK_RValue, > + OpLoc, > FPFeatures.fp_contract)); > } > > // Always do placeholder-like conversions on the RHS. > @@ -10298,7 +10298,8 @@ > > CXXOperatorCallExpr *TheCall = > new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), > - Args, ResultTy, VK, OpLoc); > + Args, ResultTy, VK, OpLoc, > + FPFeatures.fp_contract); > > if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, > FnDecl)) > @@ -10430,7 +10431,7 @@ > Args, > Context.DependentTy, > VK_RValue, > - RLoc)); > + RLoc, false)); > } > > // Handle placeholders on both operands. > @@ -10507,7 +10508,8 @@ > CXXOperatorCallExpr *TheCall = > new (Context) CXXOperatorCallExpr(Context, OO_Subscript, > FnExpr.take(), Args, > - ResultTy, VK, RLoc); > + ResultTy, VK, RLoc, > + false); > > if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, > FnDecl)) > @@ -11035,7 +11037,7 @@ > CXXOperatorCallExpr *TheCall = > new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), > llvm::makeArrayRef(MethodArgs, > NumArgs+1), > - ResultTy, VK, RParenLoc); > + ResultTy, VK, RParenLoc, false); > delete [] MethodArgs; > > if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, > @@ -11208,7 +11210,7 @@ > ResultTy = ResultTy.getNonLValueExprType(Context); > CXXOperatorCallExpr *TheCall = > new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), > - Base, ResultTy, VK, OpLoc); > + Base, ResultTy, VK, OpLoc, false); > > if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, > Method)) > > Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original) > +++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Mon Oct 1 23:45:10 2012 > @@ -356,7 +356,7 @@ > syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, > opcode, > capturedRHS->getType(), > capturedRHS->getValueKind(), > - OK_Ordinary, opcLoc); > + OK_Ordinary, opcLoc, false); > } else { > ExprResult opLHS = buildGet(); > if (opLHS.isInvalid()) return ExprError(); > @@ -375,7 +375,7 @@ > OK_Ordinary, > opLHS.get()->getType(), > result.get()->getType(), > - opcLoc); > + opcLoc, false); > } > > // The result of the assignment, if not void, is the value set into > @@ -1366,7 +1366,7 @@ > // Do nothing if either argument is dependent. > if (LHS->isTypeDependent() || RHS->isTypeDependent()) > return new (Context) BinaryOperator(LHS, RHS, opcode, > Context.DependentTy, > - VK_RValue, OK_Ordinary, opcLoc); > + VK_RValue, OK_Ordinary, opcLoc, > false); > > // Filter out non-overload placeholder types in the RHS. > if (RHS->getType()->isNonOverloadPlaceholderType()) { > @@ -1437,14 +1437,14 @@ > cop->getObjectKind(), > cop->getComputationLHSType(), > > cop->getComputationResultType(), > - cop->getOperatorLoc()); > + cop->getOperatorLoc(), > false); > } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { > Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); > Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); > return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), > bop->getType(), bop->getValueKind(), > bop->getObjectKind(), > - bop->getOperatorLoc()); > + bop->getOperatorLoc(), false); > } else { > assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); > return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); > > Modified: cfe/trunk/lib/Sema/TreeTransform.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/TreeTransform.h (original) > +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct 1 23:45:10 2012 > @@ -6429,6 +6429,9 @@ > RHS.get() == E->getRHS()) > return SemaRef.Owned(E); > > + Sema::FPContractStateRAII FPContractState(getSema()); > + getSema().FPFeatures.fp_contract = E->isFPContractable(); > + > return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), > E->getOpcode(), > LHS.get(), RHS.get()); > } > @@ -6852,6 +6855,9 @@ > (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) > return SemaRef.MaybeBindToTemporary(E); > > + Sema::FPContractStateRAII FPContractState(getSema()); > + getSema().FPFeatures.fp_contract = E->isFPContractable(); > + > return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), > E->getOperatorLoc(), > Callee.get(), > > Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Oct 1 23:45:10 2012 > @@ -565,6 +565,7 @@ > E->setRHS(Reader.ReadSubExpr()); > E->setOpcode((BinaryOperator::Opcode)Record[Idx++]); > E->setOperatorLoc(ReadSourceLocation(Record, Idx)); > + E->setFPContractable((bool)Record[Idx++]); > } > > void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) { > @@ -1086,6 +1087,7 @@ > VisitCallExpr(E); > E->Operator = (OverloadedOperatorKind)Record[Idx++]; > E->Range = Reader.ReadSourceRange(F, Record, Idx); > + E->setFPContractable((bool)Record[Idx++]); > } > > void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { > > Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) > +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Oct 1 23:45:10 2012 > @@ -536,6 +536,7 @@ > Writer.AddStmt(E->getRHS()); > Record.push_back(E->getOpcode()); // FIXME: stable encoding > Writer.AddSourceLocation(E->getOperatorLoc(), Record); > + Record.push_back(E->isFPContractable()); > Code = serialization::EXPR_BINARY_OPERATOR; > } > > @@ -1055,6 +1056,7 @@ > VisitCallExpr(E); > Record.push_back(E->getOperator()); > Writer.AddSourceRange(E->Range, Record); > + Record.push_back(E->isFPContractable()); > Code = serialization::EXPR_CXX_OPERATOR_CALL; > } > > > Added: cfe/trunk/test/CodeGen/fp-contract-pragma.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract-pragma.cpp?rev=164989&view=auto > ============================================================================== > --- cfe/trunk/test/CodeGen/fp-contract-pragma.cpp (added) > +++ cfe/trunk/test/CodeGen/fp-contract-pragma.cpp Mon Oct 1 23:45:10 2012 > @@ -0,0 +1,39 @@ > +// RUN: %clang_cc1 -O3 -emit-llvm -o - %s | FileCheck %s > + > +// Is FP_CONTRACT is honored in a simple case? > +float fp_contract_1(float a, float b, float c) { > +// CHECK: _Z13fp_contract_1fff > +// CHECK-NEXT: entry > +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd > + #pragma STDC FP_CONTRACT ON > + return a * b + c; > +} > + > +// Is FP_CONTRACT state cleared on exiting compound statements? > +float fp_contract_2(float a, float b, float c) { > +// CHECK: _Z13fp_contract_2fff > +// CHECK-NEXT: entry > +// CHECK-NEXT: %mul = fmul float %a, %b > +// CHECK-NEXT: %add = fadd float %mul, %c > + { > + #pragma STDC FP_CONTRACT ON > + } > + return a * b + c; > +} > + > +// Does FP_CONTRACT survive template instatiation? > +class Foo {}; > +Foo operator+(Foo, Foo); > + > +template <typename T> > +T template_muladd(T a, T b, T c) { > + #pragma STDC FP_CONTRACT ON > + return a * b + c; > +} > + > +float fp_contract_3(float a, float b, float c) { > +// CHECK: _Z13fp_contract_3fff > +// CHECK-NEXT: entry > +// CHECK-NEXT: %0 = tail call float @llvm.fmuladd > + return template_muladd<float>(a, b, c); > +} > > Removed: cfe/trunk/test/CodeGen/fp-contract.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/fp-contract.c?rev=164988&view=auto > ============================================================================== > --- cfe/trunk/test/CodeGen/fp-contract.c (original) > +++ cfe/trunk/test/CodeGen/fp-contract.c (removed) > @@ -1,9 +0,0 @@ > -// RUN: %clang_cc1 -O3 -ffp-contract=fast -triple=powerpc-apple-darwin10 -S > -o - %s | FileCheck %s > -// REQUIRES: ppc32-registered-target > - > -float fma_test1(float a, float b, float c) { > -// CHECK: fmadds > - float x = a * b; > - float y = x + c; > - return y; > -} > > Modified: cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl?rev=164989&r1=164988&r2=164989&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl (original) > +++ cfe/trunk/test/CodeGenOpenCL/single-precision-constant.cl Mon Oct 1 > 23:45:10 2012 > @@ -1,7 +1,6 @@ > // RUN: %clang_cc1 %s -cl-single-precision-constant -emit-llvm -o - | > FileCheck %s > > float fn(float f) { > - // CHECK: fmul float > - // CHECK: fadd float > + // CHECK: %0 = tail call float @llvm.fmuladd.f32(float %f, float > 2.000000e+00, float 1.000000e+00) > return f*2. + 1.; > } > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
