1*67e74705SXin Li // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li // Is FP_CONTRACT honored in a simple case?
fp_contract_1(float a,float b,float c)4*67e74705SXin Li float fp_contract_1(float a, float b, float c) {
5*67e74705SXin Li // CHECK: _Z13fp_contract_1fff
6*67e74705SXin Li // CHECK: tail call float @llvm.fmuladd
7*67e74705SXin Li #pragma STDC FP_CONTRACT ON
8*67e74705SXin Li return a * b + c;
9*67e74705SXin Li }
10*67e74705SXin Li
11*67e74705SXin Li // Is FP_CONTRACT state cleared on exiting compound statements?
fp_contract_2(float a,float b,float c)12*67e74705SXin Li float fp_contract_2(float a, float b, float c) {
13*67e74705SXin Li // CHECK: _Z13fp_contract_2fff
14*67e74705SXin Li // CHECK: %[[M:.+]] = fmul float %a, %b
15*67e74705SXin Li // CHECK-NEXT: fadd float %[[M]], %c
16*67e74705SXin Li {
17*67e74705SXin Li #pragma STDC FP_CONTRACT ON
18*67e74705SXin Li }
19*67e74705SXin Li return a * b + c;
20*67e74705SXin Li }
21*67e74705SXin Li
22*67e74705SXin Li // Does FP_CONTRACT survive template instantiation?
23*67e74705SXin Li class Foo {};
24*67e74705SXin Li Foo operator+(Foo, Foo);
25*67e74705SXin Li
26*67e74705SXin Li template <typename T>
template_muladd(T a,T b,T c)27*67e74705SXin Li T template_muladd(T a, T b, T c) {
28*67e74705SXin Li #pragma STDC FP_CONTRACT ON
29*67e74705SXin Li return a * b + c;
30*67e74705SXin Li }
31*67e74705SXin Li
fp_contract_3(float a,float b,float c)32*67e74705SXin Li float fp_contract_3(float a, float b, float c) {
33*67e74705SXin Li // CHECK: _Z13fp_contract_3fff
34*67e74705SXin Li // CHECK: tail call float @llvm.fmuladd
35*67e74705SXin Li return template_muladd<float>(a, b, c);
36*67e74705SXin Li }
37*67e74705SXin Li
38*67e74705SXin Li template<typename T> class fp_contract_4 {
method(float a,float b,float c)39*67e74705SXin Li float method(float a, float b, float c) {
40*67e74705SXin Li #pragma STDC FP_CONTRACT ON
41*67e74705SXin Li return a * b + c;
42*67e74705SXin Li }
43*67e74705SXin Li };
44*67e74705SXin Li
45*67e74705SXin Li template class fp_contract_4<int>;
46*67e74705SXin Li // CHECK: _ZN13fp_contract_4IiE6methodEfff
47*67e74705SXin Li // CHECK: tail call float @llvm.fmuladd
48*67e74705SXin Li
49*67e74705SXin Li // Check file-scoped FP_CONTRACT
50*67e74705SXin Li #pragma STDC FP_CONTRACT ON
fp_contract_5(float a,float b,float c)51*67e74705SXin Li float fp_contract_5(float a, float b, float c) {
52*67e74705SXin Li // CHECK: _Z13fp_contract_5fff
53*67e74705SXin Li // CHECK: tail call float @llvm.fmuladd
54*67e74705SXin Li return a * b + c;
55*67e74705SXin Li }
56*67e74705SXin Li
57*67e74705SXin Li #pragma STDC FP_CONTRACT OFF
fp_contract_6(float a,float b,float c)58*67e74705SXin Li float fp_contract_6(float a, float b, float c) {
59*67e74705SXin Li // CHECK: _Z13fp_contract_6fff
60*67e74705SXin Li // CHECK: %[[M:.+]] = fmul float %a, %b
61*67e74705SXin Li // CHECK-NEXT: fadd float %[[M]], %c
62*67e74705SXin Li return a * b + c;
63*67e74705SXin Li }
64*67e74705SXin Li
65*67e74705SXin Li // If the multiply has multiple uses, don't produce fmuladd.
66*67e74705SXin Li // This used to assert (PR25719):
67*67e74705SXin Li // https://llvm.org/bugs/show_bug.cgi?id=25719
68*67e74705SXin Li
fp_contract_7(float a,float b,float c)69*67e74705SXin Li float fp_contract_7(float a, float b, float c) {
70*67e74705SXin Li // CHECK: _Z13fp_contract_7fff
71*67e74705SXin Li // CHECK: %[[M:.+]] = fmul float %b, 2.000000e+00
72*67e74705SXin Li // CHECK-NEXT: fsub float %[[M]], %c
73*67e74705SXin Li #pragma STDC FP_CONTRACT ON
74*67e74705SXin Li return (a = 2 * b) - c;
75*67e74705SXin Li }
76*67e74705SXin Li
77