def bmm_gen_function(func_attrs, exec_cond_template, dim_info_dict):
    """Generates function body.

    Parameters
    ----------
    func_attrs : Dict
        Operation attributes.
    exec_cond_template : jinja2.Template
        Generates if statement to execute kernel.
    dim_info_dict: Dict[str, DimInfo]
        Generated from bmm._extract_dims().
        Used to store mapping between dim_names to input / output tensor dims.

    Returns
    -------
    str
        The rendered template of generated function body.
    """
    in_batch_stride_dim = "M * K"
    in_stride_k_dim = "K"
    in_offset = 0
    weight_batch_stride_dim = "N * K"
    weight_stride_k_dim = "K"
    weight_offset = 0
    bias_batch_stride_dim = "N * O"
    bias_stride_k_dim = "O"
    bias_offset = 0

    if "input_accessors" in func_attrs:
        in_accessor = func_attrs["input_accessors"][0]
        weight_accessor = func_attrs["input_accessors"][1]
        bias_accessor = func_attrs["input_accessors"][2]

        if in_accessor.is_from_strided_tensor:
            in_offset = in_accessor.offset
            if not in_accessor.is_contiguous:
                a_dims = bmm_common.reverse_dim_info_mapping(
                    dim_info_dict, gemm_common.Source.INPUT, 0
                )

                in_batch_stride_dim = in_accessor.gen_stride_str(0, a_dims)
                in_stride_k_dim = in_accessor.stride(1)

        if weight_accessor.is_from_strided_tensor:
            weight_offset = weight_accessor.offset
            if not weight_accessor.is_contiguous:
                w_dims = bmm_common.reverse_dim_info_mapping(
                    dim_info_dict, gemm_common.Source.INPUT, 1
                )

                weight_batch_stride_dim = weight_accessor.gen_stride_str(0, w_dims)
                weight_stride_k_dim = weight_accessor.stride(1)

        if bias_accessor.is_from_strided_tensor:
            bias_offset = bias_accessor.offset
            if not bias_accessor.is_contiguous:
                b_dims = bmm_common.reverse_dim_info_mapping(
                    dim_info_dict, gemm_common.Source.INPUT, 2
                )

                bias_batch_stride_dim = bias_accessor.gen_stride_str(0, b_dims)
                bias_stride_k_dim = bias_accessor.stride(1)

    input_addr_calculator = INPUT_ADDR_CALCULATOR.render(
        in_batch_stride_dim=in_batch_stride_dim,
        in_stride_dim=in_stride_k_dim,
        in_offset_val=in_offset,
        weight_batch_stride_dim=weight_batch_stride_dim,
        weight_stride_dim=weight_stride_k_dim,
        weight_offset_val=weight_offset,
        bias_batch_stride_dim=bias_batch_stride_dim,
        bias_stride_dim=bias_stride_k_dim,
        bias_offset_val=bias_offset,
    )
    # TODO: add support for output_tensor_accessors

    return bmm_common.gen_function(
        func_attrs,
        exec_cond_template,
        dim_info_dict,
        "bias_b1",
        problem_args_template=PROBLEM_ARGS_TEMPLATE,
        extra_shape_template=EXTRA_SHAPE_TEMPLATE,
        extra_header_template=EXTRA_HEADER_TEMPLATE,
        extra_code=EXTRA_CODE.render(scale=func_attrs["scale"]),
        input_addr_calculator=input_addr_calculator,
        output_addr_calculator="",
    )
Generates function body.

Parameters
----------
func_attrs : Dict
Operation attributes.
exec_cond_template : jinja2.Template
Generates if statement to execute kernel.
dim_info_dict: Dict[str, DimInfo]
Generated from bmm._extract_dims().
Used to store mapping between dim_names to input / output tensor dims.

Returns
-------
str
The rendered template of generated function body.
python/aitemplate/backend/rocm/gemm/bmm_softmax_bmm_permute.py