60 #define DEBUG_TYPE "ppc-vsx-swaps"
70 struct PPCVSXSwapEntry {
78 unsigned int IsLoad : 1;
79 unsigned int IsStore : 1;
80 unsigned int IsSwap : 1;
81 unsigned int MentionsPhysVR : 1;
82 unsigned int IsSwappable : 1;
83 unsigned int MentionsPartialVR : 1;
84 unsigned int SpecialHandling : 3;
85 unsigned int WebRejected : 1;
86 unsigned int WillRemove : 1;
108 std::vector<PPCVSXSwapEntry> SwapVector;
128 bool gatherVectorInstructions();
137 unsigned lookThruCopyLike(
unsigned SrcReg,
unsigned VecIdx);
143 void recordUnoptimizableWebs();
146 void markSwapsForRemoval();
155 unsigned DstReg,
unsigned SrcReg);
158 void handleSpecialSwappables(
int EntryIdx);
161 void dumpSwapVector();
172 return (isRegInClass(Reg, &PPC::VSRCRegClass) ||
173 isRegInClass(Reg, &PPC::VRRCRegClass));
177 bool isScalarVecReg(
unsigned Reg) {
178 return (isRegInClass(Reg, &PPC::VSFRCRegClass) ||
179 isRegInClass(Reg, &PPC::VSSRCRegClass));
185 bool isAnyVecReg(
unsigned Reg,
bool &Partial) {
186 if (isScalarVecReg(Reg))
188 return isScalarVecReg(Reg) ||
isVecReg(Reg);
202 bool Changed =
false;
205 if (gatherVectorInstructions()) {
207 recordUnoptimizableWebs();
208 markSwapsForRemoval();
209 Changed = removeSwaps();
230 const int InitialVectorSize(256);
232 SwapVector.reserve(InitialVectorSize);
243 bool PPCVSXSwapRemoval::gatherVectorInstructions() {
244 bool RelevantFunction =
false;
249 if (
MI.isDebugValue())
252 bool RelevantInstr =
false;
253 bool Partial =
false;
258 unsigned Reg = MO.getReg();
259 if (isAnyVecReg(Reg, Partial)) {
260 RelevantInstr =
true;
268 RelevantFunction =
true;
273 PPCVSXSwapEntry SwapEntry{};
274 int VecIdx = addSwapEntry(&
MI, SwapEntry);
276 switch(
MI.getOpcode()) {
285 SwapVector[VecIdx].MentionsPartialVR = 1;
287 SwapVector[VecIdx].IsSwappable = 1;
289 case PPC::XXPERMDI: {
297 int immed =
MI.getOperand(3).getImm();
299 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
301 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
303 if (trueReg1 == trueReg2)
304 SwapVector[VecIdx].IsSwap = 1;
308 SwapVector[VecIdx].IsSwappable = 1;
309 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
319 }
else if (immed == 0 || immed == 3) {
321 SwapVector[VecIdx].IsSwappable = 1;
322 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
324 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
326 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
328 if (trueReg1 == trueReg2)
329 SwapVector[VecIdx].MentionsPhysVR = 0;
333 SwapVector[VecIdx].IsSwappable = 1;
334 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
343 SwapVector[VecIdx].IsLoad = 1;
349 SwapVector[VecIdx].IsLoad = 1;
350 SwapVector[VecIdx].IsSwap = 1;
358 SwapVector[VecIdx].IsLoad = 1;
359 SwapVector[VecIdx].IsSwappable = 1;
366 SwapVector[VecIdx].IsStore = 1;
372 SwapVector[VecIdx].IsStore = 1;
373 SwapVector[VecIdx].IsSwap = 1;
380 SwapVector[VecIdx].IsSwappable = 1;
385 else if (isScalarVecReg(
MI.getOperand(0).getReg()) &&
386 isScalarVecReg(
MI.getOperand(1).getReg()))
387 SwapVector[VecIdx].IsSwappable = 1;
389 case PPC::SUBREG_TO_REG: {
399 SwapVector[VecIdx].IsSwappable = 1;
400 else if (
isVecReg(
MI.getOperand(0).getReg()) &&
401 isScalarVecReg(
MI.getOperand(2).getReg())) {
402 SwapVector[VecIdx].IsSwappable = 1;
403 SwapVector[VecIdx].SpecialHandling = SHValues::SH_COPYWIDEN;
413 SwapVector[VecIdx].IsSwappable = 1;
414 SwapVector[VecIdx].SpecialHandling = SHValues::SH_SPLAT;
425 case PPC::EXTRACT_SUBREG:
426 case PPC::INSERT_SUBREG:
427 case PPC::COPY_TO_REGCLASS:
447 case PPC::VCIPHERLAST:
467 case PPC::VNCIPHERLAST:
492 case PPC::VSHASIGMAD:
493 case PPC::VSHASIGMAW:
523 if (RelevantFunction) {
524 DEBUG(
dbgs() <<
"Swap vector when first built\n\n");
528 return RelevantFunction;
534 PPCVSXSwapEntry& SwapEntry) {
535 SwapEntry.VSEMI =
MI;
536 SwapEntry.VSEId = SwapVector.size();
537 SwapVector.push_back(SwapEntry);
538 EC->insert(SwapEntry.VSEId);
539 SwapMap[
MI] = SwapEntry.VSEId;
540 return SwapEntry.VSEId;
552 unsigned PPCVSXSwapRemoval::lookThruCopyLike(
unsigned SrcReg,
567 if (!isScalarVecReg(CopySrcReg))
568 SwapVector[VecIdx].MentionsPhysVR = 1;
572 return lookThruCopyLike(CopySrcReg, VecIdx);
582 void PPCVSXSwapRemoval::formWebs() {
584 DEBUG(
dbgs() <<
"\n*** Forming webs for swap removal ***\n\n");
586 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
590 DEBUG(
dbgs() <<
"\n" << SwapVector[EntryIdx].VSEId <<
" ");
601 unsigned Reg = MO.getReg();
602 if (!
isVecReg(Reg) && !isScalarVecReg(Reg))
606 if (!(MI->
isCopy() && isScalarVecReg(Reg)))
607 SwapVector[EntryIdx].MentionsPhysVR = 1;
615 assert(SwapMap.find(DefMI) != SwapMap.end() &&
616 "Inconsistency: def of vector reg not found in swap map!");
617 int DefIdx = SwapMap[DefMI];
618 (void)
EC->unionSets(SwapVector[DefIdx].VSEId,
619 SwapVector[EntryIdx].VSEId);
621 DEBUG(
dbgs() <<
format(
"Unioning %d with %d\n", SwapVector[DefIdx].VSEId,
622 SwapVector[EntryIdx].VSEId));
633 void PPCVSXSwapRemoval::recordUnoptimizableWebs() {
635 DEBUG(
dbgs() <<
"\n*** Rejecting webs for swap removal ***\n\n");
637 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
638 int Repr =
EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
641 if (SwapVector[Repr].WebRejected)
647 if (SwapVector[EntryIdx].MentionsPhysVR ||
648 SwapVector[EntryIdx].MentionsPartialVR ||
649 !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) {
651 SwapVector[Repr].WebRejected = 1;
654 format(
"Web %d rejected for physreg, partial reg, or not "
655 "swap[pable]\n", Repr));
656 DEBUG(
dbgs() <<
" in " << EntryIdx <<
": ");
657 DEBUG(SwapVector[EntryIdx].VSEMI->dump());
663 else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
672 int UseIdx = SwapMap[&
UseMI];
674 if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad ||
675 SwapVector[UseIdx].IsStore) {
677 SwapVector[Repr].WebRejected = 1;
680 format(
"Web %d rejected for load not feeding swap\n", Repr));
681 DEBUG(
dbgs() <<
" def " << EntryIdx <<
": ");
683 DEBUG(
dbgs() <<
" use " << UseIdx <<
": ");
691 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
696 int DefIdx = SwapMap[DefMI];
698 if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad ||
699 SwapVector[DefIdx].IsStore) {
701 SwapVector[Repr].WebRejected = 1;
704 format(
"Web %d rejected for store not fed by swap\n", Repr));
705 DEBUG(
dbgs() <<
" def " << DefIdx <<
": ");
707 DEBUG(
dbgs() <<
" use " << EntryIdx <<
": ");
715 int UseIdx = SwapMap[&
UseMI];
717 if (SwapVector[UseIdx].VSEMI->getOpcode() != MI->
getOpcode()) {
718 SwapVector[Repr].WebRejected = 1;
721 format(
"Web %d rejected for swap not feeding only stores\n",
725 DEBUG(
dbgs() <<
" use " << UseIdx <<
": ");
726 DEBUG(SwapVector[UseIdx].VSEMI->dump());
733 DEBUG(
dbgs() <<
"Swap vector after web analysis:\n\n");
742 void PPCVSXSwapRemoval::markSwapsForRemoval() {
744 DEBUG(
dbgs() <<
"\n*** Marking swaps for removal ***\n\n");
746 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
748 if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
749 int Repr =
EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
751 if (!SwapVector[Repr].WebRejected) {
756 int UseIdx = SwapMap[&
UseMI];
757 SwapVector[UseIdx].WillRemove = 1;
759 DEBUG(
dbgs() <<
"Marking swap fed by load for removal: ");
764 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
765 int Repr =
EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
767 if (!SwapVector[Repr].WebRejected) {
771 int DefIdx = SwapMap[DefMI];
772 SwapVector[DefIdx].WillRemove = 1;
774 DEBUG(
dbgs() <<
"Marking swap feeding store for removal: ");
778 }
else if (SwapVector[EntryIdx].IsSwappable &&
779 SwapVector[EntryIdx].SpecialHandling != 0) {
780 int Repr =
EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
782 if (!SwapVector[Repr].WebRejected)
783 handleSpecialSwappables(EntryIdx);
795 unsigned DstReg,
unsigned SrcReg) {
797 TII->get(PPC::XXPERMDI), DstReg)
808 void PPCVSXSwapRemoval::handleSpecialSwappables(
int EntryIdx) {
809 switch (SwapVector[EntryIdx].SpecialHandling) {
816 case SHValues::SH_SPLAT: {
826 case PPC::VSPLTB: NElts = 16;
break;
827 case PPC::VSPLTH: NElts = 8;
break;
829 case PPC::XXSPLTW: NElts = 4;
break;
838 EltNo = (EltNo + NElts / 2) % NElts;
855 case SHValues::SH_XXPERMDI: {
862 if (Selector == 0 || Selector == 3)
863 Selector = 3 - Selector;
879 case SHValues::SH_COPYWIDEN: {
882 DEBUG(
dbgs() <<
"Changing SUBREG_TO_REG: ");
887 unsigned NewVReg =
MRI->createVirtualRegister(DstRC);
900 if (DstRC == &PPC::VRRCRegClass) {
901 unsigned VSRCTmp1 =
MRI->createVirtualRegister(&PPC::VSRCRegClass);
902 unsigned VSRCTmp2 =
MRI->createVirtualRegister(&PPC::VSRCRegClass);
905 TII->get(PPC::COPY), VSRCTmp1)
909 insertSwap(MI, InsertPoint, VSRCTmp2, VSRCTmp1);
913 TII->get(PPC::COPY), DstReg)
918 insertSwap(MI, InsertPoint, DstReg, NewVReg);
928 bool PPCVSXSwapRemoval::removeSwaps() {
930 DEBUG(
dbgs() <<
"\n*** Removing swaps ***\n\n");
932 bool Changed =
false;
934 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
935 if (SwapVector[EntryIdx].WillRemove) {
944 SwapVector[EntryIdx].VSEId));
955 void PPCVSXSwapRemoval::dumpSwapVector() {
957 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
960 int ID = SwapVector[EntryIdx].VSEId;
968 if (SwapVector[EntryIdx].IsLoad)
970 if (SwapVector[EntryIdx].IsStore)
972 if (SwapVector[EntryIdx].IsSwap)
974 if (SwapVector[EntryIdx].MentionsPhysVR)
976 if (SwapVector[EntryIdx].MentionsPartialVR)
979 if (SwapVector[EntryIdx].IsSwappable) {
981 switch(SwapVector[EntryIdx].SpecialHandling) {
1011 if (SwapVector[EntryIdx].WebRejected)
1013 if (SwapVector[EntryIdx].WillRemove)
1029 "PowerPC VSX Swap Removal",
false,
false)
1033 char PPCVSXSwapRemoval::ID = 0;
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
FunctionPass * createPPCVSXSwapRemovalPass()
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
MachineInstrBundleIterator< MachineInstr > iterator
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< mop_iterator > operands()
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
Reg
All possible values of the reg field in the ModR/M byte.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
INLINEASM - Represents an inline asm block.
bool isCopyLike() const
Return true if the instruction behaves like a copy.
CHAIN = STXVD2X CHAIN, VSRC, Ptr - Occurs only for little endian.
void initializePPCVSXSwapRemovalPass(PassRegistry &)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
VSRC, CHAIN = LXVD2X_LE CHAIN, Ptr - Occurs only for little endian.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
const MachineOperand & getOperand(unsigned i) const
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
static bool isVecReg(unsigned Reg)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineOperand class - Representation of each machine instruction operand.
void dump(const TargetInstrInfo *TII=nullptr) const
VPERM - The PPC VPERM Instruction.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
initialize - Initialize the set of available library functions based on the specified target triple...
bool isSubregToReg() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static unsigned UseReg(const MachineOperand &MO)
void setReg(unsigned Reg)
Change the register this operand corresponds to.
unsigned getReg() const
getReg - Returns the register number.
INITIALIZE_PASS_BEGIN(PPCVSXSwapRemoval, DEBUG_TYPE,"PowerPC VSX Swap Removal", false, false) INITIALIZE_PASS_END(PPCVSXSwapRemoval
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.