54 #include "llvm/Config/llvm-config.h" 61 #define DEBUG_TYPE "ppc-vsx-swaps" 71 struct PPCVSXSwapEntry {
79 unsigned int IsLoad : 1;
80 unsigned int IsStore : 1;
81 unsigned int IsSwap : 1;
82 unsigned int MentionsPhysVR : 1;
83 unsigned int IsSwappable : 1;
84 unsigned int MentionsPartialVR : 1;
85 unsigned int SpecialHandling : 3;
86 unsigned int WebRejected : 1;
87 unsigned int WillRemove : 1;
109 std::vector<PPCVSXSwapEntry> SwapVector;
129 bool gatherVectorInstructions();
138 unsigned lookThruCopyLike(
unsigned SrcReg,
unsigned VecIdx);
144 void recordUnoptimizableWebs();
147 void markSwapsForRemoval();
156 unsigned DstReg,
unsigned SrcReg);
159 void handleSpecialSwappables(
int EntryIdx);
162 void dumpSwapVector();
173 return (isRegInClass(Reg, &PPC::VSRCRegClass) ||
174 isRegInClass(Reg, &PPC::VRRCRegClass));
178 bool isScalarVecReg(
unsigned Reg) {
179 return (isRegInClass(Reg, &PPC::VSFRCRegClass) ||
180 isRegInClass(Reg, &PPC::VSSRCRegClass));
186 bool isAnyVecReg(
unsigned Reg,
bool &Partial) {
187 if (isScalarVecReg(Reg))
189 return isScalarVecReg(Reg) ||
isVecReg(Reg);
205 bool Changed =
false;
208 if (gatherVectorInstructions()) {
210 recordUnoptimizableWebs();
211 markSwapsForRemoval();
212 Changed = removeSwaps();
226 MRI = &MF->getRegInfo();
233 const int InitialVectorSize(256);
235 SwapVector.reserve(InitialVectorSize);
246 bool PPCVSXSwapRemoval::gatherVectorInstructions() {
247 bool RelevantFunction =
false;
252 if (
MI.isDebugInstr())
255 bool RelevantInstr =
false;
256 bool Partial =
false;
261 unsigned Reg = MO.getReg();
262 if (isAnyVecReg(Reg, Partial)) {
263 RelevantInstr =
true;
271 RelevantFunction =
true;
276 PPCVSXSwapEntry SwapEntry{};
277 int VecIdx = addSwapEntry(&
MI, SwapEntry);
279 switch(
MI.getOpcode()) {
288 SwapVector[VecIdx].MentionsPartialVR = 1;
290 SwapVector[VecIdx].IsSwappable = 1;
300 int immed =
MI.getOperand(3).getImm();
302 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
304 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
306 if (trueReg1 == trueReg2)
307 SwapVector[VecIdx].IsSwap = 1;
311 SwapVector[VecIdx].IsSwappable = 1;
312 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
322 }
else if (immed == 0 || immed == 3) {
324 SwapVector[VecIdx].IsSwappable = 1;
325 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
327 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
329 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
331 if (trueReg1 == trueReg2)
332 SwapVector[VecIdx].MentionsPhysVR = 0;
336 SwapVector[VecIdx].IsSwappable = 1;
337 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
346 SwapVector[VecIdx].IsLoad = 1;
352 SwapVector[VecIdx].IsLoad = 1;
353 SwapVector[VecIdx].IsSwap = 1;
363 SwapVector[VecIdx].IsLoad = 1;
364 SwapVector[VecIdx].IsSwappable = 1;
371 SwapVector[VecIdx].IsStore = 1;
377 SwapVector[VecIdx].IsStore = 1;
378 SwapVector[VecIdx].IsSwap = 1;
385 SwapVector[VecIdx].IsSwappable = 1;
390 else if (isScalarVecReg(
MI.getOperand(0).getReg()) &&
391 isScalarVecReg(
MI.getOperand(1).getReg()))
392 SwapVector[VecIdx].IsSwappable = 1;
394 case PPC::SUBREG_TO_REG: {
404 SwapVector[VecIdx].IsSwappable = 1;
405 else if (
isVecReg(
MI.getOperand(0).getReg()) &&
406 isScalarVecReg(
MI.getOperand(2).getReg())) {
407 SwapVector[VecIdx].IsSwappable = 1;
408 SwapVector[VecIdx].SpecialHandling = SHValues::SH_COPYWIDEN;
418 SwapVector[VecIdx].IsSwappable = 1;
419 SwapVector[VecIdx].SpecialHandling = SHValues::SH_SPLAT;
430 case PPC::EXTRACT_SUBREG:
431 case PPC::INSERT_SUBREG:
432 case PPC::COPY_TO_REGCLASS:
452 case PPC::VCIPHERLAST:
472 case PPC::VNCIPHERLAST:
497 case PPC::VSHASIGMAD:
498 case PPC::VSHASIGMAW:
530 if (RelevantFunction) {
535 return RelevantFunction;
541 PPCVSXSwapEntry& SwapEntry) {
542 SwapEntry.VSEMI =
MI;
543 SwapEntry.VSEId = SwapVector.size();
544 SwapVector.push_back(SwapEntry);
545 EC->insert(SwapEntry.VSEId);
546 SwapMap[
MI] = SwapEntry.VSEId;
547 return SwapEntry.VSEId;
559 unsigned PPCVSXSwapRemoval::lookThruCopyLike(
unsigned SrcReg,
574 if (!isScalarVecReg(CopySrcReg))
575 SwapVector[VecIdx].MentionsPhysVR = 1;
579 return lookThruCopyLike(CopySrcReg, VecIdx);
589 void PPCVSXSwapRemoval::formWebs() {
591 LLVM_DEBUG(
dbgs() <<
"\n*** Forming webs for swap removal ***\n\n");
593 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
608 unsigned Reg = MO.getReg();
609 if (!
isVecReg(Reg) && !isScalarVecReg(Reg))
613 if (!(MI->
isCopy() && isScalarVecReg(Reg)))
614 SwapVector[EntryIdx].MentionsPhysVR = 1;
622 assert(SwapMap.find(DefMI) != SwapMap.end() &&
623 "Inconsistency: def of vector reg not found in swap map!");
624 int DefIdx = SwapMap[
DefMI];
625 (void)EC->unionSets(SwapVector[DefIdx].VSEId,
626 SwapVector[EntryIdx].VSEId);
629 SwapVector[DefIdx].VSEId,
630 SwapVector[EntryIdx].VSEId));
641 void PPCVSXSwapRemoval::recordUnoptimizableWebs() {
643 LLVM_DEBUG(
dbgs() <<
"\n*** Rejecting webs for swap removal ***\n\n");
645 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
646 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
649 if (SwapVector[Repr].WebRejected)
655 if (SwapVector[EntryIdx].MentionsPhysVR ||
656 SwapVector[EntryIdx].MentionsPartialVR ||
657 !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) {
659 SwapVector[Repr].WebRejected = 1;
662 dbgs() <<
format(
"Web %d rejected for physreg, partial reg, or not " 666 LLVM_DEBUG(SwapVector[EntryIdx].VSEMI->dump());
672 else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
681 int UseIdx = SwapMap[&
UseMI];
683 if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad ||
684 SwapVector[UseIdx].IsStore) {
686 SwapVector[Repr].WebRejected = 1;
689 "Web %d rejected for load not feeding swap\n", Repr));
700 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
705 int DefIdx = SwapMap[
DefMI];
707 if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad ||
708 SwapVector[DefIdx].IsStore) {
710 SwapVector[Repr].WebRejected = 1;
713 "Web %d rejected for store not fed by swap\n", Repr));
724 int UseIdx = SwapMap[&
UseMI];
726 if (SwapVector[UseIdx].VSEMI->getOpcode() != MI->
getOpcode()) {
727 SwapVector[Repr].WebRejected = 1;
731 "Web %d rejected for swap not feeding only stores\n", Repr));
752 void PPCVSXSwapRemoval::markSwapsForRemoval() {
756 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
758 if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
759 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
761 if (!SwapVector[Repr].WebRejected) {
766 int UseIdx = SwapMap[&
UseMI];
767 SwapVector[UseIdx].WillRemove = 1;
774 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
775 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
777 if (!SwapVector[Repr].WebRejected) {
781 int DefIdx = SwapMap[
DefMI];
782 SwapVector[DefIdx].WillRemove = 1;
788 }
else if (SwapVector[EntryIdx].IsSwappable &&
789 SwapVector[EntryIdx].SpecialHandling != 0) {
790 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
792 if (!SwapVector[Repr].WebRejected)
793 handleSpecialSwappables(EntryIdx);
805 unsigned DstReg,
unsigned SrcReg) {
818 void PPCVSXSwapRemoval::handleSpecialSwappables(
int EntryIdx) {
819 switch (SwapVector[EntryIdx].SpecialHandling) {
826 case SHValues::SH_SPLAT: {
836 case PPC::VSPLTB: NElts = 16;
break;
837 case PPC::VSPLTH: NElts = 8;
break;
839 case PPC::XXSPLTW: NElts = 4;
break;
848 EltNo = (EltNo + NElts / 2) % NElts;
865 case SHValues::SH_XXPERMDI: {
872 if (Selector == 0 || Selector == 3)
873 Selector = 3 - Selector;
895 case SHValues::SH_COPYWIDEN: {
903 unsigned NewVReg =
MRI->createVirtualRegister(DstRC);
916 if (DstRC == &PPC::VRRCRegClass) {
917 unsigned VSRCTmp1 =
MRI->createVirtualRegister(&PPC::VSRCRegClass);
918 unsigned VSRCTmp2 =
MRI->createVirtualRegister(&PPC::VSRCRegClass);
921 TII->get(PPC::COPY), VSRCTmp1)
925 insertSwap(MI, InsertPoint, VSRCTmp2, VSRCTmp1);
929 TII->get(PPC::COPY), DstReg)
934 insertSwap(MI, InsertPoint, DstReg, NewVReg);
944 bool PPCVSXSwapRemoval::removeSwaps() {
948 bool Changed =
false;
950 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
951 if (SwapVector[EntryIdx].WillRemove) {
960 SwapVector[EntryIdx].VSEId));
970 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 974 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
977 int ID = SwapVector[EntryIdx].VSEId;
980 dbgs() <<
format(
"%6d", EC->getLeaderValue(ID));
984 if (SwapVector[EntryIdx].IsLoad)
986 if (SwapVector[EntryIdx].IsStore)
988 if (SwapVector[EntryIdx].IsSwap)
990 if (SwapVector[EntryIdx].MentionsPhysVR)
991 dbgs() <<
"physreg ";
992 if (SwapVector[EntryIdx].MentionsPartialVR)
993 dbgs() <<
"partialreg ";
995 if (SwapVector[EntryIdx].IsSwappable) {
996 dbgs() <<
"swappable ";
997 switch(SwapVector[EntryIdx].SpecialHandling) {
999 dbgs() <<
"special:**unknown**";
1004 dbgs() <<
"special:extract ";
1007 dbgs() <<
"special:insert ";
1010 dbgs() <<
"special:load ";
1013 dbgs() <<
"special:store ";
1016 dbgs() <<
"special:splat ";
1019 dbgs() <<
"special:xxpermdi ";
1022 dbgs() <<
"special:copywiden ";
1027 if (SwapVector[EntryIdx].WebRejected)
1028 dbgs() <<
"rejected ";
1029 if (SwapVector[EntryIdx].WillRemove)
1030 dbgs() <<
"remove ";
1046 "PowerPC VSX Swap Removal",
false,
false)
1050 char PPCVSXSwapRemoval::
ID = 0;
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
bool contains(unsigned Reg) const
Return true if the specified register is included in this register class.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
This class represents lattice values for constants.
FunctionPass * createPPCVSXSwapRemovalPass()
bool isSubregToReg() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
iterator_range< mop_iterator > operands()
bool isCopyLike() const
Return true if the instruction behaves like a copy.
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.
INITIALIZE_PASS_BEGIN(PPCVSXSwapRemoval, DEBUG_TYPE, "PowerPC VSX Swap Removal", false, false) INITIALIZE_PASS_END(PPCVSXSwapRemoval
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
INLINEASM - Represents an inline asm block.
CHAIN = STXVD2X CHAIN, VSRC, Ptr - Occurs only for little endian.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void initializePPCVSXSwapRemovalPass(PassRegistry &)
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.
MachineInstrBundleIterator< MachineInstr > iterator
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineInstrBuilder & UseMI
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
void setImm(int64_t immVal)
FunctionPass class - This class is used to implement most global optimizations.
static bool isVecReg(unsigned Reg)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
void setIsKill(bool Val=true)
MachineOperand class - Representation of each machine instruction operand.
MachineInstrBuilder MachineInstrBuilder & DefMI
VPERM - The PPC VPERM Instruction.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
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 the set of available library functions based on the specified target triple.
const MachineBasicBlock * getParent() const
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.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
static unsigned UseReg(const MachineOperand &MO)
void setReg(unsigned Reg)
Change the register this operand corresponds to.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool needsSwapsForVSXMemOps() const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
const MachineOperand & getOperand(unsigned i) const
XXPERMDI - The PPC XXPERMDI instruction.