diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -1335,6 +1335,28 @@ } } +static bool isFMIN(unsigned Opc) { + switch (Opc) { + default: + return false; + case RISCV::FMIN_H: + case RISCV::FMIN_S: + case RISCV::FMIN_D: + return true; + } +} + +static bool isFMAX(unsigned Opc) { + switch (Opc) { + default: + return false; + case RISCV::FMAX_H: + case RISCV::FMAX_S: + case RISCV::FMAX_D: + return true; + } +} + bool RISCVInstrInfo::hasReassociableSibling(const MachineInstr &Inst, bool &Commuted) const { if (!TargetInstrInfo::hasReassociableSibling(Inst, Commuted)) @@ -1358,7 +1380,7 @@ Opc = *InverseOpcode; } - if (isFADD(Opc) || isFMUL(Opc)) + if (isFADD(Opc) || isFMUL(Opc) || isFMIN(Opc) || isFMAX(Opc)) return Inst.getFlag(MachineInstr::MIFlag::FmReassoc) && Inst.getFlag(MachineInstr::MIFlag::FmNsz); diff --git a/llvm/test/CodeGen/RISCV/machine-combiner.ll b/llvm/test/CodeGen/RISCV/machine-combiner.ll --- a/llvm/test/CodeGen/RISCV/machine-combiner.ll +++ b/llvm/test/CodeGen/RISCV/machine-combiner.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs -mcpu=sifive-u74 \ +; RUN: llc -mtriple=riscv64 -mattr=+d,+zfh -verify-machineinstrs -mcpu=sifive-u74 \ ; RUN: -O1 -riscv-enable-machine-combiner=true < %s | \ ; RUN: FileCheck %s @@ -653,3 +653,88 @@ %t2 = mul i64 %t1, %a3 ret i64 %t2 } + +define half @test_fmin_f16(half %a0, half %a1, half %a2, half %a3) { +; CHECK-LABEL: test_fmin_f16: +; CHECK: # %bb.0: +; CHECK-NEXT: fmin.h ft0, fa0, fa1 +; CHECK-NEXT: fmin.h ft1, fa2, fa3 +; CHECK-NEXT: fmin.h fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc half @llvm.minnum.f16(half %a0, half %a1) + %t1 = call nsz reassoc half @llvm.minnum.f16(half %t0, half %a2) + %t2 = call nsz reassoc half @llvm.minnum.f16(half %t1, half %a3) + ret half %t2 +} + +define float @test_fmin_f32(float %a0, float %a1, float %a2, float %a3) { +; CHECK-LABEL: test_fmin_f32: +; CHECK: # %bb.0: +; CHECK-NEXT: fmin.s ft0, fa0, fa1 +; CHECK-NEXT: fmin.s ft1, fa2, fa3 +; CHECK-NEXT: fmin.s fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc float @llvm.minnum.f32(float %a0, float %a1) + %t1 = call nsz reassoc float @llvm.minnum.f32(float %t0, float %a2) + %t2 = call nsz reassoc float @llvm.minnum.f32(float %t1, float %a3) + ret float %t2 +} + +define double @test_fmin_f64(double %a0, double %a1, double %a2, double %a3) { +; CHECK-LABEL: test_fmin_f64: +; CHECK: # %bb.0: +; CHECK-NEXT: fmin.d ft0, fa0, fa1 +; CHECK-NEXT: fmin.d ft1, fa2, fa3 +; CHECK-NEXT: fmin.d fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc double @llvm.minnum.f64(double %a0, double %a1) + %t1 = call nsz reassoc double @llvm.minnum.f64(double %t0, double %a2) + %t2 = call nsz reassoc double @llvm.minnum.f64(double %t1, double %a3) + ret double %t2 +} + +define half @test_fmax_f16(half %a0, half %a1, half %a2, half %a3) { +; CHECK-LABEL: test_fmax_f16: +; CHECK: # %bb.0: +; CHECK-NEXT: fmax.h ft0, fa0, fa1 +; CHECK-NEXT: fmax.h ft1, fa2, fa3 +; CHECK-NEXT: fmax.h fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc half @llvm.maxnum.f16(half %a0, half %a1) + %t1 = call nsz reassoc half @llvm.maxnum.f16(half %t0, half %a2) + %t2 = call nsz reassoc half @llvm.maxnum.f16(half %t1, half %a3) + ret half %t2 +} + +define float @test_fmax_f32(float %a0, float %a1, float %a2, float %a3) { +; CHECK-LABEL: test_fmax_f32: +; CHECK: # %bb.0: +; CHECK-NEXT: fmax.s ft0, fa0, fa1 +; CHECK-NEXT: fmax.s ft1, fa2, fa3 +; CHECK-NEXT: fmax.s fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc float @llvm.maxnum.f32(float %a0, float %a1) + %t1 = call nsz reassoc float @llvm.maxnum.f32(float %t0, float %a2) + %t2 = call nsz reassoc float @llvm.maxnum.f32(float %t1, float %a3) + ret float %t2 +} + +define double @test_fmax_f64(double %a0, double %a1, double %a2, double %a3) { +; CHECK-LABEL: test_fmax_f64: +; CHECK: # %bb.0: +; CHECK-NEXT: fmax.d ft0, fa0, fa1 +; CHECK-NEXT: fmax.d ft1, fa2, fa3 +; CHECK-NEXT: fmax.d fa0, ft0, ft1 +; CHECK-NEXT: ret + %t0 = call nsz reassoc double @llvm.maxnum.f64(double %a0, double %a1) + %t1 = call nsz reassoc double @llvm.maxnum.f64(double %t0, double %a2) + %t2 = call nsz reassoc double @llvm.maxnum.f64(double %t1, double %a3) + ret double %t2 +} + +declare half @llvm.minnum.f16(half, half) +declare float @llvm.minnum.f32(float, float) +declare double @llvm.minnum.f64(double, double) +declare half @llvm.maxnum.f16(half, half) +declare float @llvm.maxnum.f32(float, float) +declare double @llvm.maxnum.f64(double, double)