Skip to content

Commit c0d2222

Browse files
author
Andy Kaylor
authored
Fix bug with -ffp-contract=fast-honor-pragmas (#104857)
This fixes a problem which caused clang to assert in the Sema pragma handling if it encountered "#pragma STDC FP_CONTRACT DEFAULT" when compiling with the -ffp-contract=fast-honor-pragmas option. This fixes #104830
1 parent c9ba6d3 commit c0d2222

File tree

4 files changed

+192
-2
lines changed

4 files changed

+192
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ Miscellaneous Clang Crashes Fixed
310310
- Fixed a crash caused by long chains of ``sizeof`` and other similar operators
311311
that can be followed by a non-parenthesized expression. (#GH45061)
312312

313+
- Fixed an crash when compiling ``#pragma STDC FP_CONTRACT DEFAULT`` with
314+
``-ffp-contract=fast-honor-pragmas``. (#GH104830)
315+
313316
- Fixed a crash when function has more than 65536 parameters.
314317
Now a diagnostic is emitted. (#GH35741)
315318

clang/lib/Sema/SemaAttr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,13 +1269,12 @@ void Sema::ActOnPragmaFPContract(SourceLocation Loc,
12691269
NewFPFeatures.setAllowFPContractWithinStatement();
12701270
break;
12711271
case LangOptions::FPM_Fast:
1272+
case LangOptions::FPM_FastHonorPragmas:
12721273
NewFPFeatures.setAllowFPContractAcrossStatement();
12731274
break;
12741275
case LangOptions::FPM_Off:
12751276
NewFPFeatures.setDisallowFPContract();
12761277
break;
1277-
case LangOptions::FPM_FastHonorPragmas:
1278-
llvm_unreachable("Should not happen");
12791278
}
12801279
FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures);
12811280
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 -O3 -ffp-contract=fast-honor-pragmas -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
2+
3+
float fp_contract_1(float a, float b, float c) {
4+
// CHECK-LABEL: fp_contract_1fff(
5+
// CHECK: fmul contract float
6+
// CHECK: fadd contract float
7+
return a * b + c;
8+
}
9+
10+
float fp_contract_2(float a, float b, float c) {
11+
// CHECK-LABEL: fp_contract_2fff(
12+
// CHECK: fmul contract float
13+
// CHECK: fsub contract float
14+
return a * b - c;
15+
}
16+
17+
void fp_contract_3(float *a, float b, float c) {
18+
// CHECK-LABEL: fp_contract_3Pfff(
19+
// CHECK: fmul contract float
20+
// CHECK: fadd contract float
21+
a[0] += b * c;
22+
}
23+
24+
void fp_contract_4(float *a, float b, float c) {
25+
// CHECK-LABEL: fp_contract_4Pfff(
26+
// CHECK: fmul contract float
27+
// CHECK: fsub contract float
28+
a[0] -= b * c;
29+
}
30+
31+
float fp_contract_5(float a, float b, float c) {
32+
// CHECK-LABEL: fp_contract_5fff(
33+
// CHECK: fmul contract float
34+
// CHECK: fadd contract float
35+
float t = a * b;
36+
return t + c;
37+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// RUN: %clang_cc1 -O3 -ffp-contract=fast-honor-pragmas -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
2+
3+
float fp_contract_on_1(float a, float b, float c) {
4+
// CHECK-LABEL: fp_contract_on_1fff(
5+
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
6+
#pragma STDC FP_CONTRACT ON
7+
return a * b + c;
8+
}
9+
10+
float fp_contract_on_2(float a, float b, float c) {
11+
// CHECK-LABEL: fp_contract_on_2fff(
12+
// CHECK: fmul float
13+
// CHECK: fadd float
14+
#pragma STDC FP_CONTRACT ON
15+
float t = a * b;
16+
return t + c;
17+
}
18+
19+
float fp_contract_off_1(float a, float b, float c) {
20+
// CHECK-LABEL: fp_contract_off_1fff(
21+
// CHECK: fmul float
22+
// CHECK: fadd float
23+
#pragma STDC FP_CONTRACT OFF
24+
return a * b + c;
25+
}
26+
27+
float fp_contract_off_2(float a, float b, float c) {
28+
// CHECK-LABEL: fp_contract_off_2fff(
29+
// CHECK: fmul float
30+
// CHECK: fadd float
31+
#pragma STDC FP_CONTRACT OFF
32+
float t = a * b;
33+
return t + c;
34+
}
35+
36+
float fp_contract_default_1(float a, float b, float c) {
37+
// CHECK-LABEL: fp_contract_default_1fff(
38+
// CHECK: fmul contract float
39+
// CHECK: fadd contract float
40+
#pragma STDC FP_CONTRACT DEFAULT
41+
return a * b + c;
42+
}
43+
44+
float fp_contract_default_2(float a, float b, float c) {
45+
// CHECK-LABEL: fp_contract_default_2fff(
46+
// CHECK: fmul contract float
47+
// CHECK: fadd contract float
48+
#pragma STDC FP_CONTRACT DEFAULT
49+
float t = a * b;
50+
return t + c;
51+
}
52+
53+
float fp_contract_clang_on_1(float a, float b, float c) {
54+
// CHECK-LABEL: fp_contract_clang_on_1fff(
55+
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
56+
#pragma clang fp contract(on)
57+
return a * b + c;
58+
}
59+
60+
float fp_contract_clang_on_2(float a, float b, float c) {
61+
// CHECK-LABEL: fp_contract_clang_on_2fff(
62+
// CHECK: fmul float
63+
// CHECK: fadd float
64+
#pragma clang fp contract(on)
65+
float t = a * b;
66+
return t + c;
67+
}
68+
69+
float fp_contract_clang_off_1(float a, float b, float c) {
70+
// CHECK-LABEL: fp_contract_clang_off_1fff(
71+
// CHECK: fmul float
72+
// CHECK: fadd float
73+
#pragma clang fp contract(off)
74+
return a * b + c;
75+
}
76+
77+
float fp_contract_clang_off_2(float a, float b, float c) {
78+
// CHECK-LABEL: fp_contract_clang_off_2fff(
79+
// CHECK: fmul float
80+
// CHECK: fadd float
81+
#pragma clang fp contract(off)
82+
float t = a * b;
83+
return t + c;
84+
}
85+
86+
float fp_contract_clang_fast_1(float a, float b, float c) {
87+
// CHECK-LABEL: fp_contract_clang_fast_1fff(
88+
// CHECK: fmul contract float
89+
// CHECK: fadd contract float
90+
#pragma clang fp contract(fast)
91+
return a * b + c;
92+
}
93+
94+
float fp_contract_clang_fast_2(float a, float b, float c) {
95+
// CHECK-LABEL: fp_contract_clang_fast_2fff(
96+
// CHECK: fmul contract float
97+
// CHECK: fadd contract float
98+
#pragma clang fp contract(fast)
99+
float t = a * b;
100+
return t + c;
101+
}
102+
103+
#pragma STDC FP_CONTRACT ON
104+
105+
float fp_contract_global_on_1(float a, float b, float c) {
106+
// CHECK-LABEL: fp_contract_global_on_1fff(
107+
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
108+
return a * b + c;
109+
}
110+
111+
float fp_contract_global_on_2(float a, float b, float c) {
112+
// CHECK-LABEL: fp_contract_global_on_2fff(
113+
// CHECK: fmul float
114+
// CHECK: fadd float
115+
float t = a * b;
116+
return t + c;
117+
}
118+
119+
#pragma STDC FP_CONTRACT OFF
120+
121+
float fp_contract_global_off_1(float a, float b, float c) {
122+
// CHECK-LABEL: fp_contract_global_off_1fff(
123+
// CHECK: fmul float
124+
// CHECK: fadd float
125+
return a * b + c;
126+
}
127+
128+
float fp_contract_global_off_2(float a, float b, float c) {
129+
// CHECK-LABEL: fp_contract_global_off_2fff(
130+
// CHECK: fmul float
131+
// CHECK: fadd float
132+
float t = a * b;
133+
return t + c;
134+
}
135+
136+
#pragma STDC FP_CONTRACT DEFAULT
137+
138+
float fp_contract_global_default_1(float a, float b, float c) {
139+
// CHECK-LABEL: fp_contract_global_default_1fff(
140+
// CHECK: fmul contract float
141+
// CHECK: fadd contract float
142+
return a * b + c;
143+
}
144+
145+
float fp_contract_global_default_2(float a, float b, float c) {
146+
// CHECK-LABEL: fp_contract_global_default_2fff(
147+
// CHECK: fmul contract float
148+
// CHECK: fadd contract float
149+
float t = a * b;
150+
return t + c;
151+
}

0 commit comments

Comments
 (0)