xref: /aosp_15_r20/external/XNNPACK/src/subgraph/validation.c (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1*4bdc9457SAndroid Build Coastguard Worker // Copyright 2022 Google LLC
2*4bdc9457SAndroid Build Coastguard Worker //
3*4bdc9457SAndroid Build Coastguard Worker // This source code is licensed under the BSD-style license found in the
4*4bdc9457SAndroid Build Coastguard Worker // LICENSE file in the root directory of this source tree.
5*4bdc9457SAndroid Build Coastguard Worker 
6*4bdc9457SAndroid Build Coastguard Worker #include <assert.h>
7*4bdc9457SAndroid Build Coastguard Worker #include <math.h>
8*4bdc9457SAndroid Build Coastguard Worker 
9*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack.h>
10*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/log.h>
11*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/params.h>
12*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/subgraph.h>
13*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/subgraph-validation.h>
14*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_xnnpack_initialized(enum xnn_node_type node_type)15*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_xnnpack_initialized(enum xnn_node_type node_type)
16*4bdc9457SAndroid Build Coastguard Worker {
17*4bdc9457SAndroid Build Coastguard Worker   if ((xnn_params.init_flags & XNN_INIT_FLAG_XNNPACK) == 0) {
18*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error("failed to define %s operator: XNNPACK is not initialized", xnn_node_type_to_string(node_type));
19*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_uninitialized;
20*4bdc9457SAndroid Build Coastguard Worker   }
21*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
22*4bdc9457SAndroid Build Coastguard Worker }
23*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_input_node_id(enum xnn_node_type node_type,uint32_t input_id,size_t num_values)24*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_input_node_id(enum xnn_node_type node_type, uint32_t input_id, size_t num_values)
25*4bdc9457SAndroid Build Coastguard Worker {
26*4bdc9457SAndroid Build Coastguard Worker   if (input_id >= num_values) {
27*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
28*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with input ID #%" PRIu32 ": invalid Value ID",
29*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), input_id);
30*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
31*4bdc9457SAndroid Build Coastguard Worker   }
32*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
33*4bdc9457SAndroid Build Coastguard Worker }
34*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_nth_input_node_id(enum xnn_node_type node_type,uint32_t input_id,size_t num_values,size_t nth)35*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_nth_input_node_id(
36*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
37*4bdc9457SAndroid Build Coastguard Worker   uint32_t input_id,
38*4bdc9457SAndroid Build Coastguard Worker   size_t num_values,
39*4bdc9457SAndroid Build Coastguard Worker   size_t nth)
40*4bdc9457SAndroid Build Coastguard Worker {
41*4bdc9457SAndroid Build Coastguard Worker   if (input_id >= num_values) {
42*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
43*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with the input %zu ID #%" PRIu32 ": invalid Value ID",
44*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), nth, input_id);
45*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
46*4bdc9457SAndroid Build Coastguard Worker   }
47*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
48*4bdc9457SAndroid Build Coastguard Worker }
49*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_input_type_dense(enum xnn_node_type node_type,uint32_t input_id,const struct xnn_value * input_value)50*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_input_type_dense(
51*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
52*4bdc9457SAndroid Build Coastguard Worker   uint32_t input_id,
53*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* input_value)
54*4bdc9457SAndroid Build Coastguard Worker {
55*4bdc9457SAndroid Build Coastguard Worker   if (input_value->type != xnn_value_type_dense_tensor) {
56*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
57*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with input ID #%" PRIu32 ": unsupported Value type %d (expected dense tensor)",
58*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), input_id, input_value->type);
59*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
60*4bdc9457SAndroid Build Coastguard Worker   }
61*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
62*4bdc9457SAndroid Build Coastguard Worker }
63*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_nth_input_type_dense(enum xnn_node_type node_type,uint32_t input_id,const struct xnn_value * input_value,size_t nth)64*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_nth_input_type_dense(
65*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
66*4bdc9457SAndroid Build Coastguard Worker   uint32_t input_id,
67*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* input_value,
68*4bdc9457SAndroid Build Coastguard Worker   size_t nth)
69*4bdc9457SAndroid Build Coastguard Worker {
70*4bdc9457SAndroid Build Coastguard Worker   if (input_value->type != xnn_value_type_dense_tensor) {
71*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
72*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with %zu input ID #%" PRIu32 ": unsupported Value type %d (expected dense tensor)",
73*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), nth, input_id, input_value->type);
74*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
75*4bdc9457SAndroid Build Coastguard Worker   }
76*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
77*4bdc9457SAndroid Build Coastguard Worker }
78*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_output_node_id(enum xnn_node_type node_type,uint32_t output_id,size_t num_values)79*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_output_node_id(enum xnn_node_type node_type, uint32_t output_id, size_t num_values)
80*4bdc9457SAndroid Build Coastguard Worker {
81*4bdc9457SAndroid Build Coastguard Worker   if (output_id >= num_values) {
82*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
83*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with output ID #%" PRIu32 ": invalid Value ID",
84*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), output_id);
85*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
86*4bdc9457SAndroid Build Coastguard Worker   }
87*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
88*4bdc9457SAndroid Build Coastguard Worker }
89*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_output_type_dense(enum xnn_node_type node_type,uint32_t output_id,const struct xnn_value * output_value)90*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_output_type_dense(
91*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
92*4bdc9457SAndroid Build Coastguard Worker   uint32_t output_id,
93*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* output_value)
94*4bdc9457SAndroid Build Coastguard Worker {
95*4bdc9457SAndroid Build Coastguard Worker   if (output_value->type != xnn_value_type_dense_tensor) {
96*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
97*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with output ID #%" PRIu32 ": unsupported Value type %d (expected dense tensor)",
98*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), output_id, output_value->type);
99*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
100*4bdc9457SAndroid Build Coastguard Worker   }
101*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
102*4bdc9457SAndroid Build Coastguard Worker }
103*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_datatype_matches(enum xnn_node_type node_type,uint32_t input_id,const struct xnn_value * input_value,uint32_t output_id,const struct xnn_value * output_value)104*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_datatype_matches(
105*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
106*4bdc9457SAndroid Build Coastguard Worker   uint32_t input_id,
107*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* input_value,
108*4bdc9457SAndroid Build Coastguard Worker   uint32_t output_id,
109*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* output_value)
110*4bdc9457SAndroid Build Coastguard Worker {
111*4bdc9457SAndroid Build Coastguard Worker   assert(input_value->datatype != xnn_datatype_invalid);
112*4bdc9457SAndroid Build Coastguard Worker   assert(output_value->datatype != xnn_datatype_invalid);
113*4bdc9457SAndroid Build Coastguard Worker   if (input_value->datatype != output_value->datatype) {
114*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
115*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with input ID #%" PRIu32 " and output ID #%" PRIu32
116*4bdc9457SAndroid Build Coastguard Worker       ": mismatching datatypes across the input (%s) and output (%s)",
117*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), input_id, output_id,
118*4bdc9457SAndroid Build Coastguard Worker       xnn_datatype_to_string(input_value->datatype),
119*4bdc9457SAndroid Build Coastguard Worker       xnn_datatype_to_string(output_value->datatype));
120*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
121*4bdc9457SAndroid Build Coastguard Worker   }
122*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
123*4bdc9457SAndroid Build Coastguard Worker }
124*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_datatype_matches_two_inputs(enum xnn_node_type node_type,uint32_t input1_id,const struct xnn_value * input1_value,uint32_t input2_id,const struct xnn_value * input2_value,uint32_t output_id,const struct xnn_value * output_value)125*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_datatype_matches_two_inputs(
126*4bdc9457SAndroid Build Coastguard Worker   enum xnn_node_type node_type,
127*4bdc9457SAndroid Build Coastguard Worker   uint32_t input1_id,
128*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* input1_value,
129*4bdc9457SAndroid Build Coastguard Worker   uint32_t input2_id,
130*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* input2_value,
131*4bdc9457SAndroid Build Coastguard Worker   uint32_t output_id,
132*4bdc9457SAndroid Build Coastguard Worker   const struct xnn_value* output_value)
133*4bdc9457SAndroid Build Coastguard Worker {
134*4bdc9457SAndroid Build Coastguard Worker   assert(input1_value->datatype != xnn_datatype_invalid);
135*4bdc9457SAndroid Build Coastguard Worker   assert(input2_value->datatype != xnn_datatype_invalid);
136*4bdc9457SAndroid Build Coastguard Worker   assert(output_value->datatype != xnn_datatype_invalid);
137*4bdc9457SAndroid Build Coastguard Worker   if (input1_value->datatype != input2_value->datatype ||
138*4bdc9457SAndroid Build Coastguard Worker       input1_value->datatype != output_value->datatype)
139*4bdc9457SAndroid Build Coastguard Worker   {
140*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
141*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with input IDs #%" PRIu32 " and #%" PRIu32 " and output ID #%" PRIu32
142*4bdc9457SAndroid Build Coastguard Worker       ": mismatching datatypes across the first input (%s), the second input (%s), and output (%s)",
143*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), input1_id, input2_id, output_id,
144*4bdc9457SAndroid Build Coastguard Worker       xnn_datatype_to_string(input1_value->datatype),
145*4bdc9457SAndroid Build Coastguard Worker       xnn_datatype_to_string(input2_value->datatype),
146*4bdc9457SAndroid Build Coastguard Worker       xnn_datatype_to_string(output_value->datatype));
147*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
148*4bdc9457SAndroid Build Coastguard Worker   }
149*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
150*4bdc9457SAndroid Build Coastguard Worker }
151*4bdc9457SAndroid Build Coastguard Worker 
152*4bdc9457SAndroid Build Coastguard Worker 
xnn_subgraph_check_output_min_max(enum xnn_node_type node_type,float output_min,float output_max)153*4bdc9457SAndroid Build Coastguard Worker enum xnn_status xnn_subgraph_check_output_min_max(enum xnn_node_type node_type, float output_min, float output_max)
154*4bdc9457SAndroid Build Coastguard Worker {
155*4bdc9457SAndroid Build Coastguard Worker   if (isnan(output_min)) {
156*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
157*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with NaN output lower bound: lower bound must be non-NaN",
158*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type));
159*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
160*4bdc9457SAndroid Build Coastguard Worker   }
161*4bdc9457SAndroid Build Coastguard Worker 
162*4bdc9457SAndroid Build Coastguard Worker   if (isnan(output_max)) {
163*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
164*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with NaN output upper bound: upper bound must be non-NaN",
165*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type));
166*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
167*4bdc9457SAndroid Build Coastguard Worker   }
168*4bdc9457SAndroid Build Coastguard Worker 
169*4bdc9457SAndroid Build Coastguard Worker   if (output_min >= output_max) {
170*4bdc9457SAndroid Build Coastguard Worker     xnn_log_error(
171*4bdc9457SAndroid Build Coastguard Worker       "failed to define %s operator with [%.7g, %.7g] output range: lower bound must be below upper bound",
172*4bdc9457SAndroid Build Coastguard Worker       xnn_node_type_to_string(node_type), output_min, output_max);
173*4bdc9457SAndroid Build Coastguard Worker     return xnn_status_invalid_parameter;
174*4bdc9457SAndroid Build Coastguard Worker   }
175*4bdc9457SAndroid Build Coastguard Worker   return xnn_status_success;
176*4bdc9457SAndroid Build Coastguard Worker }
177