]> granicus.if.org Git - llvm/commitdiff
[CodeGen] Fix result type for SMULO/UMULO legalization
authorEli Friedman <efriedma@codeaurora.org>
Tue, 6 Dec 2016 22:49:36 +0000 (22:49 +0000)
committerEli Friedman <efriedma@codeaurora.org>
Tue, 6 Dec 2016 22:49:36 +0000 (22:49 +0000)
On some platforms (like MSP430) the second element of the result
structure for SMULO/UMULO may have a shorter type than the one
returned by SetCC. We need to truncate it to the right type, or
else some incorrect code may be generated later on.

This fixes issue https://github.com/rust-lang/rust/issues/37829

Patch by Vadzim Dambrouski!

Differential Revision: https://reviews.llvm.org/D27154

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288857 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
test/CodeGen/MSP430/umulo-16.ll [new file with mode: 0644]

index d970ff49bba20123b4a693e0b2b95c0963b803b3..7a04e0d033a14bcc27782e4da63be1fc5921e82a 100644 (file)
@@ -3515,6 +3515,15 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
       TopHalf = DAG.getSetCC(dl, getSetCCResultType(VT), TopHalf,
                              DAG.getConstant(0, dl, VT), ISD::SETNE);
     }
+
+    // Truncate the result if SetCC returns a larger type than needed.
+    EVT RType = Node->getValueType(1);
+    if (RType.getSizeInBits() < TopHalf.getValueSizeInBits())
+      TopHalf = DAG.getNode(ISD::TRUNCATE, dl, RType, TopHalf);
+
+    assert(RType.getSizeInBits() == TopHalf.getValueSizeInBits() &&
+           "Unexpected result type for S/UMULO legalization");
+
     Results.push_back(BottomHalf);
     Results.push_back(TopHalf);
     break;
diff --git a/test/CodeGen/MSP430/umulo-16.ll b/test/CodeGen/MSP430/umulo-16.ll
new file mode 100644 (file)
index 0000000..bd42137
--- /dev/null
@@ -0,0 +1,32 @@
+; RUN: llc < %s -march=msp430 | FileCheck %s
+target datalayout = "e-m:e-p:16:16-i32:16:32-a:16-n8:16"
+target triple = "msp430"
+
+define void @foo(i16 %arg) unnamed_addr {
+entry-block:
+  br i1 undef, label %bb2, label %bb3
+
+bb2:                                              ; preds = %entry-block
+  unreachable
+
+bb3:                                              ; preds = %entry-block
+  %0 = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 undef, i16 %arg)
+; CHECK: call
+  %1 = extractvalue { i16, i1 } %0, 1
+  %2 = call i1 @llvm.expect.i1(i1 %1, i1 false)
+  br i1 %2, label %panic, label %bb5
+
+bb5:                                              ; preds = %bb3
+  unreachable
+
+panic:                                            ; preds = %bb3
+  unreachable
+}
+
+; Function Attrs: nounwind readnone
+declare i1 @llvm.expect.i1(i1, i1) #0
+
+; Function Attrs: nounwind readnone
+declare { i16, i1 } @llvm.umul.with.overflow.i16(i16, i16) #0
+
+attributes #0 = { nounwind readnone }