77using namespace PatternMatch;
79#define DEBUG_TYPE "complex-deinterleaving"
81STATISTIC(NumComplexTransformations,
"Amount of complex patterns transformed");
84 "enable-complex-deinterleaving",
112class ComplexDeinterleavingLegacyPass :
public FunctionPass {
116 ComplexDeinterleavingLegacyPass(
const TargetMachine *TM =
nullptr)
123 return "Complex Deinterleaving Pass";
136class ComplexDeinterleavingGraph;
137struct ComplexDeinterleavingCompositeNode {
144 friend class ComplexDeinterleavingGraph;
145 using NodePtr = std::shared_ptr<ComplexDeinterleavingCompositeNode>;
146 using RawNodePtr = ComplexDeinterleavingCompositeNode *;
156 std::optional<FastMathFlags>
Flags;
159 ComplexDeinterleavingRotation::Rotation_0;
161 Value *ReplacementNode =
nullptr;
167 auto PrintValue = [&](
Value *
V) {
175 auto PrintNodeRef = [&](RawNodePtr
Ptr) {
182 OS <<
"- CompositeNode: " <<
this <<
"\n";
187 OS <<
" ReplacementNode: ";
188 PrintValue(ReplacementNode);
190 OS <<
" Rotation: " << ((int)Rotation * 90) <<
"\n";
191 OS <<
" Operands: \n";
199class ComplexDeinterleavingGraph {
207 using Addend = std::pair<Value *, bool>;
208 using NodePtr = ComplexDeinterleavingCompositeNode::NodePtr;
209 using RawNodePtr = ComplexDeinterleavingCompositeNode::RawNodePtr;
213 struct PartialMulCandidate {
223 : TL(TL), TLI(TLI) {}
234 std::map<Instruction *, NodePtr> RootToNode;
274 bool PHIsFound =
false;
282 std::map<PHINode *, PHINode *> OldToNewPHI;
287 Operation != ComplexDeinterleavingOperation::ReductionOperation) ||
289 "Reduction related nodes must have Real and Imaginary parts");
290 return std::make_shared<ComplexDeinterleavingCompositeNode>(
Operation, R,
294 NodePtr submitCompositeNode(NodePtr
Node) {
319 std::pair<Value *, Value *> &CommonOperandI);
337 NodePtr identifyAdditions(std::list<Addend> &RealAddends,
338 std::list<Addend> &ImagAddends,
339 std::optional<FastMathFlags> Flags,
343 NodePtr extractPositiveAddend(std::list<Addend> &RealAddends,
344 std::list<Addend> &ImagAddends);
349 NodePtr identifyMultiplications(std::vector<Product> &RealMuls,
350 std::vector<Product> &ImagMuls,
356 bool collectPartialMuls(
const std::vector<Product> &RealMuls,
357 const std::vector<Product> &ImagMuls,
358 std::vector<PartialMulCandidate> &Candidates);
383 NodePtr identifySplat(
Value *Real,
Value *Imag);
398 void processReductionOperation(
Value *OperationReplacement, RawNodePtr
Node);
403 for (
const auto &
Node : CompositeNodes)
416 void identifyReductionNodes();
426class ComplexDeinterleaving {
429 : TL(tl), TLI(tli) {}
441char ComplexDeinterleavingLegacyPass::ID = 0;
444 "Complex Deinterleaving",
false,
false)
450 const TargetLowering *TL = TM->getSubtargetImpl(
F)->getTargetLowering();
452 if (!ComplexDeinterleaving(TL, &TLI).runOnFunction(
F))
461 return new ComplexDeinterleavingLegacyPass(TM);
464bool ComplexDeinterleavingLegacyPass::runOnFunction(
Function &
F) {
465 const auto *TL = TM->getSubtargetImpl(
F)->getTargetLowering();
466 auto TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
467 return ComplexDeinterleaving(TL, &TLI).runOnFunction(
F);
470bool ComplexDeinterleaving::runOnFunction(
Function &
F) {
473 dbgs() <<
"Complex deinterleaving has been explicitly disabled.\n");
479 dbgs() <<
"Complex deinterleaving has been disabled, target does "
480 "not support lowering of complex number operations.\n");
484 bool Changed =
false;
486 Changed |= evaluateBasicBlock(&
B);
493 if ((Mask.size() & 1))
496 int HalfNumElements = Mask.size() / 2;
497 for (
int Idx = 0;
Idx < HalfNumElements; ++
Idx) {
498 int MaskIdx =
Idx * 2;
499 if (Mask[MaskIdx] !=
Idx || Mask[MaskIdx + 1] != (
Idx + HalfNumElements))
508 int HalfNumElements = Mask.size() / 2;
510 for (
int Idx = 1;
Idx < HalfNumElements; ++
Idx) {
524 auto *
I = cast<Instruction>(V);
525 if (
I->getOpcode() == Instruction::FNeg)
526 return I->getOperand(0);
528 return I->getOperand(1);
531bool ComplexDeinterleaving::evaluateBasicBlock(
BasicBlock *
B) {
532 ComplexDeinterleavingGraph Graph(TL, TLI);
533 if (Graph.collectPotentialReductions(
B))
534 Graph.identifyReductionNodes();
537 Graph.identifyNodes(&
I);
539 if (Graph.checkNodes()) {
540 Graph.replaceNodes();
547ComplexDeinterleavingGraph::NodePtr
548ComplexDeinterleavingGraph::identifyNodeWithImplicitAdd(
550 std::pair<Value *, Value *> &PartialMatch) {
551 LLVM_DEBUG(
dbgs() <<
"identifyNodeWithImplicitAdd " << *Real <<
" / " << *Imag
559 if ((Real->
getOpcode() != Instruction::FMul &&
560 Real->
getOpcode() != Instruction::Mul) ||
561 (Imag->
getOpcode() != Instruction::FMul &&
562 Imag->
getOpcode() != Instruction::Mul)) {
564 dbgs() <<
" - Real or imaginary instruction is not fmul or mul\n");
597 Value *CommonOperand;
598 Value *UncommonRealOp;
599 Value *UncommonImagOp;
601 if (R0 == I0 || R0 == I1) {
604 }
else if (R1 == I0 || R1 == I1) {
612 UncommonImagOp = (CommonOperand == I0) ? I1 : I0;
613 if (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
614 Rotation == ComplexDeinterleavingRotation::Rotation_270)
615 std::swap(UncommonRealOp, UncommonImagOp);
619 if (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
620 Rotation == ComplexDeinterleavingRotation::Rotation_180)
621 PartialMatch.first = CommonOperand;
623 PartialMatch.second = CommonOperand;
625 if (!PartialMatch.first || !PartialMatch.second) {
630 NodePtr CommonNode = identifyNode(PartialMatch.first, PartialMatch.second);
636 NodePtr UncommonNode = identifyNode(UncommonRealOp, UncommonImagOp);
642 NodePtr
Node = prepareCompositeNode(
643 ComplexDeinterleavingOperation::CMulPartial, Real, Imag);
644 Node->Rotation = Rotation;
645 Node->addOperand(CommonNode);
646 Node->addOperand(UncommonNode);
647 return submitCompositeNode(
Node);
650ComplexDeinterleavingGraph::NodePtr
651ComplexDeinterleavingGraph::identifyPartialMul(
Instruction *Real,
653 LLVM_DEBUG(
dbgs() <<
"identifyPartialMul " << *Real <<
" / " << *Imag
656 auto IsAdd = [](
unsigned Op) {
657 return Op == Instruction::FAdd ||
Op == Instruction::Add;
659 auto IsSub = [](
unsigned Op) {
660 return Op == Instruction::FSub ||
Op == Instruction::Sub;
664 Rotation = ComplexDeinterleavingRotation::Rotation_0;
666 Rotation = ComplexDeinterleavingRotation::Rotation_90;
668 Rotation = ComplexDeinterleavingRotation::Rotation_180;
670 Rotation = ComplexDeinterleavingRotation::Rotation_270;
676 if (isa<FPMathOperator>(Real) &&
679 LLVM_DEBUG(
dbgs() <<
" - Contract is missing from the FastMath flags.\n");
702 Value *CommonOperand;
703 Value *UncommonRealOp;
704 Value *UncommonImagOp;
706 if (R0 == I0 || R0 == I1) {
709 }
else if (R1 == I0 || R1 == I1) {
717 UncommonImagOp = (CommonOperand == I0) ? I1 : I0;
718 if (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
719 Rotation == ComplexDeinterleavingRotation::Rotation_270)
720 std::swap(UncommonRealOp, UncommonImagOp);
722 std::pair<Value *, Value *> PartialMatch(
723 (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
724 Rotation == ComplexDeinterleavingRotation::Rotation_180)
727 (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
728 Rotation == ComplexDeinterleavingRotation::Rotation_270)
732 auto *CRInst = dyn_cast<Instruction>(CR);
733 auto *CIInst = dyn_cast<Instruction>(CI);
735 if (!CRInst || !CIInst) {
736 LLVM_DEBUG(
dbgs() <<
" - Common operands are not instructions.\n");
740 NodePtr CNode = identifyNodeWithImplicitAdd(CRInst, CIInst, PartialMatch);
746 NodePtr UncommonRes = identifyNode(UncommonRealOp, UncommonImagOp);
752 assert(PartialMatch.first && PartialMatch.second);
753 NodePtr CommonRes = identifyNode(PartialMatch.first, PartialMatch.second);
759 NodePtr
Node = prepareCompositeNode(
760 ComplexDeinterleavingOperation::CMulPartial, Real, Imag);
761 Node->Rotation = Rotation;
762 Node->addOperand(CommonRes);
763 Node->addOperand(UncommonRes);
764 Node->addOperand(CNode);
765 return submitCompositeNode(
Node);
768ComplexDeinterleavingGraph::NodePtr
770 LLVM_DEBUG(
dbgs() <<
"identifyAdd " << *Real <<
" / " << *Imag <<
"\n");
774 if ((Real->
getOpcode() == Instruction::FSub &&
775 Imag->
getOpcode() == Instruction::FAdd) ||
776 (Real->
getOpcode() == Instruction::Sub &&
778 Rotation = ComplexDeinterleavingRotation::Rotation_90;
779 else if ((Real->
getOpcode() == Instruction::FAdd &&
780 Imag->
getOpcode() == Instruction::FSub) ||
781 (Real->
getOpcode() == Instruction::Add &&
783 Rotation = ComplexDeinterleavingRotation::Rotation_270;
785 LLVM_DEBUG(
dbgs() <<
" - Unhandled case, rotation is not assigned.\n");
789 auto *AR = dyn_cast<Instruction>(Real->
getOperand(0));
790 auto *BI = dyn_cast<Instruction>(Real->
getOperand(1));
791 auto *AI = dyn_cast<Instruction>(Imag->
getOperand(0));
794 if (!AR || !AI || !BR || !BI) {
799 NodePtr ResA = identifyNode(AR, AI);
801 LLVM_DEBUG(
dbgs() <<
" - AR/AI is not identified as a composite node.\n");
804 NodePtr ResB = identifyNode(BR, BI);
806 LLVM_DEBUG(
dbgs() <<
" - BR/BI is not identified as a composite node.\n");
811 prepareCompositeNode(ComplexDeinterleavingOperation::CAdd, Real, Imag);
812 Node->Rotation = Rotation;
813 Node->addOperand(ResA);
814 Node->addOperand(ResB);
815 return submitCompositeNode(
Node);
819 unsigned OpcA =
A->getOpcode();
820 unsigned OpcB =
B->getOpcode();
822 return (OpcA == Instruction::FSub && OpcB == Instruction::FAdd) ||
823 (OpcA == Instruction::FAdd && OpcB == Instruction::FSub) ||
824 (OpcA == Instruction::Sub && OpcB == Instruction::Add) ||
825 (OpcA == Instruction::Add && OpcB == Instruction::Sub);
836 switch (
I->getOpcode()) {
837 case Instruction::FAdd:
838 case Instruction::FSub:
839 case Instruction::FMul:
840 case Instruction::FNeg:
841 case Instruction::Add:
842 case Instruction::Sub:
843 case Instruction::Mul:
850ComplexDeinterleavingGraph::NodePtr
851ComplexDeinterleavingGraph::identifySymmetricOperation(
Instruction *Real,
863 NodePtr Op0 = identifyNode(R0, I0);
864 NodePtr Op1 =
nullptr;
871 Op1 = identifyNode(R1, I1);
876 if (isa<FPMathOperator>(Real) &&
880 auto Node = prepareCompositeNode(ComplexDeinterleavingOperation::Symmetric,
883 if (isa<FPMathOperator>(Real))
886 Node->addOperand(Op0);
888 Node->addOperand(Op1);
890 return submitCompositeNode(
Node);
893ComplexDeinterleavingGraph::NodePtr
894ComplexDeinterleavingGraph::identifyNode(
Value *R,
Value *
I) {
896 assert(
R->getType() ==
I->getType() &&
897 "Real and imaginary parts should not have different types");
899 auto It = CachedResult.
find({
R,
I});
900 if (It != CachedResult.
end()) {
905 if (NodePtr CN = identifySplat(R,
I))
908 auto *Real = dyn_cast<Instruction>(R);
909 auto *Imag = dyn_cast<Instruction>(
I);
913 if (NodePtr CN = identifyDeinterleave(Real, Imag))
916 if (NodePtr CN = identifyPHINode(Real, Imag))
919 if (NodePtr CN = identifySelectNode(Real, Imag))
922 auto *VTy = cast<VectorType>(Real->
getType());
923 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
926 ComplexDeinterleavingOperation::CMulPartial, NewVTy);
928 ComplexDeinterleavingOperation::CAdd, NewVTy);
931 if (NodePtr CN = identifyPartialMul(Real, Imag))
936 if (NodePtr CN = identifyAdd(Real, Imag))
940 if (HasCMulSupport && HasCAddSupport) {
941 if (NodePtr CN = identifyReassocNodes(Real, Imag))
945 if (NodePtr CN = identifySymmetricOperation(Real, Imag))
949 CachedResult[{
R,
I}] =
nullptr;
953ComplexDeinterleavingGraph::NodePtr
954ComplexDeinterleavingGraph::identifyReassocNodes(
Instruction *Real,
956 auto IsOperationSupported = [](
unsigned Opcode) ->
bool {
957 return Opcode == Instruction::FAdd || Opcode == Instruction::FSub ||
958 Opcode == Instruction::FNeg || Opcode == Instruction::Add ||
959 Opcode == Instruction::Sub;
962 if (!IsOperationSupported(Real->
getOpcode()) ||
963 !IsOperationSupported(Imag->
getOpcode()))
966 std::optional<FastMathFlags>
Flags;
967 if (isa<FPMathOperator>(Real)) {
969 LLVM_DEBUG(
dbgs() <<
"The flags in Real and Imaginary instructions are "
975 if (!
Flags->allowReassoc()) {
978 <<
"the 'Reassoc' attribute is missing in the FastMath flags\n");
987 std::list<Addend> &Addends) ->
bool {
990 while (!Worklist.
empty()) {
991 auto [
V, IsPositive] = Worklist.
back();
993 if (!Visited.
insert(V).second)
998 Addends.emplace_back(V, IsPositive);
1008 if (
I !=
Insn &&
I->getNumUses() > 1) {
1009 LLVM_DEBUG(
dbgs() <<
"Found potential sub-expression: " << *
I <<
"\n");
1010 Addends.emplace_back(
I, IsPositive);
1013 switch (
I->getOpcode()) {
1014 case Instruction::FAdd:
1015 case Instruction::Add:
1019 case Instruction::FSub:
1023 case Instruction::Sub:
1031 case Instruction::FMul:
1032 case Instruction::Mul: {
1034 if (
isNeg(
I->getOperand(0))) {
1036 IsPositive = !IsPositive;
1038 A =
I->getOperand(0);
1041 if (
isNeg(
I->getOperand(1))) {
1043 IsPositive = !IsPositive;
1045 B =
I->getOperand(1);
1047 Muls.push_back(Product{
A,
B, IsPositive});
1050 case Instruction::FNeg:
1054 Addends.emplace_back(
I, IsPositive);
1058 if (Flags &&
I->getFastMathFlags() != *Flags) {
1060 "inconsistent with the root instructions' flags: "
1068 std::vector<Product> RealMuls, ImagMuls;
1069 std::list<Addend> RealAddends, ImagAddends;
1070 if (!Collect(Real, RealMuls, RealAddends) ||
1071 !Collect(Imag, ImagMuls, ImagAddends))
1074 if (RealAddends.size() != ImagAddends.size())
1078 if (!RealMuls.empty() || !ImagMuls.empty()) {
1081 FinalNode = extractPositiveAddend(RealAddends, ImagAddends);
1082 FinalNode = identifyMultiplications(RealMuls, ImagMuls, FinalNode);
1088 if (!RealAddends.empty() || !ImagAddends.empty()) {
1089 FinalNode = identifyAdditions(RealAddends, ImagAddends, Flags, FinalNode);
1093 assert(FinalNode &&
"FinalNode can not be nullptr here");
1095 FinalNode->Real = Real;
1096 FinalNode->Imag = Imag;
1097 submitCompositeNode(FinalNode);
1101bool ComplexDeinterleavingGraph::collectPartialMuls(
1102 const std::vector<Product> &RealMuls,
const std::vector<Product> &ImagMuls,
1103 std::vector<PartialMulCandidate> &PartialMulCandidates) {
1105 auto FindCommonInstruction = [](
const Product &Real,
1106 const Product &Imag) ->
Value * {
1107 if (Real.Multiplicand == Imag.Multiplicand ||
1108 Real.Multiplicand == Imag.Multiplier)
1109 return Real.Multiplicand;
1111 if (Real.Multiplier == Imag.Multiplicand ||
1112 Real.Multiplier == Imag.Multiplier)
1113 return Real.Multiplier;
1122 for (
unsigned i = 0; i < RealMuls.size(); ++i) {
1123 bool FoundCommon =
false;
1124 for (
unsigned j = 0;
j < ImagMuls.size(); ++
j) {
1125 auto *Common = FindCommonInstruction(RealMuls[i], ImagMuls[j]);
1129 auto *
A = RealMuls[i].Multiplicand == Common ? RealMuls[i].Multiplier
1130 : RealMuls[i].Multiplicand;
1131 auto *
B = ImagMuls[
j].Multiplicand == Common ? ImagMuls[
j].Multiplier
1132 : ImagMuls[
j].Multiplicand;
1134 auto Node = identifyNode(
A,
B);
1137 PartialMulCandidates.push_back({Common,
Node, i,
j,
false});
1140 Node = identifyNode(
B,
A);
1143 PartialMulCandidates.push_back({Common,
Node, i,
j,
true});
1152ComplexDeinterleavingGraph::NodePtr
1153ComplexDeinterleavingGraph::identifyMultiplications(
1154 std::vector<Product> &RealMuls, std::vector<Product> &ImagMuls,
1156 if (RealMuls.size() != ImagMuls.size())
1159 std::vector<PartialMulCandidate>
Info;
1160 if (!collectPartialMuls(RealMuls, ImagMuls, Info))
1164 std::map<Value *, NodePtr> CommonToNode;
1165 std::vector<bool> Processed(
Info.size(),
false);
1166 for (
unsigned I = 0;
I <
Info.size(); ++
I) {
1170 PartialMulCandidate &InfoA =
Info[
I];
1171 for (
unsigned J =
I + 1; J <
Info.size(); ++J) {
1175 PartialMulCandidate &InfoB =
Info[J];
1176 auto *InfoReal = &InfoA;
1177 auto *InfoImag = &InfoB;
1179 auto NodeFromCommon = identifyNode(InfoReal->Common, InfoImag->Common);
1180 if (!NodeFromCommon) {
1182 NodeFromCommon = identifyNode(InfoReal->Common, InfoImag->Common);
1184 if (!NodeFromCommon)
1187 CommonToNode[InfoReal->Common] = NodeFromCommon;
1188 CommonToNode[InfoImag->Common] = NodeFromCommon;
1189 Processed[
I] =
true;
1190 Processed[J] =
true;
1194 std::vector<bool> ProcessedReal(RealMuls.size(),
false);
1195 std::vector<bool> ProcessedImag(ImagMuls.size(),
false);
1197 for (
auto &PMI : Info) {
1198 if (ProcessedReal[PMI.RealIdx] || ProcessedImag[PMI.ImagIdx])
1201 auto It = CommonToNode.find(PMI.Common);
1204 if (It == CommonToNode.end()) {
1206 dbgs() <<
"Unprocessed independent partial multiplication:\n";
1207 for (
auto *
Mul : {&RealMuls[PMI.RealIdx], &RealMuls[PMI.RealIdx]})
1209 <<
" multiplied by " << *
Mul->Multiplicand <<
"\n";
1214 auto &RealMul = RealMuls[PMI.RealIdx];
1215 auto &ImagMul = ImagMuls[PMI.ImagIdx];
1217 auto NodeA = It->second;
1218 auto NodeB = PMI.Node;
1219 auto IsMultiplicandReal = PMI.Common == NodeA->Real;
1234 if ((IsMultiplicandReal && PMI.IsNodeInverted) ||
1235 (!IsMultiplicandReal && !PMI.IsNodeInverted))
1240 if (IsMultiplicandReal) {
1242 if (RealMul.IsPositive && ImagMul.IsPositive)
1244 else if (!RealMul.IsPositive && !ImagMul.IsPositive)
1251 if (!RealMul.IsPositive && ImagMul.IsPositive)
1253 else if (RealMul.IsPositive && !ImagMul.IsPositive)
1260 dbgs() <<
"Identified partial multiplication (X, Y) * (U, V):\n";
1261 dbgs().
indent(4) <<
"X: " << *NodeA->Real <<
"\n";
1262 dbgs().
indent(4) <<
"Y: " << *NodeA->Imag <<
"\n";
1263 dbgs().
indent(4) <<
"U: " << *NodeB->Real <<
"\n";
1264 dbgs().
indent(4) <<
"V: " << *NodeB->Imag <<
"\n";
1265 dbgs().
indent(4) <<
"Rotation - " << (int)Rotation * 90 <<
"\n";
1268 NodePtr NodeMul = prepareCompositeNode(
1269 ComplexDeinterleavingOperation::CMulPartial,
nullptr,
nullptr);
1270 NodeMul->Rotation = Rotation;
1271 NodeMul->addOperand(NodeA);
1272 NodeMul->addOperand(NodeB);
1274 NodeMul->addOperand(Result);
1275 submitCompositeNode(NodeMul);
1277 ProcessedReal[PMI.RealIdx] =
true;
1278 ProcessedImag[PMI.ImagIdx] =
true;
1282 if (!
all_of(ProcessedReal, [](
bool V) {
return V; }) ||
1283 !
all_of(ProcessedImag, [](
bool V) {
return V; })) {
1288 dbgs() <<
"Unprocessed products (Real):\n";
1289 for (
size_t i = 0; i < ProcessedReal.size(); ++i) {
1290 if (!ProcessedReal[i])
1291 dbgs().
indent(4) << (RealMuls[i].IsPositive ?
"+" :
"-")
1292 << *RealMuls[i].Multiplier <<
" multiplied by "
1293 << *RealMuls[i].Multiplicand <<
"\n";
1295 dbgs() <<
"Unprocessed products (Imag):\n";
1296 for (
size_t i = 0; i < ProcessedImag.size(); ++i) {
1297 if (!ProcessedImag[i])
1298 dbgs().
indent(4) << (ImagMuls[i].IsPositive ?
"+" :
"-")
1299 << *ImagMuls[i].Multiplier <<
" multiplied by "
1300 << *ImagMuls[i].Multiplicand <<
"\n";
1309ComplexDeinterleavingGraph::NodePtr
1310ComplexDeinterleavingGraph::identifyAdditions(
1311 std::list<Addend> &RealAddends, std::list<Addend> &ImagAddends,
1312 std::optional<FastMathFlags> Flags, NodePtr
Accumulator =
nullptr) {
1313 if (RealAddends.size() != ImagAddends.size())
1322 Result = extractPositiveAddend(RealAddends, ImagAddends);
1327 while (!RealAddends.empty()) {
1328 auto ItR = RealAddends.begin();
1329 auto [
R, IsPositiveR] = *ItR;
1331 bool FoundImag =
false;
1332 for (
auto ItI = ImagAddends.begin(); ItI != ImagAddends.end(); ++ItI) {
1333 auto [
I, IsPositiveI] = *ItI;
1335 if (IsPositiveR && IsPositiveI)
1336 Rotation = ComplexDeinterleavingRotation::Rotation_0;
1337 else if (!IsPositiveR && IsPositiveI)
1338 Rotation = ComplexDeinterleavingRotation::Rotation_90;
1339 else if (!IsPositiveR && !IsPositiveI)
1340 Rotation = ComplexDeinterleavingRotation::Rotation_180;
1342 Rotation = ComplexDeinterleavingRotation::Rotation_270;
1345 if (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
1346 Rotation == ComplexDeinterleavingRotation::Rotation_180) {
1347 AddNode = identifyNode(R,
I);
1349 AddNode = identifyNode(
I, R);
1353 dbgs() <<
"Identified addition:\n";
1356 dbgs().
indent(4) <<
"Rotation - " << (int)Rotation * 90 <<
"\n";
1361 TmpNode = prepareCompositeNode(
1362 ComplexDeinterleavingOperation::Symmetric,
nullptr,
nullptr);
1364 TmpNode->Opcode = Instruction::FAdd;
1365 TmpNode->Flags = *
Flags;
1367 TmpNode->Opcode = Instruction::Add;
1369 }
else if (Rotation ==
1371 TmpNode = prepareCompositeNode(
1372 ComplexDeinterleavingOperation::Symmetric,
nullptr,
nullptr);
1374 TmpNode->Opcode = Instruction::FSub;
1375 TmpNode->Flags = *
Flags;
1377 TmpNode->Opcode = Instruction::Sub;
1380 TmpNode = prepareCompositeNode(ComplexDeinterleavingOperation::CAdd,
1382 TmpNode->Rotation = Rotation;
1385 TmpNode->addOperand(Result);
1386 TmpNode->addOperand(AddNode);
1387 submitCompositeNode(TmpNode);
1389 RealAddends.erase(ItR);
1390 ImagAddends.erase(ItI);
1401ComplexDeinterleavingGraph::NodePtr
1402ComplexDeinterleavingGraph::extractPositiveAddend(
1403 std::list<Addend> &RealAddends, std::list<Addend> &ImagAddends) {
1404 for (
auto ItR = RealAddends.begin(); ItR != RealAddends.end(); ++ItR) {
1405 for (
auto ItI = ImagAddends.begin(); ItI != ImagAddends.end(); ++ItI) {
1406 auto [
R, IsPositiveR] = *ItR;
1407 auto [
I, IsPositiveI] = *ItI;
1408 if (IsPositiveR && IsPositiveI) {
1409 auto Result = identifyNode(R,
I);
1411 RealAddends.erase(ItR);
1412 ImagAddends.erase(ItI);
1421bool ComplexDeinterleavingGraph::identifyNodes(
Instruction *RootI) {
1426 auto It = RootToNode.find(RootI);
1427 if (It != RootToNode.end()) {
1428 auto RootNode = It->second;
1429 assert(RootNode->Operation ==
1430 ComplexDeinterleavingOperation::ReductionOperation);
1433 auto *
R = cast<Instruction>(RootNode->Real);
1434 auto *
I = cast<Instruction>(RootNode->Imag);
1435 auto *ReplacementAnchor =
R->comesBefore(
I) ?
I :
R;
1436 if (ReplacementAnchor != RootI)
1442 auto RootNode = identifyRoot(RootI);
1449 dbgs() <<
"Complex deinterleaving graph for " <<
F->getName()
1450 <<
"::" <<
B->getName() <<
".\n";
1454 RootToNode[RootI] = RootNode;
1459bool ComplexDeinterleavingGraph::collectPotentialReductions(
BasicBlock *
B) {
1460 bool FoundPotentialReduction =
false;
1462 auto *Br = dyn_cast<BranchInst>(
B->getTerminator());
1463 if (!Br || Br->getNumSuccessors() != 2)
1467 if (Br->getSuccessor(0) !=
B && Br->getSuccessor(1) !=
B)
1471 for (
auto &
PHI :
B->phis()) {
1472 if (
PHI.getNumIncomingValues() != 2)
1475 if (!
PHI.getType()->isVectorTy())
1478 auto *ReductionOp = dyn_cast<Instruction>(
PHI.getIncomingValueForBlock(
B));
1485 for (
auto *U : ReductionOp->users()) {
1489 FinalReduction = dyn_cast<Instruction>(U);
1492 if (NumUsers != 2 || !FinalReduction || FinalReduction->
getParent() ==
B ||
1493 isa<PHINode>(FinalReduction))
1496 ReductionInfo[ReductionOp] = {&
PHI, FinalReduction};
1498 auto BackEdgeIdx =
PHI.getBasicBlockIndex(
B);
1499 auto IncomingIdx = BackEdgeIdx == 0 ? 1 : 0;
1501 FoundPotentialReduction =
true;
1506 dyn_cast<Instruction>(
PHI.getIncomingValueForBlock(
Incoming)))
1507 FinalInstructions.
insert(InitPHI);
1509 return FoundPotentialReduction;
1512void ComplexDeinterleavingGraph::identifyReductionNodes() {
1515 for (
auto &
P : ReductionInfo)
1520 for (
size_t i = 0; i < OperationInstruction.
size(); ++i) {
1523 for (
size_t j = i + 1;
j < OperationInstruction.
size(); ++
j) {
1527 auto *Real = OperationInstruction[i];
1528 auto *Imag = OperationInstruction[
j];
1529 if (Real->getType() != Imag->
getType())
1532 RealPHI = ReductionInfo[Real].first;
1533 ImagPHI = ReductionInfo[Imag].first;
1535 auto Node = identifyNode(Real, Imag);
1539 Node = identifyNode(Real, Imag);
1545 if (
Node && PHIsFound) {
1546 LLVM_DEBUG(
dbgs() <<
"Identified reduction starting from instructions: "
1547 << *Real <<
" / " << *Imag <<
"\n");
1548 Processed[i] =
true;
1549 Processed[
j] =
true;
1550 auto RootNode = prepareCompositeNode(
1551 ComplexDeinterleavingOperation::ReductionOperation, Real, Imag);
1552 RootNode->addOperand(
Node);
1553 RootToNode[Real] = RootNode;
1554 RootToNode[Imag] = RootNode;
1555 submitCompositeNode(RootNode);
1565bool ComplexDeinterleavingGraph::checkNodes() {
1569 for (
auto &Pair : RootToNode)
1574 while (!Worklist.
empty()) {
1575 auto *
I = Worklist.
back();
1578 if (!AllInstructions.
insert(
I).second)
1582 if (
auto *OpI = dyn_cast<Instruction>(
Op)) {
1583 if (!FinalInstructions.
count(
I))
1591 for (
auto *
I : AllInstructions) {
1593 if (RootToNode.count(
I))
1596 for (
User *U :
I->users()) {
1597 if (AllInstructions.count(cast<Instruction>(U)))
1609 while (!Worklist.
empty()) {
1610 auto *
I = Worklist.
back();
1612 if (!Visited.
insert(
I).second)
1617 if (RootToNode.count(
I)) {
1619 <<
" could be deinterleaved but its chain of complex "
1620 "operations have an outside user\n");
1621 RootToNode.erase(
I);
1624 if (!AllInstructions.count(
I) || FinalInstructions.
count(
I))
1627 for (
User *U :
I->users())
1631 if (
auto *OpI = dyn_cast<Instruction>(
Op))
1635 return !RootToNode.empty();
1638ComplexDeinterleavingGraph::NodePtr
1639ComplexDeinterleavingGraph::identifyRoot(
Instruction *RootI) {
1640 if (
auto *Intrinsic = dyn_cast<IntrinsicInst>(RootI)) {
1641 if (
Intrinsic->getIntrinsicID() != Intrinsic::vector_interleave2)
1644 auto *Real = dyn_cast<Instruction>(
Intrinsic->getOperand(0));
1645 auto *Imag = dyn_cast<Instruction>(
Intrinsic->getOperand(1));
1649 return identifyNode(Real, Imag);
1652 auto *SVI = dyn_cast<ShuffleVectorInst>(RootI);
1666 return identifyNode(Real, Imag);
1669ComplexDeinterleavingGraph::NodePtr
1670ComplexDeinterleavingGraph::identifyDeinterleave(
Instruction *Real,
1673 Value *FinalValue =
nullptr;
1676 match(
I, m_Intrinsic<Intrinsic::vector_deinterleave2>(
1678 NodePtr PlaceholderNode = prepareCompositeNode(
1680 PlaceholderNode->ReplacementNode = FinalValue;
1681 FinalInstructions.
insert(Real);
1682 FinalInstructions.
insert(Imag);
1683 return submitCompositeNode(PlaceholderNode);
1686 auto *RealShuffle = dyn_cast<ShuffleVectorInst>(Real);
1687 auto *ImagShuffle = dyn_cast<ShuffleVectorInst>(Imag);
1688 if (!RealShuffle || !ImagShuffle) {
1689 if (RealShuffle || ImagShuffle)
1690 LLVM_DEBUG(
dbgs() <<
" - There's a shuffle where there shouldn't be.\n");
1694 Value *RealOp1 = RealShuffle->getOperand(1);
1695 if (!isa<UndefValue>(RealOp1) && !isa<ConstantAggregateZero>(RealOp1)) {
1699 Value *ImagOp1 = ImagShuffle->getOperand(1);
1700 if (!isa<UndefValue>(ImagOp1) && !isa<ConstantAggregateZero>(ImagOp1)) {
1705 Value *RealOp0 = RealShuffle->getOperand(0);
1706 Value *ImagOp0 = ImagShuffle->getOperand(0);
1708 if (RealOp0 != ImagOp0) {
1720 if (RealMask[0] != 0 || ImagMask[0] != 1) {
1721 LLVM_DEBUG(
dbgs() <<
" - Masks do not have the correct initial value.\n");
1728 Value *
Op = Shuffle->getOperand(0);
1729 auto *ShuffleTy = cast<FixedVectorType>(Shuffle->getType());
1730 auto *OpTy = cast<FixedVectorType>(
Op->getType());
1732 if (OpTy->getScalarType() != ShuffleTy->getScalarType())
1734 if ((ShuffleTy->getNumElements() * 2) != OpTy->getNumElements())
1747 Value *
Op = Shuffle->getOperand(0);
1748 auto *OpTy = cast<FixedVectorType>(
Op->getType());
1749 int NumElements = OpTy->getNumElements();
1753 return Last < NumElements;
1756 if (RealShuffle->getType() != ImagShuffle->getType()) {
1760 if (!CheckDeinterleavingShuffle(RealShuffle)) {
1764 if (!CheckDeinterleavingShuffle(ImagShuffle)) {
1769 NodePtr PlaceholderNode =
1771 RealShuffle, ImagShuffle);
1772 PlaceholderNode->ReplacementNode = RealShuffle->getOperand(0);
1773 FinalInstructions.
insert(RealShuffle);
1774 FinalInstructions.
insert(ImagShuffle);
1775 return submitCompositeNode(PlaceholderNode);
1778ComplexDeinterleavingGraph::NodePtr
1779ComplexDeinterleavingGraph::identifySplat(
Value *R,
Value *
I) {
1780 auto IsSplat = [](
Value *
V) ->
bool {
1782 if (isa<ConstantDataVector>(V))
1789 if (
auto *Const = dyn_cast<ConstantExpr>(V)) {
1790 if (
Const->getOpcode() != Instruction::ShuffleVector)
1792 VTy = cast<VectorType>(
Const->getType());
1794 }
else if (
auto *Shuf = dyn_cast<ShuffleVectorInst>(V)) {
1795 VTy = Shuf->getType();
1796 Mask = Shuf->getShuffleMask();
1804 if (!VTy->isScalableTy() && VTy->getElementCount().getKnownMinValue() == 1)
1810 if (!IsSplat(R) || !IsSplat(
I))
1813 auto *Real = dyn_cast<Instruction>(R);
1814 auto *Imag = dyn_cast<Instruction>(
I);
1815 if ((!Real && Imag) || (Real && !Imag))
1823 FinalInstructions.
insert(Real);
1824 FinalInstructions.
insert(Imag);
1826 NodePtr PlaceholderNode =
1827 prepareCompositeNode(ComplexDeinterleavingOperation::Splat, R,
I);
1828 return submitCompositeNode(PlaceholderNode);
1831ComplexDeinterleavingGraph::NodePtr
1832ComplexDeinterleavingGraph::identifyPHINode(
Instruction *Real,
1834 if (Real != RealPHI || Imag != ImagPHI)
1838 NodePtr PlaceholderNode = prepareCompositeNode(
1839 ComplexDeinterleavingOperation::ReductionPHI, Real, Imag);
1840 return submitCompositeNode(PlaceholderNode);
1843ComplexDeinterleavingGraph::NodePtr
1844ComplexDeinterleavingGraph::identifySelectNode(
Instruction *Real,
1846 auto *SelectReal = dyn_cast<SelectInst>(Real);
1847 auto *SelectImag = dyn_cast<SelectInst>(Imag);
1848 if (!SelectReal || !SelectImag)
1865 auto NodeA = identifyNode(AR, AI);
1869 auto NodeB = identifyNode(
RA, BI);
1873 NodePtr PlaceholderNode = prepareCompositeNode(
1874 ComplexDeinterleavingOperation::ReductionSelect, Real, Imag);
1875 PlaceholderNode->addOperand(NodeA);
1876 PlaceholderNode->addOperand(NodeB);
1877 FinalInstructions.
insert(MaskA);
1878 FinalInstructions.
insert(MaskB);
1879 return submitCompositeNode(PlaceholderNode);
1883 std::optional<FastMathFlags> Flags,
1887 case Instruction::FNeg:
1888 I =
B.CreateFNeg(InputA);
1890 case Instruction::FAdd:
1891 I =
B.CreateFAdd(InputA, InputB);
1893 case Instruction::Add:
1894 I =
B.CreateAdd(InputA, InputB);
1896 case Instruction::FSub:
1897 I =
B.CreateFSub(InputA, InputB);
1899 case Instruction::Sub:
1900 I =
B.CreateSub(InputA, InputB);
1902 case Instruction::FMul:
1903 I =
B.CreateFMul(InputA, InputB);
1905 case Instruction::Mul:
1906 I =
B.CreateMul(InputA, InputB);
1912 cast<Instruction>(
I)->setFastMathFlags(*Flags);
1918 if (
Node->ReplacementNode)
1919 return Node->ReplacementNode;
1921 auto ReplaceOperandIfExist = [&](RawNodePtr &
Node,
unsigned Idx) ->
Value * {
1922 return Node->Operands.size() >
Idx
1923 ? replaceNode(Builder,
Node->Operands[
Idx])
1927 Value *ReplacementNode;
1928 switch (
Node->Operation) {
1929 case ComplexDeinterleavingOperation::CAdd:
1930 case ComplexDeinterleavingOperation::CMulPartial:
1931 case ComplexDeinterleavingOperation::Symmetric: {
1932 Value *Input0 = ReplaceOperandIfExist(
Node, 0);
1933 Value *Input1 = ReplaceOperandIfExist(
Node, 1);
1936 "Node inputs need to be of the same type"));
1939 "Accumulator and input need to be of the same type"));
1940 if (
Node->Operation == ComplexDeinterleavingOperation::Symmetric)
1945 Builder,
Node->Operation,
Node->Rotation, Input0, Input1,
1949 case ComplexDeinterleavingOperation::Deinterleave:
1952 case ComplexDeinterleavingOperation::Splat: {
1953 auto *NewTy = VectorType::getDoubleElementsVectorType(
1954 cast<VectorType>(
Node->Real->getType()));
1955 auto *
R = dyn_cast<Instruction>(
Node->Real);
1956 auto *
I = dyn_cast<Instruction>(
Node->Imag);
1961 ReplacementNode = IRB.CreateIntrinsic(Intrinsic::vector_interleave2,
1965 Intrinsic::vector_interleave2, NewTy, {
Node->Real,
Node->Imag});
1969 case ComplexDeinterleavingOperation::ReductionPHI: {
1972 auto *VTy = cast<VectorType>(
Node->Real->getType());
1973 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
1975 OldToNewPHI[dyn_cast<PHINode>(
Node->Real)] = NewPHI;
1976 ReplacementNode = NewPHI;
1979 case ComplexDeinterleavingOperation::ReductionOperation:
1980 ReplacementNode = replaceNode(Builder,
Node->Operands[0]);
1981 processReductionOperation(ReplacementNode,
Node);
1983 case ComplexDeinterleavingOperation::ReductionSelect: {
1984 auto *MaskReal = cast<Instruction>(
Node->Real)->getOperand(0);
1985 auto *MaskImag = cast<Instruction>(
Node->Imag)->getOperand(0);
1986 auto *
A = replaceNode(Builder,
Node->Operands[0]);
1987 auto *
B = replaceNode(Builder,
Node->Operands[1]);
1988 auto *NewMaskTy = VectorType::getDoubleElementsVectorType(
1989 cast<VectorType>(MaskReal->getType()));
1990 auto *NewMask = Builder.
CreateIntrinsic(Intrinsic::vector_interleave2,
1991 NewMaskTy, {MaskReal, MaskImag});
1997 assert(ReplacementNode &&
"Target failed to create Intrinsic call.");
1998 NumComplexTransformations += 1;
1999 Node->ReplacementNode = ReplacementNode;
2000 return ReplacementNode;
2003void ComplexDeinterleavingGraph::processReductionOperation(
2004 Value *OperationReplacement, RawNodePtr
Node) {
2005 auto *Real = cast<Instruction>(
Node->Real);
2006 auto *Imag = cast<Instruction>(
Node->Imag);
2007 auto *OldPHIReal = ReductionInfo[Real].first;
2008 auto *OldPHIImag = ReductionInfo[Imag].first;
2009 auto *NewPHI = OldToNewPHI[OldPHIReal];
2011 auto *VTy = cast<VectorType>(Real->
getType());
2012 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
2015 Value *InitReal = OldPHIReal->getIncomingValueForBlock(
Incoming);
2016 Value *InitImag = OldPHIImag->getIncomingValueForBlock(
Incoming);
2019 auto *NewInit = Builder.
CreateIntrinsic(Intrinsic::vector_interleave2, NewVTy,
2020 {InitReal, InitImag});
2022 NewPHI->addIncoming(NewInit,
Incoming);
2023 NewPHI->addIncoming(OperationReplacement, BackEdge);
2027 auto *FinalReductionReal = ReductionInfo[Real].second;
2028 auto *FinalReductionImag = ReductionInfo[Imag].second;
2031 &*FinalReductionReal->getParent()->getFirstInsertionPt());
2033 OperationReplacement->
getType(),
2034 OperationReplacement);
2037 FinalReductionReal->replaceUsesOfWith(Real, NewReal);
2041 FinalReductionImag->replaceUsesOfWith(Imag, NewImag);
2044void ComplexDeinterleavingGraph::replaceNodes() {
2046 for (
auto *RootInstruction : OrderedRoots) {
2049 if (!RootToNode.count(RootInstruction))
2053 auto RootNode = RootToNode[RootInstruction];
2054 Value *
R = replaceNode(Builder, RootNode.get());
2056 if (RootNode->Operation ==
2057 ComplexDeinterleavingOperation::ReductionOperation) {
2058 auto *RootReal = cast<Instruction>(RootNode->Real);
2059 auto *RootImag = cast<Instruction>(RootNode->Imag);
2060 ReductionInfo[RootReal].first->removeIncomingValue(BackEdge);
2061 ReductionInfo[RootImag].first->removeIncomingValue(BackEdge);
2062 DeadInstrRoots.
push_back(cast<Instruction>(RootReal));
2063 DeadInstrRoots.
push_back(cast<Instruction>(RootImag));
2065 assert(R &&
"Unable to find replacement for RootInstruction");
2066 DeadInstrRoots.
push_back(RootInstruction);
2067 RootInstruction->replaceAllUsesWith(R);
2071 for (
auto *
I : DeadInstrRoots)
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
VarLocInsertPt getNextNode(const DbgRecord *DVR)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
static bool isInstructionPotentiallySymmetric(Instruction *I)
static Value * getNegOperand(Value *V)
Returns the operand for negation operation.
static bool isNeg(Value *V)
Returns true if the operation is a negation of V, and it works for both integers and floats.
static cl::opt< bool > ComplexDeinterleavingEnabled("enable-complex-deinterleaving", cl::desc("Enable generation of complex instructions"), cl::init(true), cl::Hidden)
static bool isInstructionPairAdd(Instruction *A, Instruction *B)
static Value * replaceSymmetricNode(IRBuilderBase &B, unsigned Opcode, std::optional< FastMathFlags > Flags, Value *InputA, Value *InputB)
static bool isInterleavingMask(ArrayRef< int > Mask)
Checks the given mask, and determines whether said mask is interleaving.
static bool isDeinterleavingMask(ArrayRef< int > Mask)
Checks the given mask, and determines whether said mask is deinterleaving.
static bool isInstructionPairMul(Instruction *A, Instruction *B)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static bool runOnFunction(Function &F, bool PostInlining)
mir Rename Register Operands
This file implements a map that provides insertion order iteration.
PowerPC Reduce CR logical Operation
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI optimize exec mask operations pre RA
static LLVM_ATTRIBUTE_ALWAYS_INLINE bool CheckType(MVT::SimpleValueType VT, SDValue N, const TargetLowering *TLI, const DataLayout &DL)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file describes how to lower LLVM code to machine code.
DEMANGLE_DUMP_METHOD void dump() const
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
InstListType::const_iterator getFirstNonPHIIt() const
Iterator returning form of getFirstNonPHI.
This class represents an Operation in the Expression.
iterator find(const_arg_type_t< KeyT > Val)
bool allowContract() const
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Common base class shared among various IRBuilders.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const Function * getFunction() const
Return the function this instruction belongs to.
FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isIdenticalTo(const Instruction *I) const LLVM_READONLY
Return true if the specified instruction is exactly identical to the current one.
This class implements a map that also provides access to all stored values in a deterministic order.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
This instruction constructs a fixed permutation of two input vectors.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
virtual bool isComplexDeinterleavingOperationSupported(ComplexDeinterleavingOperation Operation, Type *Ty) const
Does this target support complex deinterleaving with the given operation and type.
virtual Value * createComplexDeinterleavingIR(IRBuilderBase &B, ComplexDeinterleavingOperation OperationType, ComplexDeinterleavingRotation Rotation, Value *InputA, Value *InputB, Value *Accumulator=nullptr) const
Create the IR node for the given complex deinterleaving operation.
virtual bool isComplexDeinterleavingSupported() const
Does this target support complex deinterleaving.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
bool isVectorTy() const
True if this is an instance of VectorType.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BR
Control flow instructions. These all have token chains.
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)
Matches a 'Neg' as 'sub 0, V'.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
void initializeComplexDeinterleavingLegacyPassPass(PassRegistry &)
ComplexDeinterleavingOperation
FunctionPass * createComplexDeinterleavingPass(const TargetMachine *TM)
This pass implements generation of target-specific intrinsics to support handling of complex number a...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
ComplexDeinterleavingRotation
DWARFExpression::Operation Op
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...