mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-10 20:33:15 +00:00
Lower add (mul a, b), c into MACCU / MACCS nodes which translate
directly to the maccu / maccs instructions. We handle this in ExpandADDSUB since after type legalisation it is messy to recognise these operations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98150 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1250ac8a09
commit
ebc64cf780
@ -208,6 +208,18 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
|
|||||||
return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
|
return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
|
||||||
Ops, 3);
|
Ops, 3);
|
||||||
}
|
}
|
||||||
|
case XCoreISD::MACCU: {
|
||||||
|
SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
|
||||||
|
N->getOperand(2), N->getOperand(3) };
|
||||||
|
return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
|
||||||
|
Ops, 4);
|
||||||
|
}
|
||||||
|
case XCoreISD::MACCS: {
|
||||||
|
SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
|
||||||
|
N->getOperand(2), N->getOperand(3) };
|
||||||
|
return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
|
||||||
|
Ops, 4);
|
||||||
|
}
|
||||||
// Other cases are autogenerated.
|
// Other cases are autogenerated.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,8 @@ getTargetNodeName(unsigned Opcode) const
|
|||||||
case XCoreISD::RETSP : return "XCoreISD::RETSP";
|
case XCoreISD::RETSP : return "XCoreISD::RETSP";
|
||||||
case XCoreISD::LADD : return "XCoreISD::LADD";
|
case XCoreISD::LADD : return "XCoreISD::LADD";
|
||||||
case XCoreISD::LSUB : return "XCoreISD::LSUB";
|
case XCoreISD::LSUB : return "XCoreISD::LSUB";
|
||||||
|
case XCoreISD::MACCU : return "XCoreISD::MACCU";
|
||||||
|
case XCoreISD::MACCS : return "XCoreISD::MACCS";
|
||||||
case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
|
case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
|
||||||
case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
|
case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
|
||||||
default : return NULL;
|
default : return NULL;
|
||||||
@ -541,12 +543,77 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG)
|
|||||||
return CallResult.second;
|
return CallResult.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDValue XCoreTargetLowering::
|
||||||
|
TryExpandADDSUBWithMul(SDNode *N, SelectionDAG &DAG)
|
||||||
|
{
|
||||||
|
SDValue Mul;
|
||||||
|
SDValue Other;
|
||||||
|
if (N->getOperand(0).getOpcode() == ISD::MUL) {
|
||||||
|
Mul = N->getOperand(0);
|
||||||
|
Other = N->getOperand(1);
|
||||||
|
} else if (N->getOperand(1).getOpcode() == ISD::MUL) {
|
||||||
|
Mul = N->getOperand(1);
|
||||||
|
Other = N->getOperand(0);
|
||||||
|
} else {
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
|
DebugLoc dl = N->getDebugLoc();
|
||||||
|
SDValue LL, RL, AddendL, AddendH;
|
||||||
|
LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Mul.getOperand(0), DAG.getConstant(0, MVT::i32));
|
||||||
|
RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Mul.getOperand(1), DAG.getConstant(0, MVT::i32));
|
||||||
|
AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Other, DAG.getConstant(0, MVT::i32));
|
||||||
|
AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Other, DAG.getConstant(1, MVT::i32));
|
||||||
|
APInt HighMask = APInt::getHighBitsSet(64, 32);
|
||||||
|
unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
|
||||||
|
unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
|
||||||
|
if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
|
||||||
|
DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
|
||||||
|
// The inputs are both zero-extended.
|
||||||
|
SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
|
||||||
|
DAG.getVTList(MVT::i32, MVT::i32), AddendH,
|
||||||
|
AddendL, LL, RL);
|
||||||
|
SDValue Lo(Hi.getNode(), 1);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
|
||||||
|
}
|
||||||
|
if (LHSSB > 32 && RHSSB > 32) {
|
||||||
|
// The inputs are both sign-extended.
|
||||||
|
SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
|
||||||
|
DAG.getVTList(MVT::i32, MVT::i32), AddendH,
|
||||||
|
AddendL, LL, RL);
|
||||||
|
SDValue Lo(Hi.getNode(), 1);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
|
||||||
|
}
|
||||||
|
SDValue LH, RH;
|
||||||
|
LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Mul.getOperand(0), DAG.getConstant(1, MVT::i32));
|
||||||
|
RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
|
||||||
|
Mul.getOperand(1), DAG.getConstant(1, MVT::i32));
|
||||||
|
SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
|
||||||
|
DAG.getVTList(MVT::i32, MVT::i32), AddendH,
|
||||||
|
AddendL, LL, RL);
|
||||||
|
SDValue Lo(Hi.getNode(), 1);
|
||||||
|
RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
|
||||||
|
LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
|
||||||
|
Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
|
||||||
|
Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
|
||||||
|
return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
|
||||||
|
}
|
||||||
|
|
||||||
SDValue XCoreTargetLowering::
|
SDValue XCoreTargetLowering::
|
||||||
ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
|
ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
|
||||||
{
|
{
|
||||||
assert(N->getValueType(0) == MVT::i64 &&
|
assert(N->getValueType(0) == MVT::i64 &&
|
||||||
(N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
|
(N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
|
||||||
"Unknown operand to lower!");
|
"Unknown operand to lower!");
|
||||||
|
|
||||||
|
SDValue Result = TryExpandADDSUBWithMul(N, DAG);
|
||||||
|
if (Result.getNode() != 0)
|
||||||
|
return Result;
|
||||||
|
|
||||||
DebugLoc dl = N->getDebugLoc();
|
DebugLoc dl = N->getDebugLoc();
|
||||||
|
|
||||||
// Extract components
|
// Extract components
|
||||||
|
@ -54,6 +54,12 @@ namespace llvm {
|
|||||||
// Corresponds to LSUB instruction
|
// Corresponds to LSUB instruction
|
||||||
LSUB,
|
LSUB,
|
||||||
|
|
||||||
|
// Corresponds to MACCU instruction
|
||||||
|
MACCU,
|
||||||
|
|
||||||
|
// Corresponds to MACCS instruction
|
||||||
|
MACCS,
|
||||||
|
|
||||||
// Jumptable branch.
|
// Jumptable branch.
|
||||||
BR_JT,
|
BR_JT,
|
||||||
|
|
||||||
@ -140,6 +146,7 @@ namespace llvm {
|
|||||||
EVT VT) const;
|
EVT VT) const;
|
||||||
|
|
||||||
// Expand specifics
|
// Expand specifics
|
||||||
|
SDValue TryExpandADDSUBWithMul(SDNode *Op, SelectionDAG &DAG);
|
||||||
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
|
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
@ -18,3 +18,27 @@ define i64 @sub64(i64 %a, i64 %b) {
|
|||||||
; CHECK-NEXT: lsub r2, r0, r0, r2, r11
|
; CHECK-NEXT: lsub r2, r0, r0, r2, r11
|
||||||
; CHECK-NEXT: lsub r2, r1, r1, r3, r2
|
; CHECK-NEXT: lsub r2, r1, r1, r3, r2
|
||||||
; CHECK-NEXT: retsp 0
|
; CHECK-NEXT: retsp 0
|
||||||
|
|
||||||
|
define i64 @maccu(i64 %a, i32 %b, i32 %c) {
|
||||||
|
entry:
|
||||||
|
%0 = zext i32 %b to i64
|
||||||
|
%1 = zext i32 %c to i64
|
||||||
|
%2 = mul i64 %1, %0
|
||||||
|
%3 = add i64 %2, %a
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
; CHECK: maccu:
|
||||||
|
; CHECK: maccu r1, r0, r3, r2
|
||||||
|
; CHECK-NEXT: retsp 0
|
||||||
|
|
||||||
|
define i64 @maccs(i64 %a, i32 %b, i32 %c) {
|
||||||
|
entry:
|
||||||
|
%0 = sext i32 %b to i64
|
||||||
|
%1 = sext i32 %c to i64
|
||||||
|
%2 = mul i64 %1, %0
|
||||||
|
%3 = add i64 %2, %a
|
||||||
|
ret i64 %3
|
||||||
|
}
|
||||||
|
; CHECK: maccs:
|
||||||
|
; CHECK: maccs r1, r0, r3, r2
|
||||||
|
; CHECK-NEXT: retsp 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user