[CodeGen] Fix result type for SMULO/UMULO legalization

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

llvm-svn: 288857
This commit is contained in:
Eli Friedman 2016-12-06 22:49:36 +00:00
parent e91ea67fb7
commit 3cc7de085d
2 changed files with 41 additions and 0 deletions

View 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;

View File

@ -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 }