Skip to content

Fix bug with -ffp-contract=fast-honor-pragmas #104857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ Miscellaneous Clang Crashes Fixed
- Fixed a crash caused by long chains of ``sizeof`` and other similar operators
that can be followed by a non-parenthesized expression. (#GH45061)

- Fixed an crash when compiling ``#pragma STDC FP_CONTRACT DEFAULT`` with
``-ffp-contract=fast-honor-pragmas``. (#GH104830)

- Fixed a crash when function has more than 65536 parameters.
Now a diagnostic is emitted. (#GH35741)

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,13 +1269,12 @@ void Sema::ActOnPragmaFPContract(SourceLocation Loc,
NewFPFeatures.setAllowFPContractWithinStatement();
break;
case LangOptions::FPM_Fast:
case LangOptions::FPM_FastHonorPragmas:
NewFPFeatures.setAllowFPContractAcrossStatement();
break;
case LangOptions::FPM_Off:
NewFPFeatures.setDisallowFPContract();
break;
case LangOptions::FPM_FastHonorPragmas:
llvm_unreachable("Should not happen");
}
FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures);
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
Expand Down
37 changes: 37 additions & 0 deletions clang/test/CodeGen/ffp-contract-fast-honor-pramga-option.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// RUN: %clang_cc1 -O3 -ffp-contract=fast-honor-pragmas -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s

float fp_contract_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_1fff(
// 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_2fff(
// CHECK: fmul contract float
// CHECK: fsub contract float
return a * b - c;
}

void fp_contract_3(float *a, float b, float c) {
// CHECK-LABEL: fp_contract_3Pfff(
// CHECK: fmul contract float
// CHECK: fadd contract float
a[0] += b * c;
}

void fp_contract_4(float *a, float b, float c) {
// CHECK-LABEL: fp_contract_4Pfff(
// CHECK: fmul contract float
// CHECK: fsub contract float
a[0] -= b * c;
}

float fp_contract_5(float a, float b, float c) {
// CHECK-LABEL: fp_contract_5fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
float t = a * b;
return t + c;
}
151 changes: 151 additions & 0 deletions clang/test/CodeGen/ffp-contract-fhp-pragma-override.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// RUN: %clang_cc1 -O3 -ffp-contract=fast-honor-pragmas -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s

float fp_contract_on_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_on_1fff(
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
#pragma STDC FP_CONTRACT ON
return a * b + c;
}

float fp_contract_on_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_on_2fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma STDC FP_CONTRACT ON
float t = a * b;
return t + c;
}

float fp_contract_off_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_off_1fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma STDC FP_CONTRACT OFF
return a * b + c;
}

float fp_contract_off_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_off_2fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma STDC FP_CONTRACT OFF
float t = a * b;
return t + c;
}

float fp_contract_default_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_default_1fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
#pragma STDC FP_CONTRACT DEFAULT
return a * b + c;
}

float fp_contract_default_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_default_2fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
#pragma STDC FP_CONTRACT DEFAULT
float t = a * b;
return t + c;
}

float fp_contract_clang_on_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_on_1fff(
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
#pragma clang fp contract(on)
return a * b + c;
}

float fp_contract_clang_on_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_on_2fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma clang fp contract(on)
float t = a * b;
return t + c;
}

float fp_contract_clang_off_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_off_1fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma clang fp contract(off)
return a * b + c;
}

float fp_contract_clang_off_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_off_2fff(
// CHECK: fmul float
// CHECK: fadd float
#pragma clang fp contract(off)
float t = a * b;
return t + c;
}

float fp_contract_clang_fast_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_fast_1fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
#pragma clang fp contract(fast)
return a * b + c;
}

float fp_contract_clang_fast_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_clang_fast_2fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
#pragma clang fp contract(fast)
float t = a * b;
return t + c;
}

#pragma STDC FP_CONTRACT ON

float fp_contract_global_on_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_on_1fff(
// CHECK: call float @llvm.fmuladd.f32(float {{.*}}, float {{.*}}, float {{.*}})
return a * b + c;
}

float fp_contract_global_on_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_on_2fff(
// CHECK: fmul float
// CHECK: fadd float
float t = a * b;
return t + c;
}

#pragma STDC FP_CONTRACT OFF

float fp_contract_global_off_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_off_1fff(
// CHECK: fmul float
// CHECK: fadd float
return a * b + c;
}

float fp_contract_global_off_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_off_2fff(
// CHECK: fmul float
// CHECK: fadd float
float t = a * b;
return t + c;
}

#pragma STDC FP_CONTRACT DEFAULT

float fp_contract_global_default_1(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_default_1fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
return a * b + c;
}

float fp_contract_global_default_2(float a, float b, float c) {
// CHECK-LABEL: fp_contract_global_default_2fff(
// CHECK: fmul contract float
// CHECK: fadd contract float
float t = a * b;
return t + c;
}
Loading