[X86] Remove the separate SMUL8/UMUL8 X86ISD opcodes by merging with SMUL/UMUL. Remove the second result from X86ISD::UMUL.

All of these use custom isel so we can pretty easily detect the differences in the custom code in X86ISelDAGToDAG. The ISD opcodes just need to express the desired semantics not the details of how they would be selected by isel. So unifying them lets us remove the special casing from lowering.

llvm-svn: 350206
This commit is contained in:
Craig Topper 2019-01-02 06:40:11 +00:00
parent d4db122483
commit f7cc7e3201
3 changed files with 25 additions and 47 deletions

View File

@ -3411,24 +3411,11 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
getI8Imm(ShlVal, dl)); getI8Imm(ShlVal, dl));
return; return;
} }
case X86ISD::UMUL8: case X86ISD::SMUL:
case X86ISD::SMUL8: { // i16/i32/i64 are handled with isel patterns.
SDValue N0 = Node->getOperand(0); if (NVT != MVT::i8)
SDValue N1 = Node->getOperand(1); break;
LLVM_FALLTHROUGH;
unsigned 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);
ReplaceNode(Node, CNode);
return;
}
case X86ISD::UMUL: { case X86ISD::UMUL: {
SDValue N0 = Node->getOperand(0); SDValue N0 = Node->getOperand(0);
SDValue N1 = Node->getOperand(1); SDValue N1 = Node->getOperand(1);
@ -3436,7 +3423,10 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
unsigned LoReg, Opc; unsigned LoReg, Opc;
switch (NVT.SimpleTy) { switch (NVT.SimpleTy) {
default: llvm_unreachable("Unsupported VT!"); default: llvm_unreachable("Unsupported VT!");
// MVT::i8 is handled by X86ISD::UMUL8. case MVT::i8:
LoReg = X86::AL;
Opc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
break;
case MVT::i16: LoReg = X86::AX; Opc = X86::MUL16r; break; case MVT::i16: LoReg = X86::AX; Opc = X86::MUL16r; break;
case MVT::i32: LoReg = X86::EAX; Opc = X86::MUL32r; break; case MVT::i32: LoReg = X86::EAX; Opc = X86::MUL32r; break;
case MVT::i64: LoReg = X86::RAX; Opc = X86::MUL64r; break; case MVT::i64: LoReg = X86::RAX; Opc = X86::MUL64r; break;
@ -3445,11 +3435,19 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
SDValue InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg, SDValue InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
N0, SDValue()).getValue(1); N0, SDValue()).getValue(1);
SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::i32); // i16/i32/i64 use an instruction that produces a low and high result even
// though only the low result is used.
SDVTList VTs;
if (NVT == MVT::i8)
VTs = CurDAG->getVTList(NVT, MVT::i32);
else
VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
SDValue Ops[] = {N1, InFlag}; SDValue Ops[] = {N1, InFlag};
SDNode *CNode = CurDAG->getMachineNode(Opc, dl, VTs, Ops); SDNode *CNode = CurDAG->getMachineNode(Opc, dl, VTs, Ops);
ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0));
ReplaceNode(Node, CNode); ReplaceUses(SDValue(Node, 1), SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
CurDAG->RemoveDeadNode(Node);
return; return;
} }

View File

@ -19633,23 +19633,14 @@ getX86XALUOOp(X86::CondCode &Cond, SDValue Op, SelectionDAG &DAG) {
Cond = X86::COND_B; Cond = X86::COND_B;
break; break;
case ISD::SMULO: case ISD::SMULO:
BaseOp = Op.getValueType() == MVT::i8 ? X86ISD::SMUL8 : X86ISD::SMUL; BaseOp = X86ISD::SMUL;
Cond = X86::COND_O; Cond = X86::COND_O;
break; break;
case ISD::UMULO: { // i64, i8 = umulo lhs, rhs --> i64, i64, i32 umul lhs,rhs case ISD::UMULO:
if (Op.getValueType() == MVT::i8) { BaseOp = X86ISD::UMUL;
BaseOp = X86ISD::UMUL8;
Cond = X86::COND_O; Cond = X86::COND_O;
break; break;
} }
SDVTList VTs = DAG.getVTList(Op.getValueType(), Op.getValueType(),
MVT::i32);
Value = DAG.getNode(X86ISD::UMUL, DL, VTs, LHS, RHS);
Overflow = Value.getValue(2);
Cond = X86::COND_O;
break;
}
}
if (BaseOp) { if (BaseOp) {
// Also sets EFLAGS. // Also sets EFLAGS.
@ -19683,14 +19674,11 @@ static bool isX86LogicalCmp(SDValue Op) {
return true; return true;
if (Op.getResNo() == 1 && if (Op.getResNo() == 1 &&
(Opc == X86ISD::ADD || Opc == X86ISD::SUB || Opc == X86ISD::ADC || (Opc == X86ISD::ADD || Opc == X86ISD::SUB || Opc == X86ISD::ADC ||
Opc == X86ISD::SBB || Opc == X86ISD::SMUL || Opc == X86ISD::SBB || Opc == X86ISD::SMUL || Opc == X86ISD::UMUL ||
Opc == X86ISD::INC || Opc == X86ISD::DEC || Opc == X86ISD::OR || Opc == X86ISD::INC || Opc == X86ISD::DEC || Opc == X86ISD::OR ||
Opc == X86ISD::XOR || Opc == X86ISD::AND)) Opc == X86ISD::XOR || Opc == X86ISD::AND))
return true; return true;
if (Op.getResNo() == 2 && Opc == X86ISD::UMUL)
return true;
return false; return false;
} }
@ -27085,8 +27073,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::SBB: return "X86ISD::SBB"; case X86ISD::SBB: return "X86ISD::SBB";
case X86ISD::SMUL: return "X86ISD::SMUL"; case X86ISD::SMUL: return "X86ISD::SMUL";
case X86ISD::UMUL: return "X86ISD::UMUL"; case X86ISD::UMUL: return "X86ISD::UMUL";
case X86ISD::SMUL8: return "X86ISD::SMUL8";
case X86ISD::UMUL8: return "X86ISD::UMUL8";
case X86ISD::INC: return "X86ISD::INC"; case X86ISD::INC: return "X86ISD::INC";
case X86ISD::DEC: return "X86ISD::DEC"; case X86ISD::DEC: return "X86ISD::DEC";
case X86ISD::OR: return "X86ISD::OR"; case X86ISD::OR: return "X86ISD::OR";

View File

@ -336,7 +336,7 @@ namespace llvm {
CMPM_RND, CMPM_RND,
// Arithmetic operations with FLAGS results. // Arithmetic operations with FLAGS results.
ADD, SUB, ADC, SBB, SMUL, ADD, SUB, ADC, SBB, SMUL, UMUL,
INC, DEC, OR, XOR, AND, INC, DEC, OR, XOR, AND,
// Bit field extract. // Bit field extract.
@ -345,12 +345,6 @@ namespace llvm {
// Zero High Bits Starting with Specified Bit Position. // Zero High Bits Starting with Specified Bit Position.
BZHI, BZHI,
// LOW, HI, FLAGS = umul LHS, RHS.
UMUL,
// 8-bit SMUL/UMUL - AX, FLAGS = smul8/umul8 AL, RHS.
SMUL8, UMUL8,
// X86-specific multiply by immediate. // X86-specific multiply by immediate.
MUL_IMM, MUL_IMM,