Jon Chesterfield via llvm-dev
2017-Sep-27 16:18 UTC
[llvm-dev] Custom lower multiple return values
Hey, I’ve been working on custom lowering ISD::UMUL_LOHI and ISD::SMUL_LOHI. Our target has some legal vector types but no support for these so would like to mark them as Expand. This yields “Cannot unroll a vector with multiple results!” from the default case in VectorLegalizer::Expand. Hence custom lowering. All the types are legal at this stage. I would appreciate some clarification on how custom lowering of nodes with multiple return values behaves. My theory is: - The lowering function is called once per ResNo - On each invocation, generate an SDValue for each ResNo - Generate an ISD::MERGE_VALUES nodes to combine all of these SDValues - Mutate the ResNo in the SDValue wrapping the ISD::MERGE_VALUES to match the input ResNo If that’s the right way to go, great. Confirmation would be appreciated. My first few attempts involved only generating an SDValue for the requested ResNo (which asserts when asked for ResNo == 1 and returning ResNo == 0) and returning a ISD::MERGE_VALUES without mutating the ResNo (which leads to constant folding merging the two result values together, effectively dropping the second one). The code I based this on is LowerXALUO in AArch64ISelLowering which returns a MERGE_VALUES without mutating the ResNo. I’m concerned that AArch64 may be dropping the carry bit based on the semantics observed above, but don’t know AArch64 well enough to verify. SDValue MyTarget::LowerXMUL_LOHI(SDValue Op, SelectionDAG &DAG) const { EVT VT = Op.getValueType(); SDLoc dl(Op); unsigned Opc = Op.getOpcode(); unsigned ResNo = Op.getResNo(); assert(Opc == ISD::UMUL_LOHI || Opc == ISD::SMUL_LOHI); assert(ResNo == 0 || ResNo == 1); SDValue Op0 = Op.getOperand(0); SDValue Op1 = Op.getOperand(1); unsigned MULHXOpcode = Opc == ISD::UMUL_LOHI ? ISD::MULHU : ISD::MULHS; SDValue res[2] = { // Seems wasteful to generate both of these twice per node DAG.getNode(ISD::MUL, dl, VT, Op0, Op1), LowerMULHX(DAG.getNode(MULHXOpcode, dl, VT, Op0, Op1), DAG), }; SDVTList VTs = DAG.getVTList(VT, VT); SDNode * N = DAG.getNode(ISD::MERGE_VALUES, dl, VTs, res[0], res[1]).getNode(); return SDValue(N,Op.getResNo()); // AArch64 doesn’t do this } The above is weird in at least two respects. It generates an ISD::MUL when ResNo == 1, which will then be dropped elsewhere, and likewise the result of custom lowering MULHX when ResNo == 0. It also mutates the ResNo before returning, but without that codegen just drops the second half of the lowering. The reference from AArch64 is: SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32); return DAG.getNode(ISD::MERGE_VALUES, dl, VTs, Value, Overflow); Am I on the right track here? Cheers! Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170927/3af7e15c/attachment.html>