From: whitequark Date: Tue, 4 Oct 2016 09:07:49 +0000 (+0000) Subject: [SelectionDAG] Fix calling convention in expansion of ?MULO. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e1a1a529457159f0cef5644d38421f82b5537805;p=llvm [SelectionDAG] Fix calling convention in expansion of ?MULO. The SMULO/UMULO DAG nodes, when not directly supported by the target, expand to a multiplication twice as wide. In case that the resulting type is not legal, an __mul?i3 intrinsic is used. Since the type is not legal, the legalizer cannot directly call the intrinsic with the wide arguments; instead, it "pre-lowers" them by splitting them in halves. The "pre-lowering" code in essence made assumptions about the calling convention, specifically that i(N*2) values will be split into two iN values and passed in consecutive registers in little-endian order. This, naturally, breaks on a big-endian system, such as our OR1K out-of-tree backend. Thanks to James Miller for help in debugging. Differential Revision: https://reviews.llvm.org/D25223 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283203 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index bdcf4d07c02..f80eb3ad703 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3470,8 +3470,18 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { // pre-lowered to the correct types. This all depends upon WideVT not // being a legal type for the architecture and thus has to be split to // two arguments. - SDValue Args[] = { LHS, HiLHS, RHS, HiRHS }; - SDValue Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl); + SDValue Ret; + if(DAG.getDataLayout().isLittleEndian()) { + // Halves of WideVT are packed into registers in different order + // depending on platform endianness. This is usually handled by + // the C calling convention, but we can't defer to it in + // the legalizer. + SDValue Args[] = { LHS, HiLHS, RHS, HiRHS }; + Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl); + } else { + SDValue Args[] = { HiLHS, LHS, HiRHS, RHS }; + Ret = ExpandLibCall(LC, WideVT, Args, 4, isSigned, dl); + } BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret, DAG.getIntPtrConstant(0, dl)); TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Ret,