diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3516,6 +3516,11 @@ return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(0), N0.getOperand(1).getOperand(0)); + // fold (A+B)-(A-C) -> B+C + if (N0.getOpcode() == ISD::ADD && N1.getOpcode() == ISD::SUB && + N0.getOperand(0) == N1.getOperand(0)) + return DAG.getNode(ISD::ADD, DL, VT, N1.getOperand(1), N0.getOperand(1)); + // fold (A-(B-C)) -> A+(C-B) if (N1.getOpcode() == ISD::SUB && N1.hasOneUse()) return DAG.getNode(ISD::ADD, DL, VT, N0, diff --git a/llvm/test/CodeGen/RISCV/sub-combine.ll b/llvm/test/CodeGen/RISCV/sub-combine.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/sub-combine.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32I %s +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64I %s + +define signext i32 @sub_combine(i32 %a, i32 %b, i32 %c) nounwind { +; RV32I-LABEL: sub_combine: +; RV32I: # %bb.0: +; RV32I-NEXT: add a0, a2, a1 +; RV32I-NEXT: ret +; +; RV64I-LABEL: sub_combine: +; RV64I: # %bb.0: +; RV64I-NEXT: addw a0, a2, a1 +; RV64I-NEXT: ret + %1 = add i32 %a, %b + %2 = sub i32 %a, %c + %3 = sub i32 %1, %2 + ret i32 %3 +}