diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 27 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/umulo-64.ll | 28 | 
3 files changed, 56 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 0c813834bf1..007f8d658e1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1057,6 +1057,8 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {    case ISD::SSUBO: ExpandIntRes_SADDSUBO(N, Lo, Hi); break;    case ISD::UADDO:    case ISD::USUBO: ExpandIntRes_UADDSUBO(N, Lo, Hi); break; +  case ISD::UMULO: +  case ISD::SMULO: ExpandIntRes_UMULSMULO(N, Lo, Hi); break;    }    // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -2132,6 +2134,31 @@ void DAGTypeLegalizer::ExpandIntRes_UADDSUBO(SDNode *N,    ReplaceValueWith(SDValue(N, 1), Ofl);  } +void DAGTypeLegalizer::ExpandIntRes_UMULSMULO(SDNode *N, +                                              SDValue &Lo, SDValue &Hi) { +  SDValue LHS = N->getOperand(0); +  SDValue RHS = N->getOperand(1); +  DebugLoc dl = N->getDebugLoc(); +  EVT VT = N->getValueType(0); +  EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() / 2); +  // Expand the result by simply replacing it with the equivalent +  // non-overflow-checking operation. +  SDValue Ret = DAG.getNode(ISD::MUL, dl, LHS.getValueType(), LHS, RHS); +  SplitInteger(Ret, Lo, Hi); +   +  // Now calculate overflow. +  SDValue Ofl; +  if (N->getOpcode() == ISD::UMULO) +    Ofl = DAG.getSetCC(dl, N->getValueType(1), Hi, +                       DAG.getConstant(0, VT), ISD::SETNE); +  else { +    SDValue Tmp = DAG.getConstant(VT.getSizeInBits() - 1, HalfVT); +    Tmp = DAG.getNode(ISD::SRA, dl, HalfVT, Lo, Tmp); +    Ofl = DAG.getSetCC(dl, N->getValueType(1), Hi, Tmp, ISD::SETNE); +  } +  ReplaceValueWith(SDValue(N, 1), Ofl); +} +  void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,                                           SDValue &Lo, SDValue &Hi) {    EVT VT = N->getValueType(0); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index ffc27bda521..89a1d572697 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -348,6 +348,7 @@ private:    void ExpandIntRes_SADDSUBO          (SDNode *N, SDValue &Lo, SDValue &Hi);    void ExpandIntRes_UADDSUBO          (SDNode *N, SDValue &Lo, SDValue &Hi); +	void ExpandIntRes_UMULSMULO					(SDNode *N, SDValue &Lo, SDValue &Hi);    void ExpandShiftByConstant(SDNode *N, unsigned Amt,                               SDValue &Lo, SDValue &Hi); diff --git a/llvm/test/CodeGen/X86/umulo-64.ll b/llvm/test/CodeGen/X86/umulo-64.ll new file mode 100644 index 00000000000..280bd9cb066 --- /dev/null +++ b/llvm/test/CodeGen/X86/umulo-64.ll @@ -0,0 +1,28 @@ +; RUN: llc < %s -mtriple=i386-apple-darwin + +%0 = type { i64, i1 } + +define i32 @f0(i64 %a, i64 %b) nounwind ssp { +  %1 = alloca i64, align 4 +  %2 = alloca i64, align 4 +  store i64 %a, i64* %1, align 8 +  store i64 %b, i64* %2, align 8 +  %3 = load i64* %1, align 8 +  %4 = load i64* %2, align 8 +  %5 = call %0 @llvm.smul.with.overflow.i64(i64 %3, i64 %4) +  %6 = extractvalue %0 %5, 0 +  %7 = extractvalue %0 %5, 1 +  br i1 %7, label %8, label %9 + +; <label>:8                                       ; preds = %0 +  call void @llvm.trap() +  unreachable + +; <label>:9                                       ; preds = %0 +  %10 = trunc i64 %6 to i32 +  ret i32 %10 +} + +declare %0 @llvm.smul.with.overflow.i64(i64, i64) nounwind readnone + +declare void @llvm.trap() nounwind  | 

