Returns true if n can be evaluated as constant. shape_map maps from nodes to the partially-known shapes of their outputs. consider if non-null returns a bool indicating whether a given (non-Const, non-Shape) node is eligible to be constant-propagated. shape_replacement_map is filled in with a vector of constant output tensors for constant-foldable shape nodes (Shape, ShapeN, Size, or Rank).
| 214 | // vector of constant output tensors for constant-foldable shape nodes |
| 215 | // (Shape, ShapeN, Size, or Rank). |
| 216 | bool IsConstantFoldable( |
| 217 | const Node* n, |
| 218 | const std::unordered_map<string, std::vector<PartialTensorShape>>* |
| 219 | shape_map, |
| 220 | const std::function<bool(const Node*)>& consider, |
| 221 | std::unordered_map<const Node*, std::vector<Tensor>>* |
| 222 | shape_replacement_map) { |
| 223 | if (n->IsConstant()) { |
| 224 | // Skip constant folding resources as they cannot be deep copied. |
| 225 | return n->output_type(0) != DT_RESOURCE; |
| 226 | } |
| 227 | if (MaybeReplaceShapeOp(n, shape_map, shape_replacement_map)) { |
| 228 | return true; |
| 229 | } |
| 230 | if (n->op_def().is_stateful()) { |
| 231 | return false; |
| 232 | } |
| 233 | if (consider && !consider(n)) { |
| 234 | return false; |
| 235 | } |
| 236 | if (n->IsControlFlow() || n->IsSend() || |
| 237 | n->IsRecv() || n->IsFuseRecv() || |
| 238 | n->def().op() == "RunGraph" || |
| 239 | n->def().op() == "StarRunGraph") { |
| 240 | return false; |
| 241 | } |
| 242 | // TODO(yuanbyu): For now disable these session handle operations. |
| 243 | if (n->IsGetSessionHandle() || n->IsGetSessionTensor() || |
| 244 | n->IsDeleteSessionTensor()) { |
| 245 | return false; |
| 246 | } |
| 247 | if (n->IsSource()) { |
| 248 | return false; |
| 249 | } |
| 250 | if (n->IsSink()) { |
| 251 | return false; |
| 252 | } |
| 253 | if (n->IsFakeParam()) { |
| 254 | return false; |
| 255 | } |
| 256 | // Since constant-folding runs on the CPU, do not attempt to constant-fold |
| 257 | // operators that have no CPU kernel. Also implies that we will not |
| 258 | // constant-fold functions. |
| 259 | // TODO(phawkins): allow constant-folding for functions; functions may |
| 260 | // be arbitrarily expensive to execute. |
| 261 | if (!KernelDefAvailable(DeviceType(DEVICE_CPU), n->def())) { |
| 262 | return false; |
| 263 | } |
| 264 | return true; |
| 265 | } |
| 266 | |
| 267 | // If n is eligible for constant-folding, adds it to nodes, and places its |
| 268 | // control dependencies and those transitively of its constant-foldable inputs |
no test coverage detected