Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -252,12 +252,33 @@ return Builder.CreateIsNotNull(V, "tobool"); } + static Optional getFPFeatures(Expr *E) { + if (const auto *BO = dyn_cast(E)) + return BO->getFPFeatures(); + else if (const auto *CE = dyn_cast(E)) + return CE->getFPFeatures(); + return None; + } + + /// A RAII to apply the FP features from the expression to the IRBuilder. + struct ApplyFPFeatures : public CGBuilderTy::FastMathFlagGuard { + ApplyFPFeatures(llvm::IRBuilderBase &Builder, Expr *E) + : CGBuilderTy::FastMathFlagGuard(Builder) { + if (Optional FPFeatures = getFPFeatures(E)) { + llvm::FastMathFlags FMF = Builder.getFastMathFlags(); + FMF.setAllowContract(FPFeatures->allowFPContractAcrossStatement()); + Builder.setFastMathFlags(FMF); + } + } + }; + //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// Value *Visit(Expr *E) { ApplyDebugLocation DL(CGF, E); + ApplyFPFeatures FPF(Builder, E); return StmtVisitor::Visit(E); } Index: test/CodeGen/ffp-contract-fast-option.c =================================================================== --- /dev/null +++ test/CodeGen/ffp-contract-fast-option.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -O3 -ffp-contract=fast -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s + +float fp_contract_1(float a, float b, float c) { + // CHECK-LABEL: @fp_contract_1( + // CHECK: fmul contract float + // CHECK: fadd contract float + return a * b + c; +} + +float fp_contract_2(float a, float b, float c) { + // CHECK-LABEL: @fp_contract_2( + // CHECK: fmul contract float + // CHECK: fsub contract float + return a * b - c; +}