Skip to content

Commit d595b59

Browse files
committed
[FPEnv] Fix complex operations in strictfp mode
Operations on floating-point complex data had incorrect FP attributes in strictfp mode, because IRBuilder object was not synchronized with AST node attributes. Differential Revision: https://reviews.llvm.org/D141765
1 parent 2a16e1f commit d595b59

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

clang/lib/CodeGen/CGExprComplex.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ class ComplexExprEmitter
252252
ComplexPairTy LHS;
253253
ComplexPairTy RHS;
254254
QualType Ty; // Computation Type.
255+
FPOptions FPFeatures;
255256
};
256257

257258
BinOpInfo EmitBinOps(const BinaryOperator *E,
@@ -643,6 +644,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
643644
llvm::Value *ResR, *ResI;
644645

645646
if (Op.LHS.first->getType()->isFloatingPointTy()) {
647+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
646648
ResR = Builder.CreateFAdd(Op.LHS.first, Op.RHS.first, "add.r");
647649
if (Op.LHS.second && Op.RHS.second)
648650
ResI = Builder.CreateFAdd(Op.LHS.second, Op.RHS.second, "add.i");
@@ -661,6 +663,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinAdd(const BinOpInfo &Op) {
661663
ComplexPairTy ComplexExprEmitter::EmitBinSub(const BinOpInfo &Op) {
662664
llvm::Value *ResR, *ResI;
663665
if (Op.LHS.first->getType()->isFloatingPointTy()) {
666+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
664667
ResR = Builder.CreateFSub(Op.LHS.first, Op.RHS.first, "sub.r");
665668
if (Op.LHS.second && Op.RHS.second)
666669
ResI = Builder.CreateFSub(Op.LHS.second, Op.RHS.second, "sub.i");
@@ -753,6 +756,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
753756
// FIXME: C11 also provides for imaginary types which would allow folding
754757
// still more of this within the type system.
755758

759+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
756760
if (Op.LHS.second && Op.RHS.second) {
757761
// If both operands are complex, emit the core math directly, and then
758762
// 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) {
854858
//
855859
// FIXME: We would be able to avoid the libcall in many places if we
856860
// supported imaginary types in addition to complex types.
861+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
857862
if (RHSi && !CGF.getLangOpts().FastMath) {
858863
BinOpInfo LibCallOp = Op;
859864
// If LHS was a real, supply a null imaginary part.
@@ -1025,6 +1030,7 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E,
10251030
Ops.Ty = PromotionType;
10261031
else
10271032
Ops.Ty = E->getType();
1033+
Ops.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
10281034
return Ops;
10291035
}
10301036

@@ -1039,8 +1045,9 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
10391045
if (const AtomicType *AT = LHSTy->getAs<AtomicType>())
10401046
LHSTy = AT->getValueType();
10411047

1042-
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, E);
10431048
BinOpInfo OpInfo;
1049+
OpInfo.FPFeatures = E->getFPFeaturesInEffect(CGF.getLangOpts());
1050+
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, OpInfo.FPFeatures);
10441051

10451052
// Load the RHS and LHS operands.
10461053
// __block variables need to have the rhs evaluated first, plus this should

clang/test/CodeGen/complex-strictfp.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2-
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffp-exception-behavior=maytrap -emit-llvm -o - %s | FileCheck %s
2+
// 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
33

44

55
// Test that the constrained intrinsics are picking up the exception
66
// metadata from the AST instead of the global default from the command line.
77
// Include rounding metadata in the testing.
8-
// FIXME: All cases of "fpexcept.maytrap" in this test are wrong.
9-
// FIXME: All cases of "round.tonearest" in this test are wrong.
8+
// Any cases of "fpexcept.maytrap" in this test are clang bugs.
9+
// Any cases of "round.tonearest" in this test are clang bugs.
1010

1111
#pragma float_control(except, on)
1212
#pragma STDC FENV_ROUND FE_UPWARD
@@ -15,7 +15,7 @@ _Complex double g1, g2;
1515
_Complex float cf;
1616
double D;
1717

18-
// CHECK-LABEL: define {{[^@]+}}@test3a(
18+
// CHECK-LABEL: @test3a(
1919
// CHECK-NEXT: entry:
2020
// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8
2121
// CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4
@@ -33,7 +33,7 @@ void test3a(void) {
3333
cf += D;
3434
}
3535

36-
// CHECK-LABEL: define {{[^@]+}}@test3b(
36+
// CHECK-LABEL: @test3b(
3737
// CHECK-NEXT: entry:
3838
// CHECK-NEXT: [[CF_REAL:%.*]] = load float, ptr @cf, align 4
3939
// 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) {
4848
D += cf;
4949
}
5050

51-
// CHECK-LABEL: define {{[^@]+}}@test3c(
51+
// CHECK-LABEL: @test3c(
5252
// CHECK-NEXT: entry:
5353
// CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8
5454
// 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) {
6969
cf /= g1;
7070
}
7171

72-
// CHECK-LABEL: define {{[^@]+}}@test3d(
72+
// CHECK-LABEL: @test3d(
7373
// CHECK-NEXT: entry:
7474
// CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8
7575
// CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8
7676
// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8
77-
// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR2]]
77+
// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[G1_REAL]], double [[TMP0]], metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
7878
// CHECK-NEXT: store double [[ADD_R]], ptr @g1, align 8
7979
// CHECK-NEXT: store double [[G1_IMAG]], ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8
8080
// CHECK-NEXT: ret void
@@ -83,12 +83,12 @@ void test3d(void) {
8383
g1 = g1 + D;
8484
}
8585

86-
// CHECK-LABEL: define {{[^@]+}}@test3e(
86+
// CHECK-LABEL: @test3e(
8787
// CHECK-NEXT: entry:
8888
// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr @D, align 8
8989
// CHECK-NEXT: [[G1_REAL:%.*]] = load double, ptr @g1, align 8
9090
// CHECK-NEXT: [[G1_IMAG:%.*]] = load double, ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8
91-
// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR2]]
91+
// CHECK-NEXT: [[ADD_R:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP0]], double [[G1_REAL]], metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
9292
// CHECK-NEXT: store double [[ADD_R]], ptr @g1, align 8
9393
// CHECK-NEXT: store double [[G1_IMAG]], ptr getelementptr inbounds ({ double, double }, ptr @g1, i32 0, i32 1), align 8
9494
// CHECK-NEXT: ret void
@@ -97,7 +97,7 @@ void test3e(void) {
9797
g1 = D + g1;
9898
}
9999

100-
// CHECK-LABEL: define {{[^@]+}}@t1(
100+
// CHECK-LABEL: @t1(
101101
// CHECK-NEXT: entry:
102102
// CHECK-NEXT: [[CONV:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
103103
// CHECK-NEXT: store float [[CONV]], ptr @cf, align 4
@@ -107,7 +107,7 @@ void t1(void) {
107107
(__real__ cf) = 4.0;
108108
}
109109

110-
// CHECK-LABEL: define {{[^@]+}}@t2(
110+
// CHECK-LABEL: @t2(
111111
// CHECK-NEXT: entry:
112112
// CHECK-NEXT: [[CONV:%.*]] = call float @llvm.experimental.constrained.fptrunc.f32.f64(double 4.000000e+00, metadata !"round.upward", metadata !"fpexcept.strict") #[[ATTR2]]
113113
// 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) {
117117
(__imag__ cf) = 4.0;
118118
}
119119

120-
// CHECK-LABEL: define {{[^@]+}}@t91(
120+
// CHECK-LABEL: @t91(
121121
// CHECK-NEXT: entry:
122122
// CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1
123123
// CHECK-NEXT: br i1 false, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -139,7 +139,7 @@ void t91(void) {
139139
(0 ? 2.0f : (_Complex double) 2.0f);
140140
}
141141

142-
// CHECK-LABEL: define {{[^@]+}}@t92(
142+
// CHECK-LABEL: @t92(
143143
// CHECK-NEXT: entry:
144144
// CHECK-NEXT: [[C:%.*]] = alloca [0 x i8], align 1
145145
// CHECK-NEXT: br i1 false, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]

0 commit comments

Comments
 (0)