256,256,256,binary_add:sigmoid,native_gemm,false,false,1,0,,,tensor
256,256,256,sigmoid:binary_add,native_gemm,false,false,1,0,,,tensor
256,256,256,binary_mul:relu,native_gemm,false,false,1,0,,,tensor
256,256,256,relu:binary_mul,native_gemm,false,false,1,0,,,tensor
256,256,256,clip:tanh,native_gemm,false,false,1,0,,,tensor
256,256,256,tanh:clip,native_gemm,false,false,1,0,,,tensor
./gtests --op matmul --input_file F --ndims 2 --test 2 --seed 424242 \
--gtest_filter="*TestMatmul.F32_F32/*"
6 passed / 6 failed before, 12 passed / 0 failed after.
Summary
The native loopers scan the post-op chain for the first fusable op —
relu/gelu_tanh/gelu_erf/sigmoid/tanh/swish— hand it to themicrokernel epilogue, and apply everything else afterwards via
apply_postops_tile(). The scan accepts a match at any index, but the epilogueruns before the remaining ops, so fusing an op that is not at the head of the
chain silently reorders it.
binary_add:sigmoidcomputesbinary_add(sigmoid(x))instead ofsigmoid(binary_add(x)).A binary/residual op followed by an activation is an ordinary pattern, and the
result is wrong numerics with nothing reported.
Not ISA-specific, and not tied to
--no-aocldlpReproduced on an Intel Xeon 6767P with full AVX-512 (
avx512f,avx512_bf16,avx512_vnni), where the AVX-512 microkernels and epilogue arethe ones running — i.e. the default configuration on mainstream hardware.
Reproduce
Pin the chains through a gtest input file, with
alpha=1andbeta=0so this isisolated from alpha/beta handling:
binary_add:sigmoidbinary_mul:reluclip:tanhsigmoid:binary_addrelu:binary_multanh:clip6 passed / 6 failed before, 12 passed / 0 failed after.
Suggested fix
Fuse only when the fusable op sits at index 0; otherwise leave it to the ordered
post-op pass. The same pattern appears in all four native loopers (fp32/bf16
GEMM, fp32/bf16 BRGEMM).
Reference branch: https://github.com/lwandrebeck/BullDNN/tree/upstream/postop-chain-reorder