class_docstr: Legalize QNN based patterns to match DNNL
  
  original pattern:
    OP = qnn.dense | qnn.conv2d
    %1 = OP<int>(SRC, WGH) - OP<int>(src_zp, WGH)   // qnn.conv2d
    %2 = %1 + orig_bias                             // bias
    %2 = (%1 - rq_in_zp) * rq_in_scl / rq_out_scl + rq_out_zp  // qnn.requantize
    %3 = act(%2)                                               // activation == clip
    %4 = ((%3 - sum_lh_zp) * sum_lh_scl + (SRC2 - sum_rh_zp) * sum_rh_scl)  // qnn.add
         / sum_out_scl + sum_out_zp
  
  transform to DNNL compatible:
    %1 = OP<int>(SRC, WGH)
    %2 = cast(%1, dtype="float")
    %2 = (%1 + bias) * o_scl
    %3 = act(%2) * act_scl
    %4 = %3 + SRC2 * sum_scl
    %5 = %4 + dst_zp
    %6 = cast(%5, dtype="float")
  
  where:
    o_scl = rq_in_scl / rq_out_scl
    act_scl = sum_lhs_scl / sum_out_scl
    sum_scl = sum_rhs_scl / sum_out_scl
    bias = orig_bias - OP(src_zp, WGH) - rq_in_zp + rq_out_zp * rq_out_scl / rq_in_scl
    dst_zp = sum_out_zp - sum_lhs_zp * sum_lhs_scl / sum_out_scl -
             sum_rhs_zp * sum_rhs_scl / sum_out_scl
class_docstr_tok: ["Legalize","QNN","based","patterns","to","match","DNNL","original","pattern",":","OP","=","qnn.dense","|","qnn.conv2d","%","1","=","OP","<","int",">","(","SRC",",","WGH",")","-","OP","<","int",">","(","src_zp",",","WGH",")","\/\/","qnn.conv2d","%","2","=","%","1","+","orig_bias","\/\/","bias","%","2","=","(","%","1","-","rq_in_zp",")","*","rq_in_scl","\/","rq_out_scl","+","rq_out_zp","\/\/","qnn.requantize","%","3","=","act","(","%","2",")","\/\/","activation","==","clip","%","4","=","(","(","%","3","-","sum_lh_zp",")","*","sum_lh_scl","+","(","SRC2","-","sum_rh_zp",")","*","sum_rh_scl",")","\/\/","qnn.add","\/","sum_out_scl","+","sum_out_zp","transform","to","DNNL","compatible",":","%","1","=","OP","<","int",">","(","SRC",",","WGH",")","%","2","=","cast","(","%","1",",","dtype=","''","float","''",")","%","2","=","(","%","1","+","bias",")","*","o_scl","%","3","=","act","(","%","2",")","*","act_scl","%","4","=","%","3","+","SRC2","*","sum_scl","%","5","=","%","4","+","dst_zp","%","6","=","cast","(","%","5",",","dtype=","''","float","''",")","where",":","o_scl","=","rq_in_scl","\/","rq_out_scl","act_scl","=","sum_lhs_scl","\/","sum_out_scl","sum_scl","=","sum_rhs_scl","\/","sum_out_scl","bias","=","orig_bias","-","OP","(","src_zp",",","WGH",")","-","rq_in_zp","+","rq_out_zp","*","rq_out_scl","\/","rq_in_scl","dst_zp","=","sum_out_zp","-","sum_lhs_zp","*","sum_lhs_scl","\/","sum_out_scl","-","sum_rhs_zp","*","sum_rhs_scl","\/","sum_out_scl"]
code: def __init__(self):
      super(LegalizeQnnOpForDnnl, self).__init__()
      self.src = wildcard()
      self.wgh = wildcard()
      self.bias = wildcard()
      self.sum_src = wildcard()
  
      self.src_scl = is_constant()
      self.src_zp = is_constant()
      self.wgh_scl = is_constant()
      self.wgh_zp = is_expr(const(0))
  
      self.rq_in_scl = is_constant()
      self.rq_in_zp = is_constant()
      self.rq_out_scl = is_constant()
      self.rq_out_zp = is_constant()
  
      self.sum_lhs_scl = is_constant()
      self.sum_lhs_zp = is_constant()
      self.sum_rhs_scl = is_constant()
      self.sum_rhs_zp = is_constant()
      self.sum_out_scl = is_constant()
      self.sum_out_zp = is_constant()
  
      self.root = (is_op("qnn.conv2d") | is_op("qnn.dense"))(
          self.src,
          self.wgh,
          self.src_zp,
          self.wgh_zp,
          self.src_scl,
          self.wgh_scl,
      )
      pat = (
          is_op("add")(self.root, self.bias) | self.root
      )  # optional bias
      pat = is_op("qnn.requantize")(
          pat,
          self.rq_in_scl,
          self.rq_in_zp,
          self.rq_out_scl,
          self.rq_out_zp,
      )
      pat = is_op("clip")(pat)
      cast = is_op("cast")(pat)
      pat = is_op("qnn.add")(
          cast,
          self.sum_src,
          self.sum_lhs_scl,
          self.sum_lhs_zp,
          self.sum_rhs_scl,
          self.sum_rhs_zp,
          self.sum_out_scl,
          self.sum_out_zp,
      )
      pat = is_op("clip")(pat)
      self.pattern = pat | cast
  
imports: import logging
  from functools import reduce
  import tvm.ir
  from tvm import relay
  from tvm.ir import Op
  from tvm.relay import expr
  from tvm.relay import transform
  from tvm.relay.analysis import analysis
  from tvm.relay.expr import Call, GlobalVar, TupleGetItem, const
  from tvm.relay.expr_functor import ExprMutator, ExprVisitor
  from ...None import _ffi_api
  from ...dataflow_pattern import DFPatternCallback, is_constant, is_expr, is_op, rewrite, wildcard
  from .register import register_pattern_table
label_desc: Use image node_id 1 to create a new LegalizeQnnOpForDnnl object from inherited base classes: DFPatternCallback with example: obj = LegalizeQnnOpForDnnl()