Skip to content

Commit

Permalink
[X86][NFC] Extract code for commute in foldMemoryOperandImpl into fun…
Browse files Browse the repository at this point in the history
…ctions

To share code for folding broadcast in #79761
  • Loading branch information
KanRobert committed Jan 30, 2024
1 parent b23e518 commit 2960656
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 55 deletions.
112 changes: 58 additions & 54 deletions llvm/lib/Target/X86/X86InstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MachineOperand> MOs, MachineBasicBlock::iterator InsertPt,
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/X86/X86InstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

This comment has been minimized.

Copy link
@RKSimon

RKSimon Jan 31, 2024

Collaborator

Please can you add documentation for these methods?

This comment has been minimized.

Copy link
@KanRobert

KanRobert Jan 31, 2024

Author Contributor

Done 150ab99

void UndoCommuteForFold(MachineInstr &MI, unsigned Idx1, unsigned Idx2) const;
};
} // namespace llvm

#endif

0 comments on commit 2960656

Please sign in to comment.