summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwhitequark <whitequark@whitequark.org>2016-10-04 09:07:49 +0000
committerwhitequark <whitequark@whitequark.org>2016-10-04 09:07:49 +0000
commit7c4fe0e9a323c849f3ab14354cbf1bb00fce1ee7 (patch)
treec28b13377c1e55e24dd42f14d8d2f3768e96360d
parentd2a6d7b2037b82c38adec187a76f3dac4626a9f6 (diff)
downloadbcm5719-llvm-7c4fe0e9a323c849f3ab14354cbf1bb00fce1ee7.tar.gz
bcm5719-llvm-7c4fe0e9a323c849f3ab14354cbf1bb00fce1ee7.zip
[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 <james@aatch.net> for help in debugging. Differential Revision: https://reviews.llvm.org/D25223 llvm-svn: 283203
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp14
1 files changed, 12 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index bdcf4d07c02..f80eb3ad703 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/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,
OpenPOWER on IntegriCloud