1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef HIGHWAY_HWY_FOREACH_TARGET_H_
16 #define HIGHWAY_HWY_FOREACH_TARGET_H_
17 
18 // Re-includes the translation unit zero or more times to compile for any
19 // targets except HWY_STATIC_TARGET. Defines unique HWY_TARGET each time so that
20 // highway.h defines the corresponding macro/namespace.
21 
22 #include "hwy/targets.h"
23 
24 // *_inl.h may include other headers, which requires include guards to prevent
25 // repeated inclusion. The guards must be reset after compiling each target, so
26 // the header is again visible. This is done by flipping HWY_TARGET_TOGGLE,
27 // defining it if undefined and vice versa. This macro is initially undefined
28 // so that IDEs don't gray out the contents of each header.
29 #ifdef HWY_TARGET_TOGGLE
30 #error "This macro must not be defined outside foreach_target.h"
31 #endif
32 
33 #ifdef HWY_HIGHWAY_INCLUDED  // highway.h include guard
34 // Trigger fixup at the bottom of this header.
35 #define HWY_ALREADY_INCLUDED
36 
37 // The next highway.h must re-include set_macros-inl.h because the first
38 // highway.h chose the static target instead of what we will set below.
39 #undef HWY_SET_MACROS_PER_TARGET
40 #endif
41 
42 // Disable HWY_EXPORT in user code until we have generated all targets. Note
43 // that a subsequent highway.h will not override this definition.
44 #undef HWY_ONCE
45 #define HWY_ONCE (0 || HWY_IDE)
46 
47 // Avoid warnings on #include HWY_TARGET_INCLUDE by hiding them from the IDE;
48 // also skip if only 1 target defined (no re-inclusion will be necessary).
49 #if !HWY_IDE && (HWY_TARGETS != HWY_STATIC_TARGET)
50 
51 #if !defined(HWY_TARGET_INCLUDE)
52 #error ">1 target enabled => define HWY_TARGET_INCLUDE before foreach_target.h"
53 #endif
54 
55 #if (HWY_TARGETS & HWY_SCALAR) && (HWY_STATIC_TARGET != HWY_SCALAR)
56 #undef HWY_TARGET
57 #define HWY_TARGET HWY_SCALAR
58 #include HWY_TARGET_INCLUDE
59 #ifdef HWY_TARGET_TOGGLE
60 #undef HWY_TARGET_TOGGLE
61 #else
62 #define HWY_TARGET_TOGGLE
63 #endif
64 #endif
65 
66 #if (HWY_TARGETS & HWY_NEON) && (HWY_STATIC_TARGET != HWY_NEON)
67 #undef HWY_TARGET
68 #define HWY_TARGET HWY_NEON
69 #include HWY_TARGET_INCLUDE
70 #ifdef HWY_TARGET_TOGGLE
71 #undef HWY_TARGET_TOGGLE
72 #else
73 #define HWY_TARGET_TOGGLE
74 #endif
75 #endif
76 
77 #if (HWY_TARGETS & HWY_SSE4) && (HWY_STATIC_TARGET != HWY_SSE4)
78 #undef HWY_TARGET
79 #define HWY_TARGET HWY_SSE4
80 #include HWY_TARGET_INCLUDE
81 #ifdef HWY_TARGET_TOGGLE
82 #undef HWY_TARGET_TOGGLE
83 #else
84 #define HWY_TARGET_TOGGLE
85 #endif
86 #endif
87 
88 #if (HWY_TARGETS & HWY_AVX2) && (HWY_STATIC_TARGET != HWY_AVX2)
89 #undef HWY_TARGET
90 #define HWY_TARGET HWY_AVX2
91 #include HWY_TARGET_INCLUDE
92 #ifdef HWY_TARGET_TOGGLE
93 #undef HWY_TARGET_TOGGLE
94 #else
95 #define HWY_TARGET_TOGGLE
96 #endif
97 #endif
98 
99 #if (HWY_TARGETS & HWY_AVX3) && (HWY_STATIC_TARGET != HWY_AVX3)
100 #undef HWY_TARGET
101 #define HWY_TARGET HWY_AVX3
102 #include HWY_TARGET_INCLUDE
103 #ifdef HWY_TARGET_TOGGLE
104 #undef HWY_TARGET_TOGGLE
105 #else
106 #define HWY_TARGET_TOGGLE
107 #endif
108 #endif
109 
110 #if (HWY_TARGETS & HWY_WASM) && (HWY_STATIC_TARGET != HWY_WASM)
111 #undef HWY_TARGET
112 #define HWY_TARGET HWY_WASM
113 #include HWY_TARGET_INCLUDE
114 #ifdef HWY_TARGET_TOGGLE
115 #undef HWY_TARGET_TOGGLE
116 #else
117 #define HWY_TARGET_TOGGLE
118 #endif
119 #endif
120 
121 #if (HWY_TARGETS & HWY_PPC8) && (HWY_STATIC_TARGET != HWY_PPC8)
122 #undef HWY_TARGET
123 #define HWY_TARGET HWY_PPC8
124 #include HWY_TARGET_INCLUDE
125 #ifdef HWY_TARGET_TOGGLE
126 #undef HWY_TARGET_TOGGLE
127 #else
128 #define HWY_TARGET_TOGGLE
129 #endif
130 #endif
131 
132 #endif  // !HWY_IDE && (HWY_TARGETS != HWY_STATIC_TARGET)
133 
134 // Now that all but the static target have been generated, re-enable HWY_EXPORT.
135 #undef HWY_ONCE
136 #define HWY_ONCE 1
137 
138 // If we re-include once per enabled target, the translation unit's
139 // implementation would have to be skipped via #if to avoid redefining symbols.
140 // We instead skip the re-include for HWY_STATIC_TARGET, and generate its
141 // implementation when resuming compilation of the translation unit.
142 #undef HWY_TARGET
143 #define HWY_TARGET HWY_STATIC_TARGET
144 
145 #ifdef HWY_ALREADY_INCLUDED
146 // Revert the previous toggle to prevent redefinitions for the static target.
147 #ifdef HWY_TARGET_TOGGLE
148 #undef HWY_TARGET_TOGGLE
149 #else
150 #define HWY_TARGET_TOGGLE
151 #endif
152 
153 // Force re-inclusion of set_macros-inl.h now that HWY_TARGET is restored.
154 #ifdef HWY_SET_MACROS_PER_TARGET
155 #undef HWY_SET_MACROS_PER_TARGET
156 #else
157 #define HWY_SET_MACROS_PER_TARGET
158 #endif
159 #endif
160 
161 #endif  // HIGHWAY_HWY_FOREACH_TARGET_H_
162