diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 99dba8d41ac88b..eceabe18154c8e 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -7165,6 +7165,52 @@ static bool shouldPreventUndefRegUpdateMemFold(MachineFunction &MF, return VRegDef && VRegDef->isImplicitDef(); } +unsigned X86InstrInfo::commuteOperandsForFold(MachineInstr &MI, + unsigned Idx1) const { + unsigned Idx2 = CommuteAnyOperandIndex; + if (!findCommutedOpIndices(MI, Idx1, Idx2)) + return Idx1; + + bool HasDef = MI.getDesc().getNumDefs(); + Register Reg0 = HasDef ? MI.getOperand(0).getReg() : Register(); + Register Reg1 = MI.getOperand(Idx1).getReg(); + Register Reg2 = MI.getOperand(Idx2).getReg(); + bool Tied1 = 0 == MI.getDesc().getOperandConstraint(Idx1, MCOI::TIED_TO); + bool Tied2 = 0 == MI.getDesc().getOperandConstraint(Idx2, MCOI::TIED_TO); + + // If either of the commutable operands are tied to the destination + // then we can not commute + fold. + if ((HasDef && Reg0 == Reg1 && Tied1) || (HasDef && Reg0 == Reg2 && Tied2)) + return Idx1; + + MachineInstr *CommutedMI = commuteInstruction(MI, false, Idx1, Idx2); + if (!CommutedMI) { + // Unable to commute. + return Idx1; + } + if (CommutedMI != &MI) { + // New instruction. We can't fold from this. + CommutedMI->eraseFromParent(); + return Idx1; + } + + return Idx2; +} + +void X86InstrInfo::UndoCommuteForFold(MachineInstr &MI, unsigned Idx1, + unsigned Idx2) const { + // Folding failed again - undo the commute before returning. + MachineInstr *UncommutedMI = commuteInstruction(MI, false, Idx1, Idx2); + // New instruction. It doesn't need to be kept. + if (UncommutedMI && UncommutedMI != &MI) + UncommutedMI->eraseFromParent(); +} + +static void printFailMsgforFold(const MachineInstr &MI, unsigned Idx) { + if (PrintFailedFusing && !MI.isCopy()) + dbgs() << "We failed to fuse operand " << Idx << " in " << MI; +} + MachineInstr *X86InstrInfo::foldMemoryOperandImpl( MachineFunction &MF, MachineInstr &MI, unsigned OpNum, ArrayRef MOs, MachineBasicBlock::iterator InsertPt, @@ -7292,65 +7338,23 @@ MachineInstr *X86InstrInfo::foldMemoryOperandImpl( return NewMI; } - // If the instruction and target operand are commutable, commute the - // instruction and try again. if (AllowCommute) { - unsigned CommuteOpIdx1 = OpNum, CommuteOpIdx2 = CommuteAnyOperandIndex; - if (findCommutedOpIndices(MI, CommuteOpIdx1, CommuteOpIdx2)) { - bool HasDef = MI.getDesc().getNumDefs(); - Register Reg0 = HasDef ? MI.getOperand(0).getReg() : Register(); - Register Reg1 = MI.getOperand(CommuteOpIdx1).getReg(); - Register Reg2 = MI.getOperand(CommuteOpIdx2).getReg(); - bool Tied1 = - 0 == MI.getDesc().getOperandConstraint(CommuteOpIdx1, MCOI::TIED_TO); - bool Tied2 = - 0 == MI.getDesc().getOperandConstraint(CommuteOpIdx2, MCOI::TIED_TO); - - // If either of the commutable operands are tied to the destination - // then we can not commute + fold. - if ((HasDef && Reg0 == Reg1 && Tied1) || - (HasDef && Reg0 == Reg2 && Tied2)) - return nullptr; - - MachineInstr *CommutedMI = - commuteInstruction(MI, false, CommuteOpIdx1, CommuteOpIdx2); - if (!CommutedMI) { - // Unable to commute. - return nullptr; - } - if (CommutedMI != &MI) { - // New instruction. We can't fold from this. - CommutedMI->eraseFromParent(); - return nullptr; - } - - // Attempt to fold with the commuted version of the instruction. - NewMI = foldMemoryOperandImpl(MF, MI, CommuteOpIdx2, MOs, InsertPt, Size, - Alignment, /*AllowCommute=*/false); - if (NewMI) - return NewMI; - - // Folding failed again - undo the commute before returning. - MachineInstr *UncommutedMI = - commuteInstruction(MI, false, CommuteOpIdx1, CommuteOpIdx2); - if (!UncommutedMI) { - // Unable to commute. - return nullptr; - } - if (UncommutedMI != &MI) { - // New instruction. It doesn't need to be kept. - UncommutedMI->eraseFromParent(); - return nullptr; - } - - // Return here to prevent duplicate fuse failure report. + // If the instruction and target operand are commutable, commute the + // instruction and try again. + unsigned CommuteOpIdx2 = commuteOperandsForFold(MI, OpNum); + if (CommuteOpIdx2 == OpNum) { + printFailMsgforFold(MI, OpNum); return nullptr; } + // Attempt to fold with the commuted version of the instruction. + NewMI = foldMemoryOperandImpl(MF, MI, CommuteOpIdx2, MOs, InsertPt, Size, + Alignment, /*AllowCommute=*/false); + if (NewMI) + return NewMI; + UndoCommuteForFold(MI, OpNum, CommuteOpIdx2); } - // No fusion - if (PrintFailedFusing && !MI.isCopy()) - dbgs() << "We failed to fuse operand " << OpNum << " in " << MI; + printFailMsgforFold(MI, OpNum); return nullptr; } diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h index 0cb69050656109..8512635eadaed5 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -685,8 +685,10 @@ class X86InstrInfo final : public X86GenInstrInfo { Register SrcReg2, int64_t ImmMask, int64_t ImmValue, const MachineInstr &OI, bool *IsSwapped, int64_t *ImmDelta) const; -}; + unsigned commuteOperandsForFold(MachineInstr &MI, unsigned Idx1) const; + void UndoCommuteForFold(MachineInstr &MI, unsigned Idx1, unsigned Idx2) const; +}; } // namespace llvm #endif