[llvm] [RISCV] Rewrite ADD to SUB to reuse a materialized negated constant (PR #221027)
Pengcheng Wang via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 3 21:56:47 PDT 2026
================
@@ -128,6 +128,42 @@ void RISCVDAGToDAGISel::PreprocessISelDAG() {
TrueMask, VLMAX);
break;
}
+ case ISD::ADD: {
+ // Turn (add X, C) into (sub X, -C) when a constant node holding -C
+ // already exists in the DAG, so both share one materialization. Do this
+ // before selection, while both are still ConstantSDNodes: by selection
+ // time -C may already have been selected into instructions.
+ auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (!N1C)
+ break;
+ MVT VT = N->getSimpleValueType(0);
+ if (VT != Subtarget->getXLenVT())
+ break;
+ int64_t Imm = N1C->getSExtValue();
+ // Small constants are a single instruction, and -INT64_MIN == INT64_MIN.
+ if (isInt<32>(Imm) || Imm == INT64_MIN)
+ break;
+ // Reusing a register is free, so require only that -C is no more
+ // expensive to materialize than C.
+ int OrigCost = RISCVMatInt::getIntMatCost(APInt(64, Imm), 64, *Subtarget,
+ /*CompressionCost=*/true);
+ int NegCost = RISCVMatInt::getIntMatCost(APInt(64, -Imm), 64, *Subtarget,
+ /*CompressionCost=*/true);
+ if (NegCost > OrigCost)
+ break;
+ // Only rewrite when -C already exists, else this just moves the cost.
+ bool HasNegConst = any_of(CurDAG->allnodes(), [&](const SDNode &Node) {
+ auto *C = dyn_cast<ConstantSDNode>(&Node);
+ return C && C->getSimpleValueType(0) == VT && C->getSExtValue() == -Imm;
+ });
+ if (!HasNegConst)
+ break;
+ SDLoc DL(N);
+ // getConstant uniques onto the existing -C node, so it is shared.
+ Result = CurDAG->getNode(ISD::SUB, DL, VT, N->getOperand(0),
----------------
wangpc-pp wrote:
https://github.com/llvm/llvm-project/pull/221027/commits/0de89c9e36e4f48adbb5bdde436d514c811628ee
https://github.com/llvm/llvm-project/pull/221027
More information about the llvm-commits
mailing list