Fix signed multiplication with overflow fallback.

For targets that don't have ISD::MULHS or ISD::SMUL_LOHI for the type
and the double width type is illegal, then the two operands are
sign extended to twice their size then multiplied to check for overflow.
The extended upper halves were mismatched causing an incorrect result.
This fixes the mismatch.

A test was added for ARM V6-M where the bug was detected.

Patch by James Duley.

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



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301404 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ranjeet Singh 2017-04-26 13:41:43 +00:00
parent 0f75548f9f
commit d530427b4a
2 changed files with 18 additions and 2 deletions

View File

@ -3497,11 +3497,11 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// part.
unsigned LoSize = VT.getSizeInBits();
SDValue HiLHS =
DAG.getNode(ISD::SRA, dl, VT, RHS,
DAG.getNode(ISD::SRA, dl, VT, LHS,
DAG.getConstant(LoSize - 1, dl,
TLI.getPointerTy(DAG.getDataLayout())));
SDValue HiRHS =
DAG.getNode(ISD::SRA, dl, VT, LHS,
DAG.getNode(ISD::SRA, dl, VT, RHS,
DAG.getConstant(LoSize - 1, dl,
TLI.getPointerTy(DAG.getDataLayout())));

View File

@ -0,0 +1,16 @@
; RUN: llc < %s -mtriple=thumbv6m-none-eabi | FileCheck %s
define i1 @signed_multiplication_did_overflow(i32, i32) {
; CHECK-LABEL: signed_multiplication_did_overflow:
entry-block:
%2 = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %0, i32 %1)
%3 = extractvalue { i32, i1 } %2, 1
ret i1 %3
; CHECK: mov r2, r1
; CHECK: asrs r1, r0, #31
; CHECK: asrs r3, r2, #31
; CHECK: bl __aeabi_lmul
}
declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32)