xref: /llvm-project/clang/test/CodeGen/fp-reciprocal-pragma.cpp (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
1 // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,DEFAULT %s
2 // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -freciprocal-math -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,FLAG %s
3 
4 float base(float a, float b, float c) {
5 // CHECK-LABEL: _Z4basefff
6 // FLAG: %[[A:.+]] = fdiv arcp float %b, %c
7 // FLAG: %[[M:.+]] = fdiv arcp float %[[A]], %b
8 // FLAG-NEXT: fadd arcp float %c, %[[M]]
9 
10 // DEFAULT: %[[A:.+]] = fdiv float %b, %c
11 // DEFAULT: %[[M:.+]] = fdiv float %[[A]], %b
12 // DEFAULT-NEXT: fadd float %c, %[[M]]
13   a = b / c;
14   return a / b + c;
15 }
16 
17 // Simple case
18 float fp_recip_simple(float a, float b, float c) {
19 // CHECK-LABEL: _Z15fp_recip_simplefff
20 // CHECK: %[[A:.+]] = fdiv arcp float %b, %c
21 // CHECK: %[[M:.+]] = fdiv arcp float %[[A]], %b
22 // CHECK-NEXT: fadd arcp float %c, %[[M]]
23 #pragma clang fp reciprocal(on)
24   a = b / c;
25   return a / b + c;
26 }
27 
28 // Test interaction with -freciprocal-math
29 float fp_recip_disable(float a, float b, float c) {
30 // CHECK-LABEL: _Z16fp_recip_disablefff
31 // CHECK: %[[A:.+]] = fdiv float %b, %c
32 // CHECK: %[[M:.+]] = fdiv float %[[A]], %b
33 // CHECK-NEXT: fadd float %c, %[[M]]
34 #pragma clang fp reciprocal(off)
35   a = b / c;
36   return a / b + c;
37 }
38 
39 float fp_recip_with_reassoc_simple(float a, float b, float c) {
40 // CHECK-LABEL: _Z28fp_recip_with_reassoc_simplefff
41 // CHECK: %[[A:.+]] = fmul reassoc arcp float %b, %c
42 // CHECK: %[[M:.+]] = fdiv reassoc arcp float %b, %[[A]]
43 // CHECK-NEXT: fadd reassoc arcp float %c, %[[M]]
44 #pragma clang fp reciprocal(on) reassociate(on)
45   a = b / c;
46   return a / b + c;
47 }
48 
49 // arcp pragma should only apply to its scope
50 float fp_recip_scoped(float a, float b, float c) {
51   // CHECK-LABEL: _Z15fp_recip_scopedfff
52   // DEFAULT: %[[M:.+]] = fdiv float %a, %b
53   // DEFAULT-NEXT: fadd float %[[M]], %c
54   // FLAG: %[[M:.+]] = fdiv arcp float %a, %b
55   // FLAG-NEXT: fadd arcp float %[[M]], %c
56   {
57 #pragma clang fp reciprocal(on)
58   }
59   return a / b + c;
60 }
61 
62 // arcp pragma should apply to templates as well
63 class Foo {};
64 Foo operator+(Foo, Foo);
65 template <typename T>
66 T template_recip(T a, T b, T c) {
67 #pragma clang fp reciprocal(on)
68   return ((a / b) - c) + c;
69 }
70 
71 float fp_recip_template(float a, float b, float c) {
72   // CHECK-LABEL: _Z17fp_recip_templatefff
73   // CHECK: %[[A1:.+]] = fdiv arcp float %a, %b
74   // CHECK-NEXT: %[[A2:.+]] = fsub arcp float %[[A1]], %c
75   // CHECK-NEXT: fadd arcp float %c, %[[A2]]
76   return template_recip<float>(a, b, c);
77 }
78 
79 // File Scoping should work across functions
80 #pragma clang fp reciprocal(on)
81 float fp_file_scope_on(float a, float b, float c) {
82   // CHECK-LABEL: _Z16fp_file_scope_onfff
83   // CHECK: %[[M1:.+]] = fdiv arcp float %a, %c
84   // CHECK-NEXT: %[[M2:.+]] = fdiv arcp float %b, %c
85   // CHECK-NEXT: fadd arcp float %[[M1]], %[[M2]]
86   return (a / c) + (b / c);
87 }
88 
89 // Inner pragma has precedence
90 float fp_file_scope_stop(float a, float b, float c) {
91   // CHECK-LABEL: _Z18fp_file_scope_stopfff
92   // CHECK: %[[A:.+]] = fdiv arcp float %a, %a
93   // CHECK: %[[M1:.+]] = fdiv float %[[A]], %c
94   // CHECK-NEXT: %[[M2:.+]] = fdiv float %b, %c
95   // CHECK-NEXT: fsub float %[[M1]], %[[M2]]
96   a = a / a;
97   {
98 #pragma clang fp reciprocal(off)
99     return (a / c) - (b / c);
100   }
101 }
102 
103 #pragma clang fp reciprocal(off)
104 float fp_recip_off(float a, float b, float c) {
105   // CHECK-LABEL: _Z12fp_recip_offfff
106   // CHECK: %[[D1:.+]] = fdiv float %a, %c
107   // CHECK-NEXT: %[[D2:.+]] = fdiv float %b, %c
108   // CHECK-NEXT: fadd float %[[D1]], %[[D2]]
109   return (a / c) + (b / c);
110 }
111 
112 // Takes latest flag
113 float fp_recip_many(float a, float b, float c) {
114 // CHECK-LABEL: _Z13fp_recip_manyfff
115 // CHECK: %[[D1:.+]] = fdiv arcp float %a, %c
116 // CHECK-NEXT: %[[D2:.+]] = fdiv arcp float %b, %c
117 // CHECK-NEXT: fadd arcp float %[[D1]], %[[D2]]
118 #pragma clang fp reciprocal(off) reciprocal(on)
119   return (a / c) + (b / c);
120 }
121 
122 // Pragma does not propagate through called functions
123 float helper_func(float a, float b, float c) { return a + b + c; }
124 float fp_recip_call_helper(float a, float b, float c) {
125 // CHECK-LABEL: _Z20fp_recip_call_helperfff
126 // CHECK: %[[S1:.+]] = fadd float %a, %b
127 // CHECK-NEXT: fadd float %[[S1]], %c
128 #pragma clang fp reciprocal(on)
129   return helper_func(a, b, c);
130 }
131