Index: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2218,6 +2218,25 @@ return CurDAG->SelectNodeTo(Node, ShlOp, NVT, SDValue(New, 0), getI8Imm(ShlVal)); } + case X86ISD::UMUL8: + case X86ISD::SMUL8: { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + + Opc = (Opcode == X86ISD::SMUL8 ? X86::IMUL8r : X86::MUL8r); + + SDValue InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::AL, + N0, SDValue()).getValue(1); + + SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32); + SDValue Ops[] = {N1, InFlag}; + SDNode *CNode = CurDAG->getMachineNode(Opc, dl, VTs, Ops); + + ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0)); + ReplaceUses(SDValue(Node, 1), SDValue(CNode, 1)); + return nullptr; + } + case X86ISD::UMUL: { SDValue N0 = Node->getOperand(0); SDValue N1 = Node->getOperand(1); Index: llvm/trunk/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h @@ -301,6 +301,9 @@ UMUL, // LOW, HI, FLAGS = umul LHS, RHS + // 8-bit SMUL/UMUL - AX, FLAGS = smul8/umul8 AL, RHS + SMUL8, UMUL8, + // MUL_IMM - X86 specific multiply by immediate. MUL_IMM, Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -1597,9 +1597,6 @@ setOperationAction(ISD::UMULO, VT, Custom); } - // There are no 8-bit 3-address imul/mul instructions - setOperationAction(ISD::SMULO, MVT::i8, Expand); - setOperationAction(ISD::UMULO, MVT::i8, Expand); if (!Subtarget->is64Bit()) { // These libcalls are not available in 32-bit. @@ -18190,10 +18187,15 @@ Cond = X86::COND_B; break; case ISD::SMULO: - BaseOp = X86ISD::SMUL; + BaseOp = N->getValueType(0) == MVT::i8 ? X86ISD::SMUL8 : X86ISD::SMUL; Cond = X86::COND_O; break; case ISD::UMULO: { // i64, i8 = umulo lhs, rhs --> i64, i64, i32 umul lhs,rhs + if (N->getValueType(0) == MVT::i8) { + BaseOp = X86ISD::UMUL8; + Cond = X86::COND_O; + break; + } SDVTList VTs = DAG.getVTList(N->getValueType(0), N->getValueType(0), MVT::i32); SDValue Sum = DAG.getNode(X86ISD::UMUL, DL, VTs, LHS, RHS); Index: llvm/trunk/test/CodeGen/X86/i8-umulo.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/i8-umulo.ll +++ llvm/trunk/test/CodeGen/X86/i8-umulo.ll @@ -1,24 +0,0 @@ -; RUN: llc -mcpu=generic -march=x86 < %s | FileCheck %s -; PR19858 - -declare {i8, i1} @llvm.umul.with.overflow.i8(i8 %a, i8 %b) -define i8 @testumulo(i32 %argc) { -; CHECK: imull -; CHECK: testb %{{.+}}, %{{.+}} -; CHECK: je [[NOOVERFLOWLABEL:.+]] -; CHECK: {{.*}}[[NOOVERFLOWLABEL]]: -; CHECK-NEXT: movb -; CHECK-NEXT: retl -top: - %RHS = trunc i32 %argc to i8 - %umul = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 25, i8 %RHS) - %ex = extractvalue { i8, i1 } %umul, 1 - br i1 %ex, label %overflow, label %nooverlow - -overflow: - ret i8 %RHS - -nooverlow: - %umul.value = extractvalue { i8, i1 } %umul, 0 - ret i8 %umul.value -} Index: llvm/trunk/test/CodeGen/X86/xaluo.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/xaluo.ll +++ llvm/trunk/test/CodeGen/X86/xaluo.ll @@ -123,12 +123,9 @@ ; Check boundary conditions for large immediates. define zeroext i1 @saddo.i64imm2(i64 %v1, i64* %res) { entry: -; SDAG-LABEL: saddo.i64imm2 -; SDAG: addq $-2147483648, %rdi -; SDAG-NEXT: seto %al -; FAST-LABEL: saddo.i64imm2 -; FAST: addq $-2147483648, %rdi -; FAST-NEXT: seto %al +; CHECK-LABEL: saddo.i64imm2 +; CHECK: addq $-2147483648, %rdi +; CHECK-NEXT: seto %al %t = call {i64, i1} @llvm.sadd.with.overflow.i64(i64 %v1, i64 -2147483648) %val = extractvalue {i64, i1} %t, 0 %obit = extractvalue {i64, i1} %t, 1 @@ -297,10 +294,10 @@ ; SMULO define zeroext i1 @smulo.i8(i8 %v1, i8 %v2, i8* %res) { entry: -; FAST-LABEL: smulo.i8 -; FAST: movb %dil, %al -; FAST-NEXT: imulb %sil -; FAST-NEXT: seto %cl +; CHECK-LABEL: smulo.i8 +; CHECK: movb %dil, %al +; CHECK-NEXT: imulb %sil +; CHECK-NEXT: seto %cl %t = call {i8, i1} @llvm.smul.with.overflow.i8(i8 %v1, i8 %v2) %val = extractvalue {i8, i1} %t, 0 %obit = extractvalue {i8, i1} %t, 1 @@ -347,10 +344,10 @@ ; UMULO define zeroext i1 @umulo.i8(i8 %v1, i8 %v2, i8* %res) { entry: -; FAST-LABEL: umulo.i8 -; FAST: movb %dil, %al -; FAST-NEXT: mulb %sil -; FAST-NEXT: seto %cl +; CHECK-LABEL: umulo.i8 +; CHECK: movb %dil, %al +; CHECK-NEXT: mulb %sil +; CHECK-NEXT: seto %cl %t = call {i8, i1} @llvm.umul.with.overflow.i8(i8 %v1, i8 %v2) %val = extractvalue {i8, i1} %t, 0 %obit = extractvalue {i8, i1} %t, 1