selective_build.h
1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16 
17 #pragma once
18 
19 /*
20  This file contains a useful API for analyzing OpenVINO sources
21  and enabling or disabling some regions.
22  Three working modes are currently supported.
23  * SELECTIVE_BUILD_ANALYZER This macro enables analysis mode for annotated code regions.
24  * When the process completes, a new C++ header file is created
25  * that contains macros for enabling active regions. This file
26  * should be included in all analysed C++ files.
27  *
28  * SELECTIVE_BUILD This mode disables inactive areas of the code using the result
29  * of the analysis step.
30  *
31  * No definitions The default behavior is keept if no SELECTIVE_BUILD* macros are defined,
32  * i.e all features of the OpenVINO are enabled.
33  *
34  * Prerequisites:
35  * Before using macros for code annotation,domains for conditional
36  * compilation should be defined in module namespace.
37  *
38  * OV_CC_DOMAINS(MyModule);
39  *
40  * An example of using annotation:
41  *
42  * I. Any C++ code block:
43  * OV_SCOPE(MyModule, ScopeName) {
44  * // Any C++ code.
45  * cout << "Hello world!";
46  * }
47  *
48  * II. Template class instantiation using switch-case:
49  *
50  * struct Context { ... };
51  *
52  * template<typename T>
53  * struct SomeTemplateClass {
54  * void operator()(Context &context) {
55  * // Any C++ code.
56  * cout << "Hello world!";
57  * }
58  * };
59  *
60  * auto key = Precision::U8;
61  * Context context;
62  *
63  * OV_SWITCH(MyModule, SomeTemplateClass, context, key,
64  * OV_CASE(Precision::U8, uint8_t),
65  * OV_CASE(Precision::I8, int8_t),
66  * OV_CASE(Precision::FP32, float));
67  *
68 */
69 
70 #include <openvino/pp.hpp>
71 #include <openvino/itt.hpp>
72 
73 #define OV_CC_EXPAND OV_PP_EXPAND
74 #define OV_CC_CAT OV_PP_CAT
75 #define OV_CC_TOSTRING OV_PP_TOSTRING
76 
77 #ifdef SELECTIVE_BUILD_ANALYZER
78 # include <string>
79 #endif
80 
81 #include <utility>
82 #include <tuple>
83 
84 namespace openvino {
85 namespace cc {
86 
87 #ifndef SELECTIVE_BUILD_ANALYZER
88 
89 namespace internal {
90 
91 template<typename C, typename T>
92 struct case_wrapper {
93  using type = T;
94  const C value {};
95 
96  case_wrapper(C && val)
97  : value(std::forward<C>(val))
98  {}
99 };
100 
101 template<typename T, typename C>
102 case_wrapper<C, T> make_case_wrapper(C && val) {
103  return case_wrapper<C, T>(std::forward<C>(val));
104 }
105 
106 template<template<typename...> class Fn, typename Ctx, typename T, typename Case>
107 bool match(Ctx && ctx, T && val, Case && cs) {
108  const bool is_matched = val == cs.value;
109  if (is_matched)
110  Fn<typename Case::type>()(std::forward<Ctx>(ctx));
111  return is_matched;
112 }
113 
114 template<template<typename...> class Fn, typename Ctx, typename T, typename Case, typename ...Cases>
115 bool match(Ctx && ctx, T && val, Case && cs, Cases&&... cases) {
116  if (match<Fn>(std::forward<Ctx>(ctx), std::forward<T>(val), std::forward<Case>(cs)))
117  return true;
118  return match<Fn>(std::forward<Ctx>(ctx), std::forward<T>(val), std::forward<Cases>(cases)...);
119 }
120 
121 } // namespace internal
122 
123 #endif // SELECTIVE_BUILD_ANALYZER
124 
125 #ifdef SELECTIVE_BUILD_ANALYZER // OpenVINO analysis
126 
127 #define OV_CC_DOMAINS(Module) \
128  OV_ITT_DOMAIN(OV_PP_CAT(SIMPLE_, Module)); /* Domain for simple scope surrounded by ifdefs */ \
129  OV_ITT_DOMAIN(OV_PP_CAT(SWITCH_, Module)); /* Domain for switch/cases */ \
130  OV_ITT_DOMAIN(OV_PP_CAT(FACTORY_, Module)); /* Domain for factories */
131 
132 namespace internal {
133 
134 template<typename C, typename T>
135 struct case_wrapper {
136  using type = T;
137  const C value {};
138  const char *name = nullptr;
139 
140  case_wrapper(C && val, const char *name)
141  : value(std::forward<C>(val))
142  , name(name)
143  {}
144 };
145 
146 template<typename T, typename C>
147 case_wrapper<C, T> make_case_wrapper(C && val, const char *name) {
148  return case_wrapper<C, T>(std::forward<C>(val), name);
149 }
150 
151 template<openvino::itt::domain_t(*domain)(),
152  template<typename...> class Fn,
153  typename Ctx,
154  typename T,
155  typename Case>
156 bool match(char const *region, Ctx && ctx, T && val, Case && cs) {
157  const bool is_matched = val == cs.value;
158  if (is_matched) {
160  openvino::itt::handle(
161  std::string(region) + "$" + cs.name));
162  Fn<typename Case::type>()(std::forward<Ctx>(ctx));
163  }
164  return is_matched;
165 }
166 
167 template<openvino::itt::domain_t(*domain)(),
168  template<typename...> class Fn,
169  typename Ctx,
170  typename T,
171  typename Case, typename ...Cases>
172 bool match(char const *region, Ctx && ctx, T && val, Case && cs, Cases&&... cases) {
173  if (match<domain, Fn>(region, std::forward<Ctx>(ctx), std::forward<T>(val), std::forward<Case>(cs)))
174  return true;
175  return match<domain, Fn>(region, std::forward<Ctx>(ctx), std::forward<T>(val), std::forward<Cases>(cases)...);
176 }
177 
178 } // namespace internal
179 
180 #define OV_SCOPE(Module, region) \
181  OV_ITT_SCOPED_TASK(OV_PP_CAT(SIMPLE_, Module), OV_PP_TOSTRING(region));
182 
183 #define OV_SWITCH(Module, fn, ctx, val, ...) \
184  openvino::cc::internal::match<OV_PP_CAT(SWITCH_, Module), fn> \
185  (OV_PP_TOSTRING(fn), ctx, val, __VA_ARGS__);
186 
187 #define OV_CC_LBR (
188 #define OV_CC_RBR )
189 
190 #define OV_CASE(Case, Type) \
191  openvino::cc::internal::make_case_wrapper<Type>(Case, OV_PP_TOSTRING(OV_CASE OV_CC_LBR Case, Type OV_CC_RBR))
192 
193 #define OV_CASE2(Case1, Case2, Type1, Type2) \
194  openvino::cc::internal::make_case_wrapper<std::tuple<Type1, Type2>>( \
195  std::make_tuple(Case1, Case2), \
196  OV_PP_TOSTRING(OV_CASE2 OV_CC_LBR Case1, Case2, Type1, Type2 OV_CC_RBR))
197 
198 #elif defined(SELECTIVE_BUILD) // OpenVINO selective build is enabled
199 
200 #define OV_CC_DOMAINS(Module)
201 
202 // Placeholder for first macro argument
203 #define OV_CC_SCOPE_ARG_PLACEHOLDER_1 0,
204 
205 // This macro returns second argument, first argument is ignored
206 #define OV_CC_SCOPE_SECOND_ARG(...) OV_PP_EXPAND(OV_CC_SCOPE_SECOND_ARG_(__VA_ARGS__, 0))
207 #define OV_CC_SCOPE_SECOND_ARG_(...) OV_PP_EXPAND(OV_CC_SCOPE_SECOND_ARG_GET(__VA_ARGS__))
208 #define OV_CC_SCOPE_SECOND_ARG_GET(ignored, val, ...) val
209 
210 // Return macro argument value
211 #define OV_CC_SCOPE_IS_ENABLED(x) OV_CC_SCOPE_IS_ENABLED1(x)
212 
213 // Generate junk macro or {0, } sequence if val is 1
214 #define OV_CC_SCOPE_IS_ENABLED1(val) OV_CC_SCOPE_IS_ENABLED2(OV_PP_CAT(OV_CC_SCOPE_ARG_PLACEHOLDER_, val))
215 
216 // Return second argument from possible sequences {1, 0}, {0, 1, 0}
217 #define OV_CC_SCOPE_IS_ENABLED2(arg1_or_junk) OV_CC_SCOPE_SECOND_ARG(arg1_or_junk 1, 0)
218 
219 #define OV_SCOPE(Module, region) \
220  if (OV_CC_SCOPE_IS_ENABLED(OV_PP_CAT3(Module, _, region)))
221 
222 // Switch is disabled
223 #define OV_CC_SWITCH_0(Module, fn, ctx, val)
224 
225 // Switch is enabled
226 #define OV_CC_SWITCH_1(Module, fn, ctx, val) openvino::cc::internal::match<fn>(ctx, val, OV_PP_CAT4(Module, _, fn, _cases));
227 
228 #define OV_SWITCH(Module, fn, ctx, val, ...) \
229  OV_PP_EXPAND(OV_PP_CAT(OV_CC_SWITCH_, OV_CC_SCOPE_IS_ENABLED(OV_PP_CAT3(Module, _, fn)))(Module, fn, ctx, val))
230 
231 #define OV_CASE(Case, Type) openvino::cc::internal::make_case_wrapper<Type>(Case)
232 
233 #define OV_CASE2(Case1, Case2, Type1, Type2) openvino::cc::internal::make_case_wrapper<std::tuple<Type1, Type2>>(std::make_tuple(Case1, Case2))
234 
235 #else
236 
237 #define OV_CC_DOMAINS(Module)
238 
239 #define OV_SCOPE(Module, region)
240 
241 #define OV_SWITCH(Module, fn, ctx, val, ...) \
242  openvino::cc::internal::match<fn>(ctx, val, __VA_ARGS__);
243 
244 #define OV_CASE(Case, Type) openvino::cc::internal::make_case_wrapper<Type>(Case)
245 
246 #define OV_CASE2(Case1, Case2, Type1, Type2) openvino::cc::internal::make_case_wrapper<std::tuple<Type1, Type2>>(std::make_tuple(Case1, Case2))
247 
248 #endif
249 
250 } // namespace cc
251 } // namespace openvino
C
Defines API to trace using Intel ITT.
Set of macro used by openvino.
Definition: selective_build.h:92
Used to annotate section of code which would be named at runtime.
Definition: itt.hpp:121
Definition: itt.hpp:37