diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index e65e925a11d487..7a14a418c7b65f 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -252,6 +252,7 @@ class ComplexExprEmitter ComplexPairTy LHS; ComplexPairTy RHS; QualType Ty; // Computation Type. + FPOptions FPFeatures; }; BinOpInfo EmitBinOps(const BinaryOperator *E, @@ -643,6 +644,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { llvm::Value *ResR, *ResI; if (Op.LHS.first->getType()->isFloatingPointTy()) { + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r"); if (Op.LHS.second && Op.RHS.second) ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i"); @@ -661,6 +663,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) { ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) { llvm::Value *ResR, *ResI; if (Op.LHS.first->getType()->isFloatingPointTy()) { + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r"); if (Op.LHS.second && Op.RHS.second) ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i"); @@ -753,6 +756,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { // FIXME: C11 also provides for imaginary types which would allow folding // still more of this within the type system. + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); if (Op.LHS.second && Op.RHS.second) { // If both operands are complex, emit the core math directly, and then // test for NaNs. If we find NaNs in the result, we delegate to a libcall @@ -854,6 +858,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { // // FIXME: We would be able to avoid the libcall in many places if we // supported imaginary types in addition to complex types. + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures); if (RHSi && !CGF.getLangOpts().FastMath) { BinOpInfo LibCallOp = Op; // If LHS was a real, supply a null imaginary part. @@ -1025,6 +1030,7 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E, Ops.Ty = PromotionType; else Ops.Ty = E->getType(); + Ops.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts()); return Ops; } @@ -1039,8 +1045,9 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, if (const AtomicType *AT = LHSTy->getAs()) LHSTy = AT->getValueType(); - CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E); BinOpInfo OpInfo; + OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts()); + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures); // Load the RHS and LHS operands. // __block variables need to have the rhs evaluated first, plus this should diff --git a/clang/test/CodeGen/complex-strictfp.c b/clang/test/CodeGen/complex-strictfp.c index 0bffed4ff331d4..b0c84d5eebe725 100644 --- a/clang/test/CodeGen/complex-strictfp.c +++ b/clang/test/CodeGen/complex-strictfp.c @@ -1,12 +1,12 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffp-exception-behavior=maytrap -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffp-exception-behavior=maytrap -emit-llvm -o - %s | FileCheck --implicit-check-not=fpexcept.maytrap --implicit-check-not=round.tonearest %s // Test that the constrained intrinsics are picking up the exception // metadata from the AST instead of the global default from the command line. // Include rounding metadata in the testing. -// FIXME: All cases of "fpexcept.maytrap" in this test are wrong. -// FIXME: All cases of "round.tonearest" in this test are wrong. +// Any cases of "fpexcept.maytrap" in this test are clang bugs. +// Any cases of "round.tonearest" in this test are clang bugs. #pragma float_control(except, on) #pragma STDC FENV_ROUND FE_UPWARD @@ -15,7 +15,7 @@ _Complex double g1, g2; _Complex float cf; double D; -// CHECK-LABEL: define {{[^@]+}}@test3a( +// CHECK-LABEL: @test3a( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4 @@ -33,7 +33,7 @@ void test3a(void) { cf += D; } -// CHECK-LABEL: define {{[^@]+}}@test3b( +// CHECK-LABEL: @test3b( // CHECK-NEXT: entry: // CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4 // CHECK-NEXT: [[CF_IMAG:%.*]] = load float, ptr getelementptr inbounds ({ float, float }, ptr @cf, i32 0, i32 1), align 4 @@ -48,7 +48,7 @@ void test3b(void) { D += cf; } -// CHECK-LABEL: define {{[^@]+}}@test3c( +// CHECK-LABEL: @test3c( // CHECK-NEXT: entry: // CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8 @@ -69,12 +69,12 @@ void test3c(void) { cf /= g1; } -// CHECK-LABEL: define {{[^@]+}}@test3d( +// CHECK-LABEL: @test3d( // CHECK-NEXT: entry: // CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8 -// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR2]] +// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]] // CHECK-NEXT: store double [[ADD_R]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG]], ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: ret void @@ -83,12 +83,12 @@ void test3d(void) { g1 = g1 + D; } -// CHECK-LABEL: define {{[^@]+}}@test3e( +// CHECK-LABEL: @test3e( // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8 // CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8 // CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8 -// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR2]] +// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]] // CHECK-NEXT: store double [[ADD_R]], ptr @g1, align 8 // CHECK-NEXT: store double [[G1_IMAG]], ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8 // CHECK-NEXT: ret void @@ -97,7 +97,7 @@ void test3e(void) { g1 = D + g1; } -// CHECK-LABEL: define {{[^@]+}}@t1( +// CHECK-LABEL: @t1( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]] // CHECK-NEXT: store float [[CONV]], ptr @cf, align 4 @@ -107,7 +107,7 @@ void t1(void) { (__real__ cf) = 4.0; } -// CHECK-LABEL: define {{[^@]+}}@t2( +// CHECK-LABEL: @t2( // CHECK-NEXT: entry: // CHECK-NEXT: [[CONV:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]] // CHECK-NEXT: store float [[CONV]], ptr getelementptr inbounds ({ float, float }, ptr @cf, i32 0, i32 1), align 4 @@ -117,7 +117,7 @@ void t2(void) { (__imag__ cf) = 4.0; } -// CHECK-LABEL: define {{[^@]+}}@t91( +// CHECK-LABEL: @t91( // CHECK-NEXT: entry: // CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1 // CHECK-NEXT: br i1 false, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] @@ -139,7 +139,7 @@ void t91(void) { (0 ? 2.0f : (_Complex double) 2.0f); } -// CHECK-LABEL: define {{[^@]+}}@t92( +// CHECK-LABEL: @t92( // CHECK-NEXT: entry: // CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1 // CHECK-NEXT: br i1 false, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]