52#include "llvm/Config/llvm-config.h"
59#define DEBUG_TYPE "ppc-vsx-swaps"
65struct PPCVSXSwapEntry {
73 unsigned int IsLoad : 1;
74 unsigned int IsStore : 1;
75 unsigned int IsSwap : 1;
76 unsigned int MentionsPhysVR : 1;
77 unsigned int IsSwappable : 1;
78 unsigned int MentionsPartialVR : 1;
79 unsigned int SpecialHandling : 3;
80 unsigned int WebRejected : 1;
81 unsigned int WillRemove : 1;
82 unsigned int HasUnanalyzableDef : 1;
104 std::vector<PPCVSXSwapEntry> SwapVector;
122 bool gatherVectorInstructions();
131 unsigned lookThruCopyLike(
unsigned SrcReg,
unsigned VecIdx);
137 void recordUnoptimizableWebs();
140 void markSwapsForRemoval();
149 unsigned DstReg,
unsigned SrcReg);
152 void handleSpecialSwappables(
int EntryIdx);
155 void dumpSwapVector();
171 bool isScalarVecReg(
unsigned Reg) {
179 bool isAnyVecReg(
unsigned Reg,
bool &Partial) {
180 if (isScalarVecReg(
Reg))
201 if (gatherVectorInstructions()) {
203 recordUnoptimizableWebs();
204 markSwapsForRemoval();
227 const int InitialVectorSize(256);
229 SwapVector.reserve(InitialVectorSize);
234 EC =
new EquivalenceClasses<int>;
240bool PPCVSXSwapRemoval::gatherVectorInstructions() {
241 bool RelevantFunction =
false;
243 for (MachineBasicBlock &
MBB : *MF) {
244 for (MachineInstr &
MI :
MBB) {
246 if (
MI.isDebugInstr())
249 bool RelevantInstr =
false;
250 bool Partial =
false;
252 for (
const MachineOperand &MO :
MI.operands()) {
259 if (isAnyVecReg(
Reg, Partial))
260 RelevantInstr =
true;
266 RelevantFunction =
true;
271 PPCVSXSwapEntry SwapEntry{};
272 int VecIdx = addSwapEntry(&
MI, SwapEntry);
274 switch(
MI.getOpcode()) {
283 SwapVector[VecIdx].MentionsPartialVR = 1;
285 SwapVector[VecIdx].IsSwappable = 1;
287 case PPC::XXPERMDI: {
295 int immed =
MI.getOperand(3).getImm();
297 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
299 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
301 if (trueReg1 == trueReg2)
302 SwapVector[VecIdx].IsSwap = 1;
306 SwapVector[VecIdx].IsSwappable = 1;
307 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
317 }
else if (immed == 0 || immed == 3) {
319 SwapVector[VecIdx].IsSwappable = 1;
320 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
322 unsigned trueReg1 = lookThruCopyLike(
MI.getOperand(1).getReg(),
324 unsigned trueReg2 = lookThruCopyLike(
MI.getOperand(2).getReg(),
326 if (trueReg1 == trueReg2)
327 SwapVector[VecIdx].MentionsPhysVR = 0;
331 SwapVector[VecIdx].IsSwappable = 1;
332 SwapVector[VecIdx].SpecialHandling = SHValues::SH_XXPERMDI;
341 SwapVector[VecIdx].IsLoad = 1;
347 SwapVector[VecIdx].IsLoad = 1;
348 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(1).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::INLINEASM_BR:
426 case PPC::EXTRACT_SUBREG:
427 case PPC::INSERT_SUBREG:
428 case PPC::COPY_TO_REGCLASS:
448 case PPC::VCIPHERLAST:
468 case PPC::VNCIPHERLAST:
493 case PPC::VSHASIGMAD:
494 case PPC::VSHASIGMAW:
528 if (RelevantFunction) {
533 return RelevantFunction;
538int PPCVSXSwapRemoval::addSwapEntry(MachineInstr *
MI,
539 PPCVSXSwapEntry& SwapEntry) {
540 SwapEntry.VSEMI =
MI;
541 SwapEntry.VSEId = SwapVector.size();
542 SwapVector.push_back(SwapEntry);
543 EC->insert(SwapEntry.VSEId);
544 SwapMap[
MI] = SwapEntry.VSEId;
545 return SwapEntry.VSEId;
557unsigned PPCVSXSwapRemoval::lookThruCopyLike(
unsigned SrcReg,
560 if (!
MI->isCopyLike())
563 assert((
MI->isCopy() ||
MI->isSubregToReg()) &&
564 "bad opcode for lookThruCopyLike");
565 unsigned CopySrcReg =
MI->getOperand(1).getReg();
567 if (!Register::isVirtualRegister(CopySrcReg)) {
568 if (!isScalarVecReg(CopySrcReg))
569 SwapVector[VecIdx].MentionsPhysVR = 1;
573 return lookThruCopyLike(CopySrcReg, VecIdx);
583void PPCVSXSwapRemoval::formWebs() {
585 LLVM_DEBUG(
dbgs() <<
"\n*** Forming webs for swap removal ***\n\n");
587 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
589 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
598 for (
const MachineOperand &MO :
MI->operands()) {
607 if (!(
MI->isCopy() && isScalarVecReg(
Reg)))
608 SwapVector[EntryIdx].MentionsPhysVR = 1;
617 SwapVector[EntryIdx].HasUnanalyzableDef = 1;
622 "Inconsistency: def of vector reg not found in swap map!");
623 int DefIdx = SwapMap[
DefMI];
624 (void)EC->unionSets(SwapVector[DefIdx].VSEId,
625 SwapVector[EntryIdx].VSEId);
628 SwapVector[DefIdx].VSEId,
629 SwapVector[EntryIdx].VSEId));
640void PPCVSXSwapRemoval::recordUnoptimizableWebs() {
642 LLVM_DEBUG(
dbgs() <<
"\n*** Rejecting webs for swap removal ***\n\n");
644 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
645 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
648 if (SwapVector[Repr].WebRejected)
654 if (SwapVector[EntryIdx].MentionsPhysVR ||
655 SwapVector[EntryIdx].MentionsPartialVR ||
656 SwapVector[EntryIdx].HasUnanalyzableDef ||
657 !(SwapVector[EntryIdx].IsSwappable || SwapVector[EntryIdx].IsSwap)) {
659 SwapVector[Repr].WebRejected = 1;
662 "unanalyzable def, or not swap[pable]\n",
665 LLVM_DEBUG(SwapVector[EntryIdx].VSEMI->dump());
671 else if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
672 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
680 int UseIdx = SwapMap[&
UseMI];
682 if (!SwapVector[UseIdx].IsSwap || SwapVector[UseIdx].IsLoad ||
683 SwapVector[UseIdx].IsStore) {
685 SwapVector[Repr].WebRejected = 1;
688 "Web %d rejected for load not feeding swap\n", Repr));
699 if (SwapVector[UseIdx].IsSwap && !SwapVector[UseIdx].IsLoad &&
700 !SwapVector[UseIdx].IsStore) {
702 for (MachineInstr &UseOfUseMI :
704 int UseOfUseIdx = SwapMap[&UseOfUseMI];
705 if (SwapVector[UseOfUseIdx].IsStore) {
706 SwapVector[Repr].WebRejected = 1;
709 "Web %d rejected for load/swap feeding a store\n", Repr));
722 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
723 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
727 int DefIdx = SwapMap[
DefMI];
729 if (!SwapVector[DefIdx].IsSwap || SwapVector[DefIdx].IsLoad ||
730 SwapVector[DefIdx].IsStore) {
732 SwapVector[Repr].WebRejected = 1;
735 "Web %d rejected for store not fed by swap\n", Repr));
746 int UseIdx = SwapMap[&
UseMI];
748 if (SwapVector[UseIdx].VSEMI->getOpcode() !=
MI->getOpcode()) {
749 SwapVector[Repr].WebRejected = 1;
753 "Web %d rejected for swap not feeding only stores\n", Repr));
774void PPCVSXSwapRemoval::markSwapsForRemoval() {
778 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
780 if (SwapVector[EntryIdx].IsLoad && SwapVector[EntryIdx].IsSwap) {
781 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
783 if (!SwapVector[Repr].WebRejected) {
784 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
788 int UseIdx = SwapMap[&
UseMI];
789 SwapVector[UseIdx].WillRemove = 1;
796 }
else if (SwapVector[EntryIdx].IsStore && SwapVector[EntryIdx].IsSwap) {
797 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
799 if (!SwapVector[Repr].WebRejected) {
800 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
803 int DefIdx = SwapMap[
DefMI];
804 SwapVector[DefIdx].WillRemove = 1;
810 }
else if (SwapVector[EntryIdx].IsSwappable &&
811 SwapVector[EntryIdx].SpecialHandling != 0) {
812 int Repr = EC->getLeaderValue(SwapVector[EntryIdx].VSEId);
814 if (!SwapVector[Repr].WebRejected)
815 handleSpecialSwappables(EntryIdx);
825void PPCVSXSwapRemoval::insertSwap(MachineInstr *
MI,
827 unsigned DstReg,
unsigned SrcReg) {
828 BuildMI(*
MI->getParent(), InsertPoint,
MI->getDebugLoc(),
829 TII->get(PPC::XXPERMDI), DstReg)
840void PPCVSXSwapRemoval::handleSpecialSwappables(
int EntryIdx) {
841 switch (SwapVector[EntryIdx].SpecialHandling) {
848 case SHValues::SH_SPLAT: {
849 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
855 switch (
MI->getOpcode()) {
858 case PPC::VSPLTB: NElts = 16;
break;
859 case PPC::VSPLTH: NElts = 8;
break;
861 case PPC::XXSPLTW: NElts = 4;
break;
865 if (
MI->getOpcode() == PPC::XXSPLTW)
866 EltNo =
MI->getOperand(2).getImm();
868 EltNo =
MI->getOperand(1).getImm();
870 EltNo = (EltNo + NElts / 2) % NElts;
871 if (
MI->getOpcode() == PPC::XXSPLTW)
872 MI->getOperand(2).setImm(EltNo);
874 MI->getOperand(1).setImm(EltNo);
887 case SHValues::SH_XXPERMDI: {
888 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
893 unsigned Selector =
MI->getOperand(3).getImm();
894 if (Selector == 0 || Selector == 3)
895 Selector = 3 - Selector;
896 MI->getOperand(3).setImm(Selector);
900 MI->getOperand(1).setReg(Reg2);
901 MI->getOperand(2).setReg(Reg1);
904 bool IsKill1 =
MI->getOperand(1).isKill();
905 bool IsKill2 =
MI->getOperand(2).isKill();
906 MI->getOperand(1).setIsKill(IsKill2);
907 MI->getOperand(2).setIsKill(IsKill1);
917 case SHValues::SH_COPYWIDEN: {
918 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
927 MI->getOperand(0).setReg(NewVReg);
938 if (DstRC == &PPC::VRRCRegClass) {
942 BuildMI(*
MI->getParent(), InsertPoint,
MI->getDebugLoc(),
943 TII->get(PPC::COPY), VSRCTmp1)
947 insertSwap(
MI, InsertPoint, VSRCTmp2, VSRCTmp1);
950 BuildMI(*
MI->getParent(), InsertPoint,
MI->getDebugLoc(),
951 TII->get(PPC::COPY), DstReg)
956 insertSwap(
MI, InsertPoint, DstReg, NewVReg);
966bool PPCVSXSwapRemoval::removeSwaps() {
972 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
973 if (SwapVector[EntryIdx].WillRemove) {
975 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
978 MI->getOperand(0).getReg())
979 .
add(
MI->getOperand(1));
982 SwapVector[EntryIdx].VSEId));
985 MI->eraseFromParent();
992#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
996 for (
unsigned EntryIdx = 0; EntryIdx < SwapVector.size(); ++EntryIdx) {
998 MachineInstr *
MI = SwapVector[EntryIdx].VSEMI;
999 int ID = SwapVector[EntryIdx].VSEId;
1002 dbgs() <<
format(
"%6d", EC->getLeaderValue(ID));
1003 dbgs() <<
format(
" %bb.%3d",
MI->getParent()->getNumber());
1004 dbgs() <<
format(
" %14s ",
TII->getName(
MI->getOpcode()).str().c_str());
1006 if (SwapVector[EntryIdx].IsLoad)
1008 if (SwapVector[EntryIdx].IsStore)
1010 if (SwapVector[EntryIdx].IsSwap)
1012 if (SwapVector[EntryIdx].MentionsPhysVR)
1013 dbgs() <<
"physreg ";
1014 if (SwapVector[EntryIdx].MentionsPartialVR)
1015 dbgs() <<
"partialreg ";
1016 if (SwapVector[EntryIdx].HasUnanalyzableDef)
1017 dbgs() <<
"unanalyzabledef ";
1019 if (SwapVector[EntryIdx].IsSwappable) {
1020 dbgs() <<
"swappable ";
1021 switch(SwapVector[EntryIdx].SpecialHandling) {
1023 dbgs() <<
"special:**unknown**";
1028 dbgs() <<
"special:extract ";
1031 dbgs() <<
"special:insert ";
1034 dbgs() <<
"special:load ";
1037 dbgs() <<
"special:store ";
1040 dbgs() <<
"special:splat ";
1043 dbgs() <<
"special:xxpermdi ";
1046 dbgs() <<
"special:copywiden ";
1051 if (SwapVector[EntryIdx].WebRejected)
1052 dbgs() <<
"rejected ";
1053 if (SwapVector[EntryIdx].WillRemove)
1054 dbgs() <<
"remove ";
1068 "PowerPC VSX Swap Removal",
false,
false)
1072char PPCVSXSwapRemoval::ID = 0;
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isRegInClass(const MachineOperand &MO, const TargetRegisterClass *Class)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
static bool isVecReg(unsigned Reg)
Promote Memory to Register
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
This represents a collection of equivalence classes and supports three efficient operations: insert a...
FunctionPass class - This class is used to implement most global optimizations.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
bool needsSwapsForVSXMemOps() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createPPCVSXSwapRemovalPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
MCRegisterClass TargetRegisterClass