[llvm-commits] [llvm] r73477 - in /llvm/trunk: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp test/CodeGen/CellSPU/mul-with-overflow.ll test/CodeGen/PowerPC/mul-with-overflow.ll test/CodeGen/X86/umul-with-overflow.ll
Eli Friedman
eli.friedman at gmail.com
Mon Jun 15 23:58:29 PDT 2009
Author: efriedma
Date: Tue Jun 16 01:58:29 2009
New Revision: 73477
URL: http://llvm.org/viewvc/llvm-project?rev=73477&view=rev
Log:
Add some generic expansion logic for SMULO and UMULO. Fixes UMULO
support for x86, and UMULO/SMULO for many architectures, including PPC
(PR4201), ARM, and Cell. The resulting expansion isn't perfect, but it's
not bad.
Added:
llvm/trunk/test/CodeGen/CellSPU/mul-with-overflow.ll
llvm/trunk/test/CodeGen/PowerPC/mul-with-overflow.ll
llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=73477&r1=73476&r2=73477&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Tue Jun 16 01:58:29 2009
@@ -2768,6 +2768,53 @@
ISD::SETULT : ISD::SETUGT));
break;
}
+ case ISD::UMULO:
+ case ISD::SMULO: {
+ MVT VT = Node->getValueType(0);
+ SDValue LHS = Node->getOperand(0);
+ SDValue RHS = Node->getOperand(1);
+ SDValue BottomHalf;
+ SDValue TopHalf;
+ static unsigned Ops[2][3] =
+ { { ISD::MULHU, ISD::UMUL_LOHI, ISD::ZERO_EXTEND },
+ { ISD::MULHS, ISD::SMUL_LOHI, ISD::SIGN_EXTEND }};
+ bool isSigned = Node->getOpcode() == ISD::SMULO;
+ if (TLI.isOperationLegalOrCustom(Ops[isSigned][0], VT)) {
+ BottomHalf = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS);
+ TopHalf = DAG.getNode(Ops[isSigned][0], dl, VT, LHS, RHS);
+ } else if (TLI.isOperationLegalOrCustom(Ops[isSigned][1], VT)) {
+ BottomHalf = DAG.getNode(Ops[isSigned][1], dl, DAG.getVTList(VT, VT), LHS,
+ RHS);
+ TopHalf = BottomHalf.getValue(1);
+ } else if (TLI.isTypeLegal(MVT::getIntegerVT(VT.getSizeInBits() * 2))) {
+ MVT WideVT = MVT::getIntegerVT(VT.getSizeInBits() * 2);
+ LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
+ RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
+ Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS);
+ BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1,
+ DAG.getIntPtrConstant(0));
+ TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1,
+ DAG.getIntPtrConstant(1));
+ } else {
+ // FIXME: We should be able to fall back to a libcall with an illegal
+ // type in some cases cases.
+ // Also, we can fall back to a division in some cases, but that's a big
+ // performance hit in the general case.
+ assert(0 && "Don't know how to expand this operation yet!");
+ }
+ if (isSigned) {
+ Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy());
+ Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1);
+ TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1,
+ ISD::SETNE);
+ } else {
+ TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf,
+ DAG.getConstant(0, VT), ISD::SETNE);
+ }
+ Results.push_back(BottomHalf);
+ Results.push_back(TopHalf);
+ break;
+ }
case ISD::BUILD_PAIR: {
MVT PairTy = Node->getValueType(0);
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0));
Added: llvm/trunk/test/CodeGen/CellSPU/mul-with-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/mul-with-overflow.ll?rev=73477&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/CellSPU/mul-with-overflow.ll (added)
+++ llvm/trunk/test/CodeGen/CellSPU/mul-with-overflow.ll Tue Jun 16 01:58:29 2009
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=cellspu
+
+declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
+define i1 @a(i16 %x) zeroext nounwind {
+ %res = call {i16, i1} @llvm.smul.with.overflow.i16(i16 %x, i16 3)
+ %obil = extractvalue {i16, i1} %res, 1
+ ret i1 %obil
+}
+
+declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
+define i1 @b(i16 %x) zeroext nounwind {
+ %res = call {i16, i1} @llvm.umul.with.overflow.i16(i16 %x, i16 3)
+ %obil = extractvalue {i16, i1} %res, 1
+ ret i1 %obil
+}
Added: llvm/trunk/test/CodeGen/PowerPC/mul-with-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/mul-with-overflow.ll?rev=73477&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/mul-with-overflow.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/mul-with-overflow.ll Tue Jun 16 01:58:29 2009
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=ppc32
+
+declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
+define i1 @a(i32 %x) zeroext nounwind {
+ %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 3)
+ %obil = extractvalue {i32, i1} %res, 1
+ ret i1 %obil
+}
+
+declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
+define i1 @b(i32 %x) zeroext nounwind {
+ %res = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %x, i32 3)
+ %obil = extractvalue {i32, i1} %res, 1
+ ret i1 %obil
+}
Added: llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll?rev=73477&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll (added)
+++ llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll Tue Jun 16 01:58:29 2009
@@ -0,0 +1,8 @@
+; RUN: llvm-as < %s | llc -march=x86 | grep "\\\\\\\<mul"
+
+declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
+define i1 @a(i32 %x) zeroext nounwind {
+ %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 3)
+ %obil = extractvalue {i32, i1} %res, 1
+ ret i1 %obil
+}
More information about the llvm-commits
mailing list