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,20 @@ 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; + + void + finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P, + SmallVectorImpl &InsInstrs) const override; + protected: const RISCVSubtarget &STI; }; @@ -204,6 +218,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,127 @@ return None; } +void RISCVInstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1, + MachineInstr &OldMI2, + MachineInstr &NewMI1, + MachineInstr &NewMI2) const { + uint16_t IntersectedFlags = OldMI1.getFlags() & OldMI2.getFlags(); + NewMI1.setFlags(IntersectedFlags); + NewMI2.setFlags(IntersectedFlags); +} + +void RISCVInstrInfo::finalizeInsInstrs( + MachineInstr &Root, MachineCombinerPattern &P, + SmallVectorImpl &InsInstrs) const { + int16_t FrmOpIdx = + RISCV::getNamedOperandIdx(Root.getOpcode(), RISCV::OpName::frm); + if (FrmOpIdx < 0) { + assert(all_of(InsInstrs, + [](MachineInstr *MI) { + return RISCV::getNamedOperandIdx(MI->getOpcode(), + RISCV::OpName::frm) < 0; + }) && + "New instructions require FRM whereas the old one does not have it"); + return; + } + + const MachineOperand &FRM = Root.getOperand(FrmOpIdx); + MachineFunction &MF = *Root.getMF(); + + for (auto NewMI : InsInstrs) { + assert(static_cast(RISCV::getNamedOperandIdx( + NewMI->getOpcode(), RISCV::OpName::frm)) == + NewMI->getNumOperands() && + "Instruction has unexpected number of operands"); + MachineInstrBuilder MIB(MF, NewMI); + MIB.add(FRM); + if (FRM.getImm() == RISCVFPRndMode::DYN) + MIB.addUse(RISCV::FRM, RegState::Implicit); + } +} + +static bool isFADD(unsigned Opc) { + switch (Opc) { + default: + return false; + case RISCV::FADD_H: + case RISCV::FADD_S: + case RISCV::FADD_D: + return true; + } +} + +static bool isFMUL(unsigned Opc) { + switch (Opc) { + default: + return false; + case RISCV::FMUL_H: + case RISCV::FMUL_S: + case RISCV::FMUL_D: + return true; + } +} + +static bool isAssociativeAndCommutativeFPOpcode(unsigned Opc) { + return isFADD(Opc) || isFMUL(Opc); +} + +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; + + if (!Root.getFlag(MachineInstr::MIFlag::FmReassoc) || + !Root.getFlag(MachineInstr::MIFlag::FmNsz) || + !MI->getFlag(MachineInstr::MIFlag::FmReassoc) || + !MI->getFlag(MachineInstr::MIFlag::FmNsz)) + 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) { + unsigned Opc = Root.getOpcode(); + if (isAssociativeAndCommutativeFPOpcode(Opc)) + return getFPReassocPatterns(Root, Patterns); + return false; +} + +bool RISCVInstrInfo::getMachineCombinerPatterns( + MachineInstr &Root, SmallVectorImpl &Patterns, + bool DoRegPressureReduce) const { + + if (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 +2264,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-mir.ll b/llvm/test/CodeGen/RISCV/machine-combiner-mir.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/machine-combiner-mir.ll @@ -0,0 +1,87 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs -mcpu=sifive-u74 \ +; RUN: -O3 -enable-unsafe-fp-math -riscv-enable-machine-combiner=true \ +; RUN: -stop-after machine-combiner < %s | FileCheck %s + +define double @test_reassoc_fadd1(double %a0, double %a1, double %a2, double %a3) { + ; CHECK-LABEL: name: test_reassoc_fadd1 + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $f10_d, $f11_d, $f12_d, $f13_d + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f13_d + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f12_d + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $f11_d + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fpr64 = COPY $f10_d + ; CHECK-NEXT: %4:fpr64 = nsz reassoc nofpexcept FADD_D [[COPY3]], [[COPY2]], 7, implicit $frm + ; CHECK-NEXT: %9:fpr64 = nsz reassoc nofpexcept FADD_D [[COPY1]], [[COPY]], 7, implicit $frm + ; CHECK-NEXT: %6:fpr64 = nsz reassoc nofpexcept FADD_D killed %4, killed %9, 7, implicit $frm + ; CHECK-NEXT: $f10_d = COPY %6 + ; CHECK-NEXT: PseudoRET implicit $f10_d + %t0 = fadd nsz reassoc double %a0, %a1 + %t1 = fadd nsz reassoc double %t0, %a2 + %t2 = fadd nsz reassoc double %t1, %a3 + ret double %t2 +} + +define double @test_reassoc_fmul1(double %a0, double %a1, double %a2, double %a3) { + ; CHECK-LABEL: name: test_reassoc_fmul1 + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $f10_d, $f11_d, $f12_d, $f13_d + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f13_d + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f12_d + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $f11_d + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fpr64 = COPY $f10_d + ; CHECK-NEXT: %4:fpr64 = nsz reassoc nofpexcept FMUL_D [[COPY3]], [[COPY2]], 7, implicit $frm + ; CHECK-NEXT: %9:fpr64 = nsz reassoc nofpexcept FMUL_D [[COPY1]], [[COPY]], 7, implicit $frm + ; CHECK-NEXT: %6:fpr64 = nsz reassoc nofpexcept FMUL_D killed %4, killed %9, 7, implicit $frm + ; CHECK-NEXT: $f10_d = COPY %6 + ; CHECK-NEXT: PseudoRET implicit $f10_d + %t0 = fmul nsz reassoc double %a0, %a1 + %t1 = fmul nsz reassoc double %t0, %a2 + %t2 = fmul nsz reassoc double %t1, %a3 + ret double %t2 +} + +; Verify flags intersection +define double @test_reassoc_flags1(double %a0, double %a1, double %a2, double %a3) { + ; CHECK-LABEL: name: test_reassoc_flags1 + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $f10_d, $f11_d, $f12_d, $f13_d + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f13_d + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f12_d + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $f11_d + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fpr64 = COPY $f10_d + ; CHECK-NEXT: %4:fpr64 = nsz reassoc nofpexcept FADD_D [[COPY3]], [[COPY2]], 7, implicit $frm + ; CHECK-NEXT: %9:fpr64 = nsz reassoc nofpexcept FADD_D [[COPY1]], [[COPY]], 7, implicit $frm + ; CHECK-NEXT: %6:fpr64 = nsz reassoc nofpexcept FADD_D killed %4, killed %9, 7, implicit $frm + ; CHECK-NEXT: $f10_d = COPY %6 + ; CHECK-NEXT: PseudoRET implicit $f10_d + %t0 = fadd nsz reassoc double %a0, %a1 + %t1 = fadd contract nsz reassoc double %t0, %a2 + %t2 = fadd nsz reassoc double %t1, %a3 + ret double %t2 +} + +; Verify flags intersection +define double @test_reassoc_flags2(double %a0, double %a1, double %a2, double %a3) { + ; CHECK-LABEL: name: test_reassoc_flags2 + ; CHECK: bb.0 (%ir-block.0): + ; CHECK-NEXT: liveins: $f10_d, $f11_d, $f12_d, $f13_d + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f13_d + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f12_d + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $f11_d + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:fpr64 = COPY $f10_d + ; CHECK-NEXT: %4:fpr64 = nsz reassoc nofpexcept FADD_D [[COPY3]], [[COPY2]], 7, implicit $frm + ; CHECK-NEXT: %9:fpr64 = nsz contract reassoc nofpexcept FADD_D [[COPY1]], [[COPY]], 7, implicit $frm + ; CHECK-NEXT: %6:fpr64 = nsz contract reassoc nofpexcept FADD_D killed %4, killed %9, 7, implicit $frm + ; CHECK-NEXT: $f10_d = COPY %6 + ; CHECK-NEXT: PseudoRET implicit $f10_d + %t0 = fadd nsz reassoc double %a0, %a1 + %t1 = fadd contract nsz reassoc double %t0, %a2 + %t2 = fadd contract nsz reassoc double %t1, %a3 + ret double %t2 +} + 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,13 +1,14 @@ ; 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 +; RUN: -O3 -enable-unsafe-fp-math -riscv-enable-machine-combiner=true < %s | \ +; RUN: FileCheck %s 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: fadd.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 @@ -19,8 +20,8 @@ ; 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: fadd.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 %a2, %t0 @@ -32,8 +33,8 @@ ; 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: fadd.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 @@ -45,8 +46,8 @@ ; 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: fadd.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 %a2, %t0 @@ -58,8 +59,8 @@ ; 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: fmul.d ft1, fa2, fa3 +; CHECK-NEXT: fmul.d fa0, ft0, ft1 ; CHECK-NEXT: ret %t0 = fmul nsz reassoc double %a0, %a1 %t1 = fmul nsz reassoc double %t0, %a2 @@ -71,8 +72,8 @@ ; 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: fmul.d ft1, fa2, fa3 +; CHECK-NEXT: fmul.d fa0, ft0, ft1 ; CHECK-NEXT: ret %t0 = fmul nsz reassoc double %a0, %a1 %t1 = fmul nsz reassoc double %a2, %t0 @@ -84,8 +85,8 @@ ; 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: fmul.d ft1, fa2, fa3 +; CHECK-NEXT: fmul.d fa0, ft0, ft1 ; CHECK-NEXT: ret %t0 = fmul nsz reassoc double %a0, %a1 %t1 = fmul nsz reassoc double %t0, %a2 @@ -97,8 +98,8 @@ ; 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: fmul.d ft1, fa2, fa3 +; CHECK-NEXT: fmul.d fa0, ft0, ft1 ; CHECK-NEXT: ret %t0 = fmul nsz reassoc double %a0, %a1 %t1 = fmul nsz reassoc double %a2, %t0 @@ -110,11 +111,11 @@ ; 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: fadd.d ft1, fa2, fa3 +; CHECK-NEXT: fadd.d ft2, fa4, fa5 +; CHECK-NEXT: fadd.d ft0, ft0, ft1 +; CHECK-NEXT: fadd.d ft1, ft2, fa6 +; CHECK-NEXT: fadd.d fa0, ft0, ft1 ; CHECK-NEXT: ret %t0 = fadd nsz reassoc double %a0, %a1 %t1 = fadd nsz reassoc double %t0, %a2 @@ -129,14 +130,14 @@ ; 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: 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, ft0, ft1 +; 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 @@ -156,6 +157,7 @@ ret double %t8 } +; Negative test define double @test_reassoc_fadd_flags_1(double %a0, double %a1, double %a2, double %a3) { ; CHECK-LABEL: test_reassoc_fadd_flags_1: ; CHECK: # %bb.0: @@ -169,6 +171,7 @@ ret double %t2 } +; Negative test define double @test_reassoc_fadd_flags_2(double %a0, double %a1, double %a2, double %a3) { ; CHECK-LABEL: test_reassoc_fadd_flags_2: ; CHECK: # %bb.0: