1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[RISCV] Refactor an optimization of addition with immediate

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D100769
This commit is contained in:
Ben Shi 2021-04-20 18:04:25 +08:00
parent a248bdd4af
commit 9a8c38e0c8
3 changed files with 41 additions and 23 deletions

View File

@ -379,28 +379,6 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
MVT VT = Node->getSimpleValueType(0);
switch (Opcode) {
case ISD::ADD: {
// Optimize (add r, imm) to (addi (addi r, imm0) imm1) if applicable. The
// immediate must be in specific ranges and have a single use.
if (auto *ConstOp = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
if (!(ConstOp->hasOneUse()))
break;
// The imm must be in range [-4096,-2049] or [2048,4094].
int64_t Imm = ConstOp->getSExtValue();
if (!(-4096 <= Imm && Imm <= -2049) && !(2048 <= Imm && Imm <= 4094))
break;
// Break the imm to imm0+imm1.
const SDValue ImmOp0 = CurDAG->getTargetConstant(Imm - Imm / 2, DL, VT);
const SDValue ImmOp1 = CurDAG->getTargetConstant(Imm / 2, DL, VT);
auto *NodeAddi0 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT,
Node->getOperand(0), ImmOp0);
auto *NodeAddi1 = CurDAG->getMachineNode(RISCV::ADDI, DL, VT,
SDValue(NodeAddi0, 0), ImmOp1);
ReplaceNode(Node, NodeAddi1);
return;
}
break;
}
case ISD::Constant: {
auto *ConstNode = cast<ConstantSDNode>(Node);
if (VT == XLenVT && ConstNode->isNullValue()) {
@ -1092,6 +1070,23 @@ bool RISCVDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) {
return false;
}
// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),
// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12.
bool RISCVDAGToDAGISel::selectAddiPair(SDValue N, SDValue &Val) {
if (auto *ConstOp = dyn_cast<ConstantSDNode>(N)) {
// The immediate operand must have only use.
if (!(ConstOp->hasOneUse()))
return false;
// The immediate operand must be in range [-4096,-2049] or [2048,4094].
int64_t Imm = ConstOp->getSExtValue();
if ((-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094)) {
Val = N;
return true;
}
}
return false;
}
// Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
// on RV64).
// SLLIUW is the same as SLLI except for the fact that it clears the bits

View File

@ -57,6 +57,8 @@ public:
bool selectSExti32(SDValue N, SDValue &Val);
bool selectZExti32(SDValue N, SDValue &Val);
bool selectAddiPair(SDValue N, SDValue &Val);
bool MatchSLLIUW(SDNode *N) const;
bool selectVLOp(SDValue N, SDValue &VL);

View File

@ -145,7 +145,7 @@ def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
if (STI.getTargetTriple().isArch64Bit())
return isUInt<6>(Imm);
return isUInt<6>(Imm);
return isUInt<5>(Imm);
}];
let OperandType = "OPERAND_UIMMLOG2XLEN";
@ -343,6 +343,22 @@ def ImmSubFrom32 : SDNodeXForm<imm, [{
N->getValueType(0));
}]>;
// Check if an addition can be broken to a pair of ADDI.
def AddiPair : ComplexPattern<XLenVT, 1, "selectAddiPair">;
// Return imm/2.
def AddiPairImmA : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N),
N->getValueType(0));
}]>;
// Return imm - imm/2.
def AddiPairImmB : SDNodeXForm<imm, [{
int64_t Imm = N->getSExtValue();
return CurDAG->getTargetConstant(Imm - Imm / 2, SDLoc(N),
N->getValueType(0));
}]>;
//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
@ -1274,6 +1290,11 @@ def : Pat<(trap), (UNIMP)>;
// debugger if possible.
def : Pat<(debugtrap), (EBREAK)>;
/// Simple optimization
def : Pat<(add GPR:$rs1, (AddiPair GPR:$rs2)),
(ADDI (ADDI GPR:$rs1, (AddiPairImmB GPR:$rs2)),
(AddiPairImmA GPR:$rs2))>;
//===----------------------------------------------------------------------===//
// Standard extensions
//===----------------------------------------------------------------------===//