diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h @@ -182,6 +182,16 @@ MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, int64_t Amount, MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; + bool useMachineCombiner() const override { return true; } + + void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2, + MachineInstr &NewMI1, + MachineInstr &NewMI2) const override; + bool + getMachineCombinerPatterns(MachineInstr &Root, + SmallVectorImpl &Patterns, + bool DoRegPressureReduce) const override; + protected: const RISCVSubtarget &STI; }; @@ -204,6 +214,10 @@ // Implemented in RISCVGenInstrInfo.inc int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); +// Return true if both input instructions have equal rounding mode. If at least +// one of the instructions does not have rounding mode, false will be returned. +bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2); + // Special immediate for AVL operand of V pseudo instructions to indicate VLMax. static constexpr int64_t VLMaxSentinel = -1LL; } // namespace RISCV 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 @@ -1125,6 +1125,95 @@ return None; } +void RISCVInstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1, + MachineInstr &OldMI2, + MachineInstr &NewMI1, + MachineInstr &NewMI2) const { + int16_t FrmOpIdx = + RISCV::getNamedOperandIdx(OldMI1.getOpcode(), RISCV::OpName::frm); + if (FrmOpIdx < 0) { + assert(RISCV::getNamedOperandIdx(OldMI2.getOpcode(), RISCV::OpName::frm) < + 0 && + "Only one instruction has FRM"); + return; + } + assert(RISCV::getNamedOperandIdx(OldMI2.getOpcode(), RISCV::OpName::frm) >= + 0 && + "Only one instruction has FRM"); + assert(RISCV::hasEqualFRM(OldMI1, OldMI2) && + "Instructions with different FRMs must not be combined"); + + const MachineOperand &FRM = OldMI1.getOperand(FrmOpIdx); + MachineFunction &MF = *OldMI1.getMF(); + MachineInstrBuilder MIB1(MF, &NewMI1); + MIB1.add(FRM); + MachineInstrBuilder MIB2(MF, &NewMI2); + MIB2.add(FRM); + if (FRM.getImm() == RISCVFPRndMode::DYN) { + const MachineOperand &FRMDep = OldMI1.getOperand(FrmOpIdx + 1); + MIB1.add(FRMDep); + MIB2.add(FRMDep); + } +} + +static bool canReassociate(MachineInstr &Root, MachineOperand &MO) { + if (!MO.isReg() || !Register::isVirtualRegister(MO.getReg())) + return false; + MachineRegisterInfo &MRI = Root.getMF()->getRegInfo(); + MachineInstr *MI = MRI.getVRegDef(MO.getReg()); + if (!MI || !MRI.hasOneNonDBGUse(MO.getReg())) + return false; + + if (MI->getOpcode() != Root.getOpcode()) + return false; + + return RISCV::hasEqualFRM(Root, *MI); +} + +static bool +getFPReassocPatterns(MachineInstr &Root, + SmallVectorImpl &Patterns) { + bool Added = false; + if (canReassociate(Root, Root.getOperand(1))) { + Patterns.push_back(MachineCombinerPattern::REASSOC_AX_BY); + Patterns.push_back(MachineCombinerPattern::REASSOC_XA_BY); + Added |= true; + } + if (canReassociate(Root, Root.getOperand(2))) { + Patterns.push_back(MachineCombinerPattern::REASSOC_AX_YB); + Patterns.push_back(MachineCombinerPattern::REASSOC_XA_YB); + Added |= true; + } + return Added; +} + +static bool getFPPatterns(MachineInstr &Root, + SmallVectorImpl &Patterns) { + switch (Root.getOpcode()) { + default: + return false; + case RISCV::FADD_H: + case RISCV::FADD_S: + case RISCV::FADD_D: + case RISCV::FMUL_H: + case RISCV::FMUL_S: + case RISCV::FMUL_D: + return getFPReassocPatterns(Root, Patterns); + } +} + +bool RISCVInstrInfo::getMachineCombinerPatterns( + MachineInstr &Root, SmallVectorImpl &Patterns, + bool DoRegPressureReduce) const { + const TargetOptions &Options = Root.getMF()->getTarget().Options; + + if (Options.UnsafeFPMath && getFPPatterns(Root, Patterns)) + return true; + + return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns, + DoRegPressureReduce); +} + bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const { MCInstrDesc const &Desc = MI.getDesc(); @@ -2143,3 +2232,15 @@ return MI.getNumExplicitDefs() == 2 && MI.modifiesRegister(RISCV::VL) && !MI.isInlineAsm(); } + +bool RISCV::hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2) { + int16_t MI1FrmOpIdx = + RISCV::getNamedOperandIdx(MI1.getOpcode(), RISCV::OpName::frm); + int16_t MI2FrmOpIdx = + RISCV::getNamedOperandIdx(MI2.getOpcode(), RISCV::OpName::frm); + if (MI1FrmOpIdx < 0 || MI2FrmOpIdx < 0) + return false; + MachineOperand FrmOp1 = MI1.getOperand(MI1FrmOpIdx); + MachineOperand FrmOp2 = MI2.getOperand(MI2FrmOpIdx); + return FrmOp1.getImm() == FrmOp2.getImm(); +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -47,6 +47,11 @@ EnableGlobalMerge("riscv-enable-global-merge", cl::Hidden, cl::desc("Enable the global merge pass")); +static cl::opt + EnableMachineCombiner("riscv-enable-machine-combiner", + cl::desc("Enable the machine combiner pass"), + cl::init(true), cl::Hidden); + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() { RegisterTargetMachine X(getTheRISCV32Target()); RegisterTargetMachine Y(getTheRISCV64Target()); @@ -263,6 +268,8 @@ void RISCVPassConfig::addMachineSSAOptimization() { TargetPassConfig::addMachineSSAOptimization(); + if (TM->getOptLevel() == CodeGenOpt::Aggressive && EnableMachineCombiner) + addPass(&MachineCombinerID); if (TM->getTargetTriple().getArch() == Triple::riscv64) addPass(createRISCVSExtWRemovalPass()); diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll --- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll +++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll @@ -97,6 +97,9 @@ ; CHECK-NEXT: Machine code sinking ; CHECK-NEXT: Peephole Optimizations ; CHECK-NEXT: Remove dead machine instructions +; CHECK-NEXT: Machine Trace Metrics +; CHECK-NEXT: Lazy Machine Block Frequency Analysis +; CHECK-NEXT: Machine InstCombiner ; RV64-NEXT: RISCV sext.w Removal ; CHECK-NEXT: RISCV Pre-RA pseudo instruction expansion pass ; CHECK-NEXT: RISCV Merge Base Offset 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,17 +1,23 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs -mcpu=sifive-u74 \ -; RUN: -O3 -enable-unsafe-fp-math < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SAFE +; RUN: -O3 -riscv-enable-machine-combiner=true < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SAFE ; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs -mcpu=sifive-u74 \ -; RUN: -O3 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-UNSAFE - +; RUN: -O3 -enable-unsafe-fp-math -riscv-enable-machine-combiner=true < %s | FileCheck %s --check-prefixes=CHECK,CHECK-UNSAFE define double @test_reassoc_fadd1(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fadd1: -; CHECK: # %bb.0: -; CHECK-NEXT: fadd.d ft0, fa0, fa1 -; CHECK-NEXT: fadd.d ft0, ft0, fa2 -; CHECK-NEXT: fadd.d fa0, ft0, fa3 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fadd1: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa2 +; CHECK-SAFE-NEXT: fadd.d fa0, ft0, fa3 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fadd1: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fadd.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fadd double %a0, %a1 %t1 = fadd double %t0, %a2 %t2 = fadd double %t1, %a3 @@ -19,12 +25,19 @@ } define double @test_reassoc_fadd2(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fadd2: -; CHECK: # %bb.0: -; CHECK-NEXT: fadd.d ft0, fa0, fa1 -; CHECK-NEXT: fadd.d ft0, fa2, ft0 -; CHECK-NEXT: fadd.d fa0, ft0, fa3 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fadd2: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft0, fa2, ft0 +; CHECK-SAFE-NEXT: fadd.d fa0, ft0, fa3 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fadd2: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fadd.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fadd double %a0, %a1 %t1 = fadd double %a2, %t0 %t2 = fadd double %t1, %a3 @@ -32,12 +45,19 @@ } define double @test_reassoc_fadd3(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fadd3: -; CHECK: # %bb.0: -; CHECK-NEXT: fadd.d ft0, fa0, fa1 -; CHECK-NEXT: fadd.d ft0, ft0, fa2 -; CHECK-NEXT: fadd.d fa0, fa3, ft0 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fadd3: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa2 +; CHECK-SAFE-NEXT: fadd.d fa0, fa3, ft0 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fadd3: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fadd.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fadd double %a0, %a1 %t1 = fadd double %t0, %a2 %t2 = fadd double %a3, %t1 @@ -45,12 +65,19 @@ } define double @test_reassoc_fadd4(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fadd4: -; CHECK: # %bb.0: -; CHECK-NEXT: fadd.d ft0, fa0, fa1 -; CHECK-NEXT: fadd.d ft0, fa2, ft0 -; CHECK-NEXT: fadd.d fa0, fa3, ft0 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fadd4: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft0, fa2, ft0 +; CHECK-SAFE-NEXT: fadd.d fa0, fa3, ft0 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fadd4: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fadd.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fadd double %a0, %a1 %t1 = fadd double %a2, %t0 %t2 = fadd double %a3, %t1 @@ -58,12 +85,19 @@ } define double @test_reassoc_fmul1(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fmul1: -; CHECK: # %bb.0: -; CHECK-NEXT: fmul.d ft0, fa0, fa1 -; CHECK-NEXT: fmul.d ft0, ft0, fa2 -; CHECK-NEXT: fmul.d fa0, ft0, fa3 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fmul1: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft0, fa2 +; CHECK-SAFE-NEXT: fmul.d fa0, ft0, fa3 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fmul1: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fmul.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fmul.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fmul double %a0, %a1 %t1 = fmul double %t0, %a2 %t2 = fmul double %t1, %a3 @@ -71,12 +105,19 @@ } define double @test_reassoc_fmul2(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fmul2: -; CHECK: # %bb.0: -; CHECK-NEXT: fmul.d ft0, fa0, fa1 -; CHECK-NEXT: fmul.d ft0, fa2, ft0 -; CHECK-NEXT: fmul.d fa0, ft0, fa3 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fmul2: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, fa2, ft0 +; CHECK-SAFE-NEXT: fmul.d fa0, ft0, fa3 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fmul2: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fmul.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fmul.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fmul double %a0, %a1 %t1 = fmul double %a2, %t0 %t2 = fmul double %t1, %a3 @@ -84,12 +125,19 @@ } define double @test_reassoc_fmul3(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fmul3: -; CHECK: # %bb.0: -; CHECK-NEXT: fmul.d ft0, fa0, fa1 -; CHECK-NEXT: fmul.d ft0, ft0, fa2 -; CHECK-NEXT: fmul.d fa0, fa3, ft0 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fmul3: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft0, fa2 +; CHECK-SAFE-NEXT: fmul.d fa0, fa3, ft0 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fmul3: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fmul.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fmul.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fmul double %a0, %a1 %t1 = fmul double %t0, %a2 %t2 = fmul double %a3, %t1 @@ -97,12 +145,19 @@ } define double @test_reassoc_fmul4(double %a0, double %a1, double %a2, double %a3) { -; CHECK-LABEL: test_reassoc_fmul4: -; CHECK: # %bb.0: -; CHECK-NEXT: fmul.d ft0, fa0, fa1 -; CHECK-NEXT: fmul.d ft0, fa2, ft0 -; CHECK-NEXT: fmul.d fa0, fa3, ft0 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_fmul4: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, fa2, ft0 +; CHECK-SAFE-NEXT: fmul.d fa0, fa3, ft0 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_fmul4: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fmul.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fmul.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fmul.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fmul double %a0, %a1 %t1 = fmul double %a2, %t0 %t2 = fmul double %a3, %t1 @@ -110,15 +165,25 @@ } define double @test_reassoc_big1(double %a0, double %a1, double %a2, double %a3, double %a4, double %a5, double %a6) { -; CHECK-LABEL: test_reassoc_big1: -; CHECK: # %bb.0: -; CHECK-NEXT: fadd.d ft0, fa0, fa1 -; CHECK-NEXT: fadd.d ft0, ft0, fa2 -; CHECK-NEXT: fadd.d ft0, ft0, fa3 -; CHECK-NEXT: fadd.d ft0, ft0, fa4 -; CHECK-NEXT: fadd.d ft0, ft0, fa5 -; CHECK-NEXT: fadd.d fa0, ft0, fa6 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_big1: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa2 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa3 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa4 +; CHECK-SAFE-NEXT: fadd.d ft0, ft0, fa5 +; CHECK-SAFE-NEXT: fadd.d fa0, ft0, fa6 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_big1: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fadd.d ft0, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, fa3 +; CHECK-UNSAFE-NEXT: fadd.d ft2, fa4, fa5 +; CHECK-UNSAFE-NEXT: fadd.d ft0, ft0, ft1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, ft2, fa6 +; CHECK-UNSAFE-NEXT: fadd.d fa0, ft0, ft1 +; CHECK-UNSAFE-NEXT: ret %t0 = fadd double %a0, %a1 %t1 = fadd double %t0, %a2 %t2 = fadd double %t1, %a3 @@ -129,21 +194,37 @@ } 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: fmul.d ft0, fa2, ft0 -; CHECK-NEXT: fcvt.d.w ft1, a1 -; CHECK-NEXT: fmul.d ft0, ft1, ft0 -; CHECK-NEXT: fadd.d ft1, fa0, fa1 -; CHECK-NEXT: fmul.d ft0, ft0, fa1 -; CHECK-NEXT: fadd.d ft1, fa2, ft1 -; CHECK-NEXT: fadd.d ft2, fa2, fa1 -; CHECK-NEXT: fmul.d ft0, ft0, fa0 -; CHECK-NEXT: fsub.d ft1, fa3, ft1 -; CHECK-NEXT: fmul.d ft0, ft0, ft2 -; CHECK-NEXT: fmul.d fa0, ft1, ft0 -; CHECK-NEXT: ret +; CHECK-SAFE-LABEL: test_reassoc_big2: +; CHECK-SAFE: # %bb.0: +; CHECK-SAFE-NEXT: fcvt.d.w ft0, a0 +; CHECK-SAFE-NEXT: fmul.d ft0, fa2, ft0 +; CHECK-SAFE-NEXT: fcvt.d.w ft1, a1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft1, ft0 +; CHECK-SAFE-NEXT: fadd.d ft1, fa0, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft0, fa1 +; CHECK-SAFE-NEXT: fadd.d ft1, fa2, ft1 +; CHECK-SAFE-NEXT: fadd.d ft2, fa2, fa1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft0, fa0 +; CHECK-SAFE-NEXT: fsub.d ft1, fa3, ft1 +; CHECK-SAFE-NEXT: fmul.d ft0, ft0, ft2 +; CHECK-SAFE-NEXT: fmul.d fa0, ft1, ft0 +; CHECK-SAFE-NEXT: ret +; +; CHECK-UNSAFE-LABEL: test_reassoc_big2: +; CHECK-UNSAFE: # %bb.0: +; CHECK-UNSAFE-NEXT: fcvt.d.w ft0, a0 +; CHECK-UNSAFE-NEXT: fcvt.d.w ft1, a1 +; CHECK-UNSAFE-NEXT: fmul.d ft0, fa2, ft0 +; CHECK-UNSAFE-NEXT: fmul.d ft1, ft1, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft2, fa0, fa1 +; CHECK-UNSAFE-NEXT: fadd.d ft3, fa2, fa1 +; CHECK-UNSAFE-NEXT: fmul.d ft0, ft0, ft1 +; CHECK-UNSAFE-NEXT: fadd.d ft1, fa2, ft2 +; CHECK-UNSAFE-NEXT: fmul.d ft2, fa0, ft3 +; CHECK-UNSAFE-NEXT: fsub.d ft1, fa3, ft1 +; CHECK-UNSAFE-NEXT: fmul.d ft0, ft0, ft2 +; CHECK-UNSAFE-NEXT: fmul.d fa0, ft1, ft0 +; CHECK-UNSAFE-NEXT: ret %cvt1 = sitofp i32 %a2 to double %cvt2 = sitofp i32 %a4 to double %t5 = fmul double %a3, %cvt1 @@ -160,5 +241,4 @@ } ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; CHECK-SAFE: {{.*}} -; CHECK-UNSAFE: {{.*}} +; CHECK: {{.*}}