[llvm] 1cdffa3 - [MachineCombiner][RISCV] Support inverse instructions reassociation

Anton Sidorenko via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 15 05:48:59 PST 2022


Author: Anton Sidorenko
Date: 2022-12-15T16:48:30+03:00
New Revision: 1cdffa359a3344f966ed309de17af17f8abfbe4d

URL: https://github.com/llvm/llvm-project/commit/1cdffa359a3344f966ed309de17af17f8abfbe4d
DIFF: https://github.com/llvm/llvm-project/commit/1cdffa359a3344f966ed309de17af17f8abfbe4d.diff

LOG: [MachineCombiner][RISCV] Support inverse instructions reassociation

This patch adds reassociation of FADD/FSUB instruction pairs.

Differential Revision: https://reviews.llvm.org/D138660

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
    llvm/lib/Target/RISCV/RISCVInstrInfo.h
    llvm/test/CodeGen/RISCV/machine-combiner.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index acee7a994707..92e8fca53c12 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1203,8 +1203,12 @@ bool RISCVInstrInfo::hasReassociableSibling(const MachineInstr &Inst,
 bool RISCVInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
                                                  bool Invert) const {
   unsigned Opc = Inst.getOpcode();
-  if (Invert)
-    return false;
+  if (Invert) {
+    auto InverseOpcode = getInverseOpcode(Opc);
+    if (!InverseOpcode)
+      return false;
+    Opc = *InverseOpcode;
+  }
 
   if (isFADD(Opc) || isFMUL(Opc))
     return Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&
@@ -1212,6 +1216,26 @@ bool RISCVInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
   return false;
 }
 
+std::optional<unsigned>
+RISCVInstrInfo::getInverseOpcode(unsigned Opcode) const {
+  switch (Opcode) {
+  default:
+    return std::nullopt;
+  case RISCV::FADD_H:
+    return RISCV::FSUB_H;
+  case RISCV::FADD_S:
+    return RISCV::FSUB_S;
+  case RISCV::FADD_D:
+    return RISCV::FSUB_D;
+  case RISCV::FSUB_H:
+    return RISCV::FADD_H;
+  case RISCV::FSUB_S:
+    return RISCV::FADD_S;
+  case RISCV::FSUB_D:
+    return RISCV::FADD_D;
+  }
+}
+
 static bool canCombineFPFusedMultiply(const MachineInstr &Root,
                                       const MachineOperand &MO,
                                       bool DoRegPressureReduce) {

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index eac190f7c99d..ceddbacf61e0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -208,6 +208,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
   bool isAssociativeAndCommutative(const MachineInstr &Inst,
                                    bool Invert) const override;
 
+  std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;
+
 protected:
   const RISCVSubtarget &STI;
 };

diff  --git a/llvm/test/CodeGen/RISCV/machine-combiner.ll b/llvm/test/CodeGen/RISCV/machine-combiner.ll
index 8c5db3479f30..55551044cd7d 100644
--- a/llvm/test/CodeGen/RISCV/machine-combiner.ll
+++ b/llvm/test/CodeGen/RISCV/machine-combiner.ll
@@ -129,18 +129,18 @@ define double @test_reassoc_big1(double %a0, double %a1, double %a2, double %a3,
 define double @test_reassoc_big2(double %a0, double %a1, i32 %a2, double %a3, i32 %a4, double %a5) {
 ; CHECK-LABEL: test_reassoc_big2:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    fcvt.d.w ft0, a0
-; CHECK-NEXT:    fcvt.d.w ft1, a1
-; CHECK-NEXT:    fmul.d ft0, fa2, ft0
-; CHECK-NEXT:    fmul.d ft1, ft1, fa1
-; CHECK-NEXT:    fadd.d ft2, fa0, fa1
-; CHECK-NEXT:    fadd.d ft3, fa2, fa1
-; CHECK-NEXT:    fmul.d ft0, ft1, ft0
-; CHECK-NEXT:    fadd.d ft1, fa2, ft2
-; CHECK-NEXT:    fmul.d ft2, fa0, ft3
-; CHECK-NEXT:    fsub.d ft1, fa3, ft1
-; CHECK-NEXT:    fmul.d ft0, ft0, ft2
-; CHECK-NEXT:    fmul.d fa0, ft1, ft0
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa3, fa2
+; CHECK-NEXT:    fadd.d ft2, fa2, fa1
+; CHECK-NEXT:    fcvt.d.w ft3, a0
+; CHECK-NEXT:    fcvt.d.w ft4, a1
+; CHECK-NEXT:    fmul.d ft3, fa2, ft3
+; CHECK-NEXT:    fmul.d ft4, ft4, fa1
+; CHECK-NEXT:    fsub.d ft0, ft1, ft0
+; CHECK-NEXT:    fmul.d ft1, fa0, ft2
+; CHECK-NEXT:    fmul.d ft2, ft4, ft3
+; CHECK-NEXT:    fmul.d ft0, ft0, ft1
+; CHECK-NEXT:    fmul.d fa0, ft0, ft2
 ; CHECK-NEXT:    ret
   %cvt1 = sitofp i32 %a2 to double
   %cvt2 = sitofp i32 %a4 to double
@@ -237,3 +237,159 @@ define double @test_fnmsub(double %a0, double %a1, double %a2) {
   %t2 = fdiv double %t1, %t0
   ret double %t2
 }
+
+define double @test_reassoc_fsub1(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub1:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa2, fa3
+; CHECK-NEXT:    fadd.d fa0, ft0, ft1
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fadd nsz reassoc double %t0, %a2
+  %t2 = fsub nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub2(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub2:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa2, fa3
+; CHECK-NEXT:    fsub.d fa0, ft0, ft1
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %t0, %a2
+  %t2 = fadd nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub3(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub3:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fadd.d ft1, fa2, fa3
+; CHECK-NEXT:    fsub.d fa0, ft0, ft1
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %t0, %a2
+  %t2 = fsub nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub4(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub4:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa2, fa3
+; CHECK-NEXT:    fadd.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fadd nsz reassoc double %a2, %t0
+  %t2 = fsub nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub5(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub5:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fadd.d ft1, fa2, fa3
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %a2, %t0
+  %t2 = fadd nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub6(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub6:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa2, fa3
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %a2, %t0
+  %t2 = fsub nsz reassoc double %t1, %a3
+  ret double %t2
+}
+
+define double @test_reassoc_fsub7(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub7:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa3, fa2
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fadd nsz reassoc double %t0, %a2
+  %t2 = fsub nsz reassoc double %a3, %t1
+  ret double %t2
+}
+
+define double @test_reassoc_fsub8(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa3, fa2
+; CHECK-NEXT:    fadd.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %t0, %a2
+  %t2 = fadd nsz reassoc double %a3, %t1
+  ret double %t2
+}
+
+define double @test_reassoc_fsub9(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub9:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fadd.d ft1, fa3, fa2
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %t0, %a2
+  %t2 = fsub nsz reassoc double %a3, %t1
+  ret double %t2
+}
+
+define double @test_reassoc_fsub10(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub10:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa3, fa2
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fadd nsz reassoc double %a2, %t0
+  %t2 = fsub nsz reassoc double %a3, %t1
+  ret double %t2
+}
+
+define double @test_reassoc_fsub11(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub11:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fadd.d ft1, fa3, fa2
+; CHECK-NEXT:    fsub.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %a2, %t0
+  %t2 = fadd nsz reassoc double %a3, %t1
+  ret double %t2
+}
+
+define double @test_reassoc_fsub12(double %a0, double %a1, double %a2, double %a3) {
+; CHECK-LABEL: test_reassoc_fsub12:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fadd.d ft0, fa0, fa1
+; CHECK-NEXT:    fsub.d ft1, fa3, fa2
+; CHECK-NEXT:    fadd.d fa0, ft1, ft0
+; CHECK-NEXT:    ret
+  %t0 = fadd nsz reassoc double %a0, %a1
+  %t1 = fsub nsz reassoc double %a2, %t0
+  %t2 = fsub nsz reassoc double %a3, %t1
+  ret double %t2
+}


        


More information about the llvm-commits mailing list