summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwhitequark <whitequark@whitequark.org>2019-02-12 16:41:50 +0000
committerwhitequark <whitequark@whitequark.org>2019-02-12 16:41:50 +0000
commit77ccc2eba4b2fd178f1d3ca86edffe737014bdf5 (patch)
tree3aa880c61dd25b6ad4be82967db9d0a43ddd17b4
parentf9fe483eb5f2b61761647a102a4b1dbc501856d0 (diff)
downloadbcm5719-llvm-77ccc2eba4b2fd178f1d3ca86edffe737014bdf5.tar.gz
bcm5719-llvm-77ccc2eba4b2fd178f1d3ca86edffe737014bdf5.zip
[SelectionDAG] Fix return calling convention in expansion of ?MULO
Summary: 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, the legalizer cannot directly call the intrinsic with the wide arguments; instead, it "pre-lowers" them by splitting them in halves. rL283203 made sure that on big endian targets, the legalizer passes the argument halves in the correct order. It did not do the same for the return value halves because the existing code used a hack; it put an illegal type into DAG and hoped that nothing would break and it would be correctly lowered elsewhere. rL307207 fixed this, handling return value halves similar to how argument handles are handled, but did not take big-endian targets into account. This commit fixes the expansion on big-endian targets, such as the out-of-tree OR1K target. Reviewers: eli.friedman, vadimcn Subscribers: george-hopkins, efriedma, llvm-commits Differential Revision: https://reviews.llvm.org/D45355 llvm-svn: 353854
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp12
-rw-r--r--llvm/test/CodeGen/Thumb/umulo-32-legalisation-lowering.ll43
2 files changed, 52 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index cba80e1955a..b6b96deed32 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3423,7 +3423,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// being a legal type for the architecture and thus has to be split to
// two arguments.
SDValue Ret;
- if(DAG.getDataLayout().isLittleEndian()) {
+ 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
@@ -3436,8 +3436,14 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
}
assert(Ret.getOpcode() == ISD::MERGE_VALUES &&
"Ret value is a collection of constituent nodes holding result.");
- BottomHalf = Ret.getOperand(0);
- TopHalf = Ret.getOperand(1);
+ if (DAG.getDataLayout().isLittleEndian()) {
+ // Same as above.
+ BottomHalf = Ret.getOperand(0);
+ TopHalf = Ret.getOperand(1);
+ } else {
+ BottomHalf = Ret.getOperand(1);
+ TopHalf = Ret.getOperand(0);
+ }
}
if (isSigned) {
diff --git a/llvm/test/CodeGen/Thumb/umulo-32-legalisation-lowering.ll b/llvm/test/CodeGen/Thumb/umulo-32-legalisation-lowering.ll
new file mode 100644
index 00000000000..fb0d441e0c3
--- /dev/null
+++ b/llvm/test/CodeGen/Thumb/umulo-32-legalisation-lowering.ll
@@ -0,0 +1,43 @@
+; RUN: llc < %s -mtriple=thumb-eabi | FileCheck %s --check-prefixes CHECK,CHECK-LITTLE
+; RUN: llc < %s -mtriple=thumbeb-eabi | FileCheck %s --check-prefixes CHECK,CHECK-BIG
+
+define i1 @umulo32(i32 %l, i32 %r) unnamed_addr #0 {
+; CHECK-LABEL: umulo32:
+; CHECK: @ %bb.0: @ %start
+; CHECK-NEXT: .save {r7, lr}
+; CHECK-NEXT: push {r7, lr}
+; CHECK-LITTLE-NEXT: movs r2, r1
+; CHECK-LITTLE-NEXT: movs r1, #0
+; CHECK-NEXT: movs r3, r1
+; CHECK-BIG-NEXT: movs r1, r0
+; CHECK-BIG-NEXT: movs r0, #0
+; CHECK-BIG-NEXT: movs r2, r0
+; CHECK-NEXT: bl __aeabi_lmul
+; CHECK-LITTLE-NEXT: cmp r1, #0
+; CHECK-LITTLE-NEXT: bne .LBB0_2
+; CHECK-LITTLE-NEXT: @ %bb.1:
+; CHECK-LITTLE-NEXT: movs r0, r1
+; CHECK-LITTLE-NEXT: b .LBB0_3
+; CHECK-LITTLE-NEXT: .LBB0_2:
+; CHECK-LITTLE-NEXT: movs r0, #1
+; CHECK-LITTLE-NEXT: .LBB0_3:
+; CHECK-BIG-NEXT: cmp r0, #0
+; CHECK-BIG-NEXT: beq .LBB0_2
+; CHECK-BIG-NEXT: @ %bb.1:
+; CHECK-BIG-NEXT: movs r0, #1
+; CHECK-BIG-NEXT: .LBB0_2:
+; CHECK-NEXT: pop {r7}
+; CHECK-NEXT: pop {r1}
+; CHECK-NEXT: bx r1
+start:
+ %0 = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %l, i32 %r) #2
+ %1 = extractvalue { i32, i1 } %0, 1
+ ret i1 %1
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) #1
+
+attributes #0 = { nounwind readnone uwtable }
+attributes #1 = { nounwind readnone speculatable }
+attributes #2 = { nounwind }
OpenPOWER on IntegriCloud