mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
[mips] Move the code which does dag-combine for multiply-add/sub nodes to
derived class MipsSETargetLowering. We shouldn't be generating madd/msub nodes if target is Mips16, since Mips16 doesn't have support for multipy-add/sub instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178404 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f5926fd844
commit
d593a77b4c
@ -382,8 +382,6 @@ MipsTargetLowering(MipsTargetMachine &TM)
|
||||
setTruncStoreAction(MVT::i64, MVT::i32, Custom);
|
||||
}
|
||||
|
||||
setTargetDAGCombine(ISD::ADDE);
|
||||
setTargetDAGCombine(ISD::SUBE);
|
||||
setTargetDAGCombine(ISD::SDIVREM);
|
||||
setTargetDAGCombine(ISD::UDIVREM);
|
||||
setTargetDAGCombine(ISD::SELECT);
|
||||
@ -414,186 +412,6 @@ EVT MipsTargetLowering::getSetCCResultType(EVT VT) const {
|
||||
return VT.changeVectorElementTypeToInteger();
|
||||
}
|
||||
|
||||
// selectMADD -
|
||||
// Transforms a subgraph in CurDAG if the following pattern is found:
|
||||
// (addc multLo, Lo0), (adde multHi, Hi0),
|
||||
// where,
|
||||
// multHi/Lo: product of multiplication
|
||||
// Lo0: initial value of Lo register
|
||||
// Hi0: initial value of Hi register
|
||||
// Return true if pattern matching was successful.
|
||||
static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
|
||||
// ADDENode's second operand must be a flag output of an ADDC node in order
|
||||
// for the matching to be successful.
|
||||
SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
|
||||
|
||||
if (ADDCNode->getOpcode() != ISD::ADDC)
|
||||
return false;
|
||||
|
||||
SDValue MultHi = ADDENode->getOperand(0);
|
||||
SDValue MultLo = ADDCNode->getOperand(0);
|
||||
SDNode *MultNode = MultHi.getNode();
|
||||
unsigned MultOpc = MultHi.getOpcode();
|
||||
|
||||
// MultHi and MultLo must be generated by the same node,
|
||||
if (MultLo.getNode() != MultNode)
|
||||
return false;
|
||||
|
||||
// and it must be a multiplication.
|
||||
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
|
||||
return false;
|
||||
|
||||
// MultLo amd MultHi must be the first and second output of MultNode
|
||||
// respectively.
|
||||
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
|
||||
return false;
|
||||
|
||||
// Transform this to a MADD only if ADDENode and ADDCNode are the only users
|
||||
// of the values of MultNode, in which case MultNode will be removed in later
|
||||
// phases.
|
||||
// If there exist users other than ADDENode or ADDCNode, this function returns
|
||||
// here, which will result in MultNode being mapped to a single MULT
|
||||
// instruction node rather than a pair of MULT and MADD instructions being
|
||||
// produced.
|
||||
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
|
||||
return false;
|
||||
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = ADDENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
ADDCNode->getOperand(1),
|
||||
ADDENode->getOperand(1));
|
||||
|
||||
// create MipsMAdd(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
|
||||
|
||||
SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
ACCIn);
|
||||
|
||||
// replace uses of adde and addc here
|
||||
if (!SDValue(ADDCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(ADDENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// selectMSUB -
|
||||
// Transforms a subgraph in CurDAG if the following pattern is found:
|
||||
// (addc Lo0, multLo), (sube Hi0, multHi),
|
||||
// where,
|
||||
// multHi/Lo: product of multiplication
|
||||
// Lo0: initial value of Lo register
|
||||
// Hi0: initial value of Hi register
|
||||
// Return true if pattern matching was successful.
|
||||
static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
|
||||
// SUBENode's second operand must be a flag output of an SUBC node in order
|
||||
// for the matching to be successful.
|
||||
SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
|
||||
|
||||
if (SUBCNode->getOpcode() != ISD::SUBC)
|
||||
return false;
|
||||
|
||||
SDValue MultHi = SUBENode->getOperand(1);
|
||||
SDValue MultLo = SUBCNode->getOperand(1);
|
||||
SDNode *MultNode = MultHi.getNode();
|
||||
unsigned MultOpc = MultHi.getOpcode();
|
||||
|
||||
// MultHi and MultLo must be generated by the same node,
|
||||
if (MultLo.getNode() != MultNode)
|
||||
return false;
|
||||
|
||||
// and it must be a multiplication.
|
||||
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
|
||||
return false;
|
||||
|
||||
// MultLo amd MultHi must be the first and second output of MultNode
|
||||
// respectively.
|
||||
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
|
||||
return false;
|
||||
|
||||
// Transform this to a MSUB only if SUBENode and SUBCNode are the only users
|
||||
// of the values of MultNode, in which case MultNode will be removed in later
|
||||
// phases.
|
||||
// If there exist users other than SUBENode or SUBCNode, this function returns
|
||||
// here, which will result in MultNode being mapped to a single MULT
|
||||
// instruction node rather than a pair of MULT and MSUB instructions being
|
||||
// produced.
|
||||
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
|
||||
return false;
|
||||
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = SUBENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
SUBCNode->getOperand(0),
|
||||
SUBENode->getOperand(0));
|
||||
|
||||
// create MipsSub(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
|
||||
|
||||
SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
ACCIn);
|
||||
|
||||
// replace uses of sube and subc here
|
||||
if (!SDValue(SUBCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(SUBENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const MipsSubtarget *Subtarget) {
|
||||
if (DCI.isBeforeLegalize())
|
||||
return SDValue();
|
||||
|
||||
if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
|
||||
selectMADD(N, &DAG))
|
||||
return SDValue(N, 0);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const MipsSubtarget *Subtarget) {
|
||||
if (DCI.isBeforeLegalize())
|
||||
return SDValue();
|
||||
|
||||
if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
|
||||
selectMSUB(N, &DAG))
|
||||
return SDValue(N, 0);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const MipsSubtarget *Subtarget) {
|
||||
@ -864,10 +682,6 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
|
||||
|
||||
switch (Opc) {
|
||||
default: break;
|
||||
case ISD::ADDE:
|
||||
return performADDECombine(N, DAG, DCI, Subtarget);
|
||||
case ISD::SUBE:
|
||||
return performSUBECombine(N, DAG, DCI, Subtarget);
|
||||
case ISD::SDIVREM:
|
||||
case ISD::UDIVREM:
|
||||
return performDivRemCombine(N, DAG, DCI, Subtarget);
|
||||
|
@ -77,6 +77,9 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
|
||||
setOperationAction(ISD::LOAD, MVT::i32, Custom);
|
||||
setOperationAction(ISD::STORE, MVT::i32, Custom);
|
||||
|
||||
setTargetDAGCombine(ISD::ADDE);
|
||||
setTargetDAGCombine(ISD::SUBE);
|
||||
|
||||
computeRegisterProperties();
|
||||
}
|
||||
|
||||
@ -116,6 +119,200 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
|
||||
return MipsTargetLowering::LowerOperation(Op, DAG);
|
||||
}
|
||||
|
||||
// selectMADD -
|
||||
// Transforms a subgraph in CurDAG if the following pattern is found:
|
||||
// (addc multLo, Lo0), (adde multHi, Hi0),
|
||||
// where,
|
||||
// multHi/Lo: product of multiplication
|
||||
// Lo0: initial value of Lo register
|
||||
// Hi0: initial value of Hi register
|
||||
// Return true if pattern matching was successful.
|
||||
static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
|
||||
// ADDENode's second operand must be a flag output of an ADDC node in order
|
||||
// for the matching to be successful.
|
||||
SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
|
||||
|
||||
if (ADDCNode->getOpcode() != ISD::ADDC)
|
||||
return false;
|
||||
|
||||
SDValue MultHi = ADDENode->getOperand(0);
|
||||
SDValue MultLo = ADDCNode->getOperand(0);
|
||||
SDNode *MultNode = MultHi.getNode();
|
||||
unsigned MultOpc = MultHi.getOpcode();
|
||||
|
||||
// MultHi and MultLo must be generated by the same node,
|
||||
if (MultLo.getNode() != MultNode)
|
||||
return false;
|
||||
|
||||
// and it must be a multiplication.
|
||||
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
|
||||
return false;
|
||||
|
||||
// MultLo amd MultHi must be the first and second output of MultNode
|
||||
// respectively.
|
||||
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
|
||||
return false;
|
||||
|
||||
// Transform this to a MADD only if ADDENode and ADDCNode are the only users
|
||||
// of the values of MultNode, in which case MultNode will be removed in later
|
||||
// phases.
|
||||
// If there exist users other than ADDENode or ADDCNode, this function returns
|
||||
// here, which will result in MultNode being mapped to a single MULT
|
||||
// instruction node rather than a pair of MULT and MADD instructions being
|
||||
// produced.
|
||||
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
|
||||
return false;
|
||||
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = ADDENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
ADDCNode->getOperand(1),
|
||||
ADDENode->getOperand(1));
|
||||
|
||||
// create MipsMAdd(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
|
||||
|
||||
SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
ACCIn);
|
||||
|
||||
// replace uses of adde and addc here
|
||||
if (!SDValue(ADDCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(ADDENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// selectMSUB -
|
||||
// Transforms a subgraph in CurDAG if the following pattern is found:
|
||||
// (addc Lo0, multLo), (sube Hi0, multHi),
|
||||
// where,
|
||||
// multHi/Lo: product of multiplication
|
||||
// Lo0: initial value of Lo register
|
||||
// Hi0: initial value of Hi register
|
||||
// Return true if pattern matching was successful.
|
||||
static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
|
||||
// SUBENode's second operand must be a flag output of an SUBC node in order
|
||||
// for the matching to be successful.
|
||||
SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
|
||||
|
||||
if (SUBCNode->getOpcode() != ISD::SUBC)
|
||||
return false;
|
||||
|
||||
SDValue MultHi = SUBENode->getOperand(1);
|
||||
SDValue MultLo = SUBCNode->getOperand(1);
|
||||
SDNode *MultNode = MultHi.getNode();
|
||||
unsigned MultOpc = MultHi.getOpcode();
|
||||
|
||||
// MultHi and MultLo must be generated by the same node,
|
||||
if (MultLo.getNode() != MultNode)
|
||||
return false;
|
||||
|
||||
// and it must be a multiplication.
|
||||
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
|
||||
return false;
|
||||
|
||||
// MultLo amd MultHi must be the first and second output of MultNode
|
||||
// respectively.
|
||||
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
|
||||
return false;
|
||||
|
||||
// Transform this to a MSUB only if SUBENode and SUBCNode are the only users
|
||||
// of the values of MultNode, in which case MultNode will be removed in later
|
||||
// phases.
|
||||
// If there exist users other than SUBENode or SUBCNode, this function returns
|
||||
// here, which will result in MultNode being mapped to a single MULT
|
||||
// instruction node rather than a pair of MULT and MSUB instructions being
|
||||
// produced.
|
||||
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
|
||||
return false;
|
||||
|
||||
SDValue Chain = CurDAG->getEntryNode();
|
||||
DebugLoc DL = SUBENode->getDebugLoc();
|
||||
|
||||
// Initialize accumulator.
|
||||
SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
|
||||
SUBCNode->getOperand(0),
|
||||
SUBENode->getOperand(0));
|
||||
|
||||
// create MipsSub(u) node
|
||||
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
|
||||
|
||||
SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
|
||||
MultNode->getOperand(0),// Factor 0
|
||||
MultNode->getOperand(1),// Factor 1
|
||||
ACCIn);
|
||||
|
||||
// replace uses of sube and subc here
|
||||
if (!SDValue(SUBCNode, 0).use_empty()) {
|
||||
SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
|
||||
SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
LoIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
|
||||
}
|
||||
if (!SDValue(SUBENode, 0).use_empty()) {
|
||||
SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
|
||||
SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
|
||||
HiIdx);
|
||||
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const MipsSubtarget *Subtarget) {
|
||||
if (DCI.isBeforeLegalize())
|
||||
return SDValue();
|
||||
|
||||
if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
|
||||
selectMADD(N, &DAG))
|
||||
return SDValue(N, 0);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
|
||||
TargetLowering::DAGCombinerInfo &DCI,
|
||||
const MipsSubtarget *Subtarget) {
|
||||
if (DCI.isBeforeLegalize())
|
||||
return SDValue();
|
||||
|
||||
if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
|
||||
selectMSUB(N, &DAG))
|
||||
return SDValue(N, 0);
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue
|
||||
MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
|
||||
SelectionDAG &DAG = DCI.DAG;
|
||||
|
||||
switch (N->getOpcode()) {
|
||||
case ISD::ADDE:
|
||||
return performADDECombine(N, DAG, DCI, Subtarget);
|
||||
case ISD::SUBE:
|
||||
return performSUBECombine(N, DAG, DCI, Subtarget);
|
||||
default:
|
||||
return MipsTargetLowering::PerformDAGCombine(N, DCI);
|
||||
}
|
||||
}
|
||||
|
||||
MachineBasicBlock *
|
||||
MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const {
|
||||
|
@ -26,6 +26,8 @@ namespace llvm {
|
||||
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
|
||||
virtual MachineBasicBlock *
|
||||
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: llc -march=mips < %s | FileCheck %s
|
||||
; RUN: llc -march=mips -mcpu=mips16 < %s
|
||||
|
||||
; CHECK: madd
|
||||
define i64 @madd1(i32 %a, i32 %b, i32 %c) nounwind readnone {
|
||||
|
Loading…
x
Reference in New Issue
Block a user