code: def local_conv2d_gradinputs_cpu(node):
      if (
          not isinstance(node.op, AbstractConv2d_gradInputs)
          or node.inputs[0].dtype == "float16"
      ):
          return None
  
      kern, topgrad, shape = node.inputs
  
      if not isinstance(kern.type, TensorType) or not isinstance(
          topgrad.type, TensorType
      ):
          return None
      if node.op.border_mode not in ["full", "valid"]:
          return None
      if not node.op.filter_flip:
          # Not tested yet
          return None
      if node.op.num_groups > 1 or node.op.unshared:
          return None
  
      # Conv 3d implementation, needed when subsample > 2
      if node.op.border_mode == "valid" and node.op.subsample != (1, 1):
          # The op don't support that anymore.
          return False
  
      # Conv2d Implementation
      dx, dy = node.op.subsample
      if dx not in (1, 2) or dy not in (1, 2):
          # Not implemented in the gradient of ConvOp
          return None
  
      if node.op.imshp is None:
          op_imshp = (None, None, None, None)
      else:
          op_imshp = node.op.imshp
  
      if node.op.kshp is None:
          op_kshp = (None, None, None, None)
      else:
          op_kshp = node.op.kshp
  
      if None in op_imshp or None in op_kshp:
          if (dx, dy) != (1, 1):
              return None
  
      mode = "valid"
      if not node.op.border_mode == "full":
          mode = "full"
      filters = kern.dimshuffle((1, 0, 2, 3))
      filters = filters[:, :, ::-1, ::-1]
  
      outshp = get_conv_output_shape(
          op_imshp,
          op_kshp,
          node.op.border_mode,
          node.op.subsample,
          node.op.filter_dilation,
      )[2:]
      fulloutshp = get_conv_output_shape(
          op_imshp, op_kshp, node.op.border_mode, (1, 1)
      )[2:]
  
      nkern = op_imshp[1]
      imshp = (op_kshp[0], outshp[0], outshp[1])
      imshp_logical = (op_kshp[0], fulloutshp[0], fulloutshp[1])
      din = ConvOp(
          imshp,
          op_kshp[2:],
          nkern,
          op_imshp[0],
          1,
          1,
          output_mode=mode,
          unroll_batch=None,
          unroll_kern=None,
          unroll_patch=None,
          imshp_logical=imshp_logical,
          kshp_logical=None,
          version=-1,
          direction_hint="bprop inputs",
      )
      din = din(topgrad, filters)
      copy_stack_trace(node.outputs[0], din)
      din = theano.tensor.patternbroadcast(
          din, node.outputs[0].broadcastable
      )
      copy_stack_trace(node.outputs[0], din)
      return [din]
  
imports: from __future__ import absolute_import, print_function, division
  import theano
  from theano import compile, gof
  from theano.compile import optdb
  from theano.gof import local_optimizer
  from theano.gof.opt import copy_stack_trace
  from theano.tensor.nnet.corr import CorrMM, CorrMM_gradInputs, CorrMM_gradWeights
  from theano.tensor.nnet.corr3d import Corr3dMM, Corr3dMM_gradInputs, Corr3dMM_gradWeights
  from theano.tensor.nnet.blocksparse import SparseBlockGemv, SparseBlockOuter, sparse_block_gemv_inplace, sparse_block_outer_inplace
  from theano.tensor.nnet.abstract_conv import AbstractConv2d, AbstractConv2d_gradWeights, AbstractConv2d_gradInputs
  from theano.tensor.nnet.abstract_conv import AbstractConv3d, AbstractConv3d_gradWeights, AbstractConv3d_gradInputs
  from theano.tensor.nnet.abstract_conv import get_conv_output_shape
  from theano.tensor.opt import register_specialize_device
  from theano.tensor import TensorType
  from theano.tensor import opt
  from theano.tensor.nnet.conv import conv2d, ConvOp
label_desc: Use image node_id 11 for calling a global function with example usage: local_conv2d_gradinputs_cpu(node) and returns: list, None, None, None, None, None, False, None, None