Currently, two element vectors produced as the result of a binary op are
widened to four element vectors on x86 by
DAGTypeLegalizer::WidenVecRes_BinaryCanTrap. If the op still isn't legal
after widening it is unrolled into scalar 4 scalar ops in selectionDAG before
being converted into a libcall. This way we end up with 4 libcalls (two of them
on known undef elements) instead of the original two libcalls.
This patch modifies DAGTypeLegalizer::WidenVectorResult to ensure
that if it is known that an binary op will be turned into a libcall, it is
unrolled instead of being widened. This prevents the creation of the extra
scalar instructions on known undef elements and (eventually) libcalls with
known undef parameters which would otherwise be created when the op gets
expanded post widening.
llvm/test/CodeGen/X86/frem-libcall.ll:
Regression test for the change.
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp:
The change in SelectionDAG as mentioned above.
Instead of copying this block, create a lambda above the switch and call it from here and the existing code?
auto unrollExpandedOp = [&]() { // We're going to widen this vector op to a legal type by padding with undef // elements. If the wide vector op is eventually going to be expanded to // scalar libcalls, then unroll into scalar ops now to avoid unnecessary // libcalls on the undef elements. EVT VT = N->getValueType(0); EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); if (!TLI.isOperationLegalOrCustom(N->getOpcode(), WideVecVT) && TLI.isOperationExpand(N->getOpcode(), VT.getScalarType())) { Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements()); return true; } return false; };