Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -57,6 +57,8 @@ 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); Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -379,28 +379,6 @@ 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(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(Node); if (VT == XLenVT && ConstNode->isNullValue()) { @@ -1092,6 +1070,23 @@ 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(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 Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -145,7 +145,7 @@ 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 @@ N->getValueType(0)); }]>; +// Check if an addition can be broken to a pair of ADDI. +def AddiPair : ComplexPattern; + +// Return imm/2. +def AddiPairImmA : SDNodeXFormgetTargetConstant(N->getSExtValue() / 2, SDLoc(N), + N->getValueType(0)); +}]>; + +// Return imm - imm/2. +def AddiPairImmB : SDNodeXFormgetSExtValue(); + return CurDAG->getTargetConstant(Imm - Imm / 2, SDLoc(N), + N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction Formats //===----------------------------------------------------------------------===// @@ -1274,6 +1290,15 @@ // 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))>; +let Predicates = [IsRV64] in +def : Pat<(sext_inreg (add GPR:$rs1, (AddiPair GPR:$rs2)), i32), + (ADDIW (ADDIW GPR:$rs1, (AddiPairImmB GPR:$rs2)), + (AddiPairImmA GPR:$rs2))>; + //===----------------------------------------------------------------------===// // Standard extensions //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/RISCV/add-imm.ll =================================================================== --- llvm/test/CodeGen/RISCV/add-imm.ll +++ llvm/test/CodeGen/RISCV/add-imm.ll @@ -159,9 +159,8 @@ ; ; RV64I-LABEL: add32_sext_accept: ; RV64I: # %bb.0: -; RV64I-NEXT: lui a1, 1 -; RV64I-NEXT: addiw a1, a1, -1097 -; RV64I-NEXT: addw a0, a0, a1 +; RV64I-NEXT: addiw a0, a0, 1500 +; RV64I-NEXT: addiw a0, a0, 1499 ; RV64I-NEXT: ret %1 = add i32 %a, 2999 ret i32 %1