78using namespace PatternMatch;
80#define DEBUG_TYPE "complex-deinterleaving"
82STATISTIC(NumComplexTransformations,
"Amount of complex patterns transformed");
85 "enable-complex-deinterleaving",
113class ComplexDeinterleavingLegacyPass :
public FunctionPass {
117 ComplexDeinterleavingLegacyPass(
const TargetMachine *TM =
nullptr)
124 return "Complex Deinterleaving Pass";
137class ComplexDeinterleavingGraph;
138struct ComplexDeinterleavingCompositeNode {
145 friend class ComplexDeinterleavingGraph;
146 using NodePtr = std::shared_ptr<ComplexDeinterleavingCompositeNode>;
147 using RawNodePtr = ComplexDeinterleavingCompositeNode *;
157 std::optional<FastMathFlags>
Flags;
160 ComplexDeinterleavingRotation::Rotation_0;
162 Value *ReplacementNode =
nullptr;
168 auto PrintValue = [&](
Value *
V) {
176 auto PrintNodeRef = [&](RawNodePtr
Ptr) {
183 OS <<
"- CompositeNode: " <<
this <<
"\n";
188 OS <<
" ReplacementNode: ";
189 PrintValue(ReplacementNode);
191 OS <<
" Rotation: " << ((int)Rotation * 90) <<
"\n";
192 OS <<
" Operands: \n";
200class ComplexDeinterleavingGraph {
208 using Addend = std::pair<Value *, bool>;
209 using NodePtr = ComplexDeinterleavingCompositeNode::NodePtr;
210 using RawNodePtr = ComplexDeinterleavingCompositeNode::RawNodePtr;
214 struct PartialMulCandidate {
224 : TL(TL), TLI(TLI) {}
235 std::map<Instruction *, NodePtr> RootToNode;
275 bool PHIsFound =
false;
283 std::map<PHINode *, PHINode *> OldToNewPHI;
288 Operation != ComplexDeinterleavingOperation::ReductionOperation) ||
290 "Reduction related nodes must have Real and Imaginary parts");
291 return std::make_shared<ComplexDeinterleavingCompositeNode>(
Operation, R,
295 NodePtr submitCompositeNode(NodePtr
Node) {
320 std::pair<Value *, Value *> &CommonOperandI);
338 NodePtr identifyAdditions(std::list<Addend> &RealAddends,
339 std::list<Addend> &ImagAddends,
340 std::optional<FastMathFlags> Flags,
344 NodePtr extractPositiveAddend(std::list<Addend> &RealAddends,
345 std::list<Addend> &ImagAddends);
350 NodePtr identifyMultiplications(std::vector<Product> &RealMuls,
351 std::vector<Product> &ImagMuls,
357 bool collectPartialMuls(
const std::vector<Product> &RealMuls,
358 const std::vector<Product> &ImagMuls,
359 std::vector<PartialMulCandidate> &Candidates);
384 NodePtr identifySplat(
Value *Real,
Value *Imag);
399 void processReductionOperation(
Value *OperationReplacement, RawNodePtr
Node);
404 for (
const auto &
Node : CompositeNodes)
417 void identifyReductionNodes();
427class ComplexDeinterleaving {
430 : TL(tl), TLI(tli) {}
442char ComplexDeinterleavingLegacyPass::ID = 0;
445 "Complex Deinterleaving",
false,
false)
451 const TargetLowering *TL = TM->getSubtargetImpl(
F)->getTargetLowering();
453 if (!ComplexDeinterleaving(TL, &TLI).runOnFunction(
F))
462 return new ComplexDeinterleavingLegacyPass(TM);
465bool ComplexDeinterleavingLegacyPass::runOnFunction(
Function &
F) {
466 const auto *TL = TM->getSubtargetImpl(
F)->getTargetLowering();
467 auto TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
468 return ComplexDeinterleaving(TL, &TLI).runOnFunction(
F);
471bool ComplexDeinterleaving::runOnFunction(
Function &
F) {
474 dbgs() <<
"Complex deinterleaving has been explicitly disabled.\n");
480 dbgs() <<
"Complex deinterleaving has been disabled, target does "
481 "not support lowering of complex number operations.\n");
485 bool Changed =
false;
487 Changed |= evaluateBasicBlock(&
B);
494 if ((Mask.size() & 1))
497 int HalfNumElements = Mask.size() / 2;
498 for (
int Idx = 0;
Idx < HalfNumElements; ++
Idx) {
499 int MaskIdx =
Idx * 2;
500 if (Mask[MaskIdx] !=
Idx || Mask[MaskIdx + 1] != (
Idx + HalfNumElements))
509 int HalfNumElements = Mask.size() / 2;
511 for (
int Idx = 1;
Idx < HalfNumElements; ++
Idx) {
525 auto *
I = cast<Instruction>(V);
526 if (
I->getOpcode() == Instruction::FNeg)
527 return I->getOperand(0);
529 return I->getOperand(1);
532bool ComplexDeinterleaving::evaluateBasicBlock(
BasicBlock *
B) {
533 ComplexDeinterleavingGraph Graph(TL, TLI);
534 if (Graph.collectPotentialReductions(
B))
535 Graph.identifyReductionNodes();
538 Graph.identifyNodes(&
I);
540 if (Graph.checkNodes()) {
541 Graph.replaceNodes();
548ComplexDeinterleavingGraph::NodePtr
549ComplexDeinterleavingGraph::identifyNodeWithImplicitAdd(
551 std::pair<Value *, Value *> &PartialMatch) {
552 LLVM_DEBUG(
dbgs() <<
"identifyNodeWithImplicitAdd " << *Real <<
" / " << *Imag
560 if ((Real->
getOpcode() != Instruction::FMul &&
561 Real->
getOpcode() != Instruction::Mul) ||
562 (Imag->
getOpcode() != Instruction::FMul &&
563 Imag->
getOpcode() != Instruction::Mul)) {
565 dbgs() <<
" - Real or imaginary instruction is not fmul or mul\n");
598 Value *CommonOperand;
599 Value *UncommonRealOp;
600 Value *UncommonImagOp;
602 if (R0 == I0 || R0 == I1) {
605 }
else if (R1 == I0 || R1 == I1) {
613 UncommonImagOp = (CommonOperand == I0) ? I1 : I0;
614 if (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
615 Rotation == ComplexDeinterleavingRotation::Rotation_270)
616 std::swap(UncommonRealOp, UncommonImagOp);
620 if (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
621 Rotation == ComplexDeinterleavingRotation::Rotation_180)
622 PartialMatch.first = CommonOperand;
624 PartialMatch.second = CommonOperand;
626 if (!PartialMatch.first || !PartialMatch.second) {
631 NodePtr CommonNode = identifyNode(PartialMatch.first, PartialMatch.second);
637 NodePtr UncommonNode = identifyNode(UncommonRealOp, UncommonImagOp);
643 NodePtr
Node = prepareCompositeNode(
644 ComplexDeinterleavingOperation::CMulPartial, Real, Imag);
645 Node->Rotation = Rotation;
646 Node->addOperand(CommonNode);
647 Node->addOperand(UncommonNode);
648 return submitCompositeNode(
Node);
651ComplexDeinterleavingGraph::NodePtr
652ComplexDeinterleavingGraph::identifyPartialMul(
Instruction *Real,
654 LLVM_DEBUG(
dbgs() <<
"identifyPartialMul " << *Real <<
" / " << *Imag
657 auto IsAdd = [](
unsigned Op) {
658 return Op == Instruction::FAdd ||
Op == Instruction::Add;
660 auto IsSub = [](
unsigned Op) {
661 return Op == Instruction::FSub ||
Op == Instruction::Sub;
665 Rotation = ComplexDeinterleavingRotation::Rotation_0;
667 Rotation = ComplexDeinterleavingRotation::Rotation_90;
669 Rotation = ComplexDeinterleavingRotation::Rotation_180;
671 Rotation = ComplexDeinterleavingRotation::Rotation_270;
677 if (isa<FPMathOperator>(Real) &&
680 LLVM_DEBUG(
dbgs() <<
" - Contract is missing from the FastMath flags.\n");
703 Value *CommonOperand;
704 Value *UncommonRealOp;
705 Value *UncommonImagOp;
707 if (R0 == I0 || R0 == I1) {
710 }
else if (R1 == I0 || R1 == I1) {
718 UncommonImagOp = (CommonOperand == I0) ? I1 : I0;
719 if (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
720 Rotation == ComplexDeinterleavingRotation::Rotation_270)
721 std::swap(UncommonRealOp, UncommonImagOp);
723 std::pair<Value *, Value *> PartialMatch(
724 (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
725 Rotation == ComplexDeinterleavingRotation::Rotation_180)
728 (Rotation == ComplexDeinterleavingRotation::Rotation_90 ||
729 Rotation == ComplexDeinterleavingRotation::Rotation_270)
733 auto *CRInst = dyn_cast<Instruction>(CR);
734 auto *CIInst = dyn_cast<Instruction>(CI);
736 if (!CRInst || !CIInst) {
737 LLVM_DEBUG(
dbgs() <<
" - Common operands are not instructions.\n");
741 NodePtr CNode = identifyNodeWithImplicitAdd(CRInst, CIInst, PartialMatch);
747 NodePtr UncommonRes = identifyNode(UncommonRealOp, UncommonImagOp);
753 assert(PartialMatch.first && PartialMatch.second);
754 NodePtr CommonRes = identifyNode(PartialMatch.first, PartialMatch.second);
760 NodePtr
Node = prepareCompositeNode(
761 ComplexDeinterleavingOperation::CMulPartial, Real, Imag);
762 Node->Rotation = Rotation;
763 Node->addOperand(CommonRes);
764 Node->addOperand(UncommonRes);
765 Node->addOperand(CNode);
766 return submitCompositeNode(
Node);
769ComplexDeinterleavingGraph::NodePtr
771 LLVM_DEBUG(
dbgs() <<
"identifyAdd " << *Real <<
" / " << *Imag <<
"\n");
775 if ((Real->
getOpcode() == Instruction::FSub &&
776 Imag->
getOpcode() == Instruction::FAdd) ||
777 (Real->
getOpcode() == Instruction::Sub &&
779 Rotation = ComplexDeinterleavingRotation::Rotation_90;
780 else if ((Real->
getOpcode() == Instruction::FAdd &&
781 Imag->
getOpcode() == Instruction::FSub) ||
782 (Real->
getOpcode() == Instruction::Add &&
784 Rotation = ComplexDeinterleavingRotation::Rotation_270;
786 LLVM_DEBUG(
dbgs() <<
" - Unhandled case, rotation is not assigned.\n");
790 auto *AR = dyn_cast<Instruction>(Real->
getOperand(0));
791 auto *BI = dyn_cast<Instruction>(Real->
getOperand(1));
792 auto *AI = dyn_cast<Instruction>(Imag->
getOperand(0));
795 if (!AR || !AI || !BR || !BI) {
800 NodePtr ResA = identifyNode(AR, AI);
802 LLVM_DEBUG(
dbgs() <<
" - AR/AI is not identified as a composite node.\n");
805 NodePtr ResB = identifyNode(BR, BI);
807 LLVM_DEBUG(
dbgs() <<
" - BR/BI is not identified as a composite node.\n");
812 prepareCompositeNode(ComplexDeinterleavingOperation::CAdd, Real, Imag);
813 Node->Rotation = Rotation;
814 Node->addOperand(ResA);
815 Node->addOperand(ResB);
816 return submitCompositeNode(
Node);
820 unsigned OpcA =
A->getOpcode();
821 unsigned OpcB =
B->getOpcode();
823 return (OpcA == Instruction::FSub && OpcB == Instruction::FAdd) ||
824 (OpcA == Instruction::FAdd && OpcB == Instruction::FSub) ||
825 (OpcA == Instruction::Sub && OpcB == Instruction::Add) ||
826 (OpcA == Instruction::Add && OpcB == Instruction::Sub);
837 switch (
I->getOpcode()) {
838 case Instruction::FAdd:
839 case Instruction::FSub:
840 case Instruction::FMul:
841 case Instruction::FNeg:
842 case Instruction::Add:
843 case Instruction::Sub:
844 case Instruction::Mul:
851ComplexDeinterleavingGraph::NodePtr
852ComplexDeinterleavingGraph::identifySymmetricOperation(
Instruction *Real,
864 NodePtr Op0 = identifyNode(R0, I0);
865 NodePtr Op1 =
nullptr;
872 Op1 = identifyNode(R1, I1);
877 if (isa<FPMathOperator>(Real) &&
881 auto Node = prepareCompositeNode(ComplexDeinterleavingOperation::Symmetric,
884 if (isa<FPMathOperator>(Real))
887 Node->addOperand(Op0);
889 Node->addOperand(Op1);
891 return submitCompositeNode(
Node);
894ComplexDeinterleavingGraph::NodePtr
895ComplexDeinterleavingGraph::identifyNode(
Value *R,
Value *
I) {
897 assert(
R->getType() ==
I->getType() &&
898 "Real and imaginary parts should not have different types");
900 auto It = CachedResult.
find({
R,
I});
901 if (It != CachedResult.
end()) {
906 if (NodePtr CN = identifySplat(R,
I))
909 auto *Real = dyn_cast<Instruction>(R);
910 auto *Imag = dyn_cast<Instruction>(
I);
914 if (NodePtr CN = identifyDeinterleave(Real, Imag))
917 if (NodePtr CN = identifyPHINode(Real, Imag))
920 if (NodePtr CN = identifySelectNode(Real, Imag))
923 auto *VTy = cast<VectorType>(Real->
getType());
924 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
927 ComplexDeinterleavingOperation::CMulPartial, NewVTy);
929 ComplexDeinterleavingOperation::CAdd, NewVTy);
932 if (NodePtr CN = identifyPartialMul(Real, Imag))
937 if (NodePtr CN = identifyAdd(Real, Imag))
941 if (HasCMulSupport && HasCAddSupport) {
942 if (NodePtr CN = identifyReassocNodes(Real, Imag))
946 if (NodePtr CN = identifySymmetricOperation(Real, Imag))
950 CachedResult[{
R,
I}] =
nullptr;
954ComplexDeinterleavingGraph::NodePtr
955ComplexDeinterleavingGraph::identifyReassocNodes(
Instruction *Real,
957 auto IsOperationSupported = [](
unsigned Opcode) ->
bool {
958 return Opcode == Instruction::FAdd || Opcode == Instruction::FSub ||
959 Opcode == Instruction::FNeg || Opcode == Instruction::Add ||
960 Opcode == Instruction::Sub;
963 if (!IsOperationSupported(Real->
getOpcode()) ||
964 !IsOperationSupported(Imag->
getOpcode()))
967 std::optional<FastMathFlags>
Flags;
968 if (isa<FPMathOperator>(Real)) {
970 LLVM_DEBUG(
dbgs() <<
"The flags in Real and Imaginary instructions are "
976 if (!
Flags->allowReassoc()) {
979 <<
"the 'Reassoc' attribute is missing in the FastMath flags\n");
988 std::list<Addend> &Addends) ->
bool {
991 while (!Worklist.
empty()) {
992 auto [
V, IsPositive] = Worklist.
back();
994 if (!Visited.
insert(V).second)
999 Addends.emplace_back(V, IsPositive);
1009 if (
I !=
Insn &&
I->getNumUses() > 1) {
1010 LLVM_DEBUG(
dbgs() <<
"Found potential sub-expression: " << *
I <<
"\n");
1011 Addends.emplace_back(
I, IsPositive);
1014 switch (
I->getOpcode()) {
1015 case Instruction::FAdd:
1016 case Instruction::Add:
1020 case Instruction::FSub:
1024 case Instruction::Sub:
1032 case Instruction::FMul:
1033 case Instruction::Mul: {
1035 if (
isNeg(
I->getOperand(0))) {
1037 IsPositive = !IsPositive;
1039 A =
I->getOperand(0);
1042 if (
isNeg(
I->getOperand(1))) {
1044 IsPositive = !IsPositive;
1046 B =
I->getOperand(1);
1048 Muls.push_back(Product{
A,
B, IsPositive});
1051 case Instruction::FNeg:
1055 Addends.emplace_back(
I, IsPositive);
1059 if (Flags &&
I->getFastMathFlags() != *Flags) {
1061 "inconsistent with the root instructions' flags: "
1069 std::vector<Product> RealMuls, ImagMuls;
1070 std::list<Addend> RealAddends, ImagAddends;
1071 if (!Collect(Real, RealMuls, RealAddends) ||
1072 !Collect(Imag, ImagMuls, ImagAddends))
1075 if (RealAddends.size() != ImagAddends.size())
1079 if (!RealMuls.empty() || !ImagMuls.empty()) {
1082 FinalNode = extractPositiveAddend(RealAddends, ImagAddends);
1083 FinalNode = identifyMultiplications(RealMuls, ImagMuls, FinalNode);
1089 if (!RealAddends.empty() || !ImagAddends.empty()) {
1090 FinalNode = identifyAdditions(RealAddends, ImagAddends, Flags, FinalNode);
1094 assert(FinalNode &&
"FinalNode can not be nullptr here");
1096 FinalNode->Real = Real;
1097 FinalNode->Imag = Imag;
1098 submitCompositeNode(FinalNode);
1102bool ComplexDeinterleavingGraph::collectPartialMuls(
1103 const std::vector<Product> &RealMuls,
const std::vector<Product> &ImagMuls,
1104 std::vector<PartialMulCandidate> &PartialMulCandidates) {
1106 auto FindCommonInstruction = [](
const Product &Real,
1107 const Product &Imag) ->
Value * {
1108 if (Real.Multiplicand == Imag.Multiplicand ||
1109 Real.Multiplicand == Imag.Multiplier)
1110 return Real.Multiplicand;
1112 if (Real.Multiplier == Imag.Multiplicand ||
1113 Real.Multiplier == Imag.Multiplier)
1114 return Real.Multiplier;
1123 for (
unsigned i = 0; i < RealMuls.size(); ++i) {
1124 bool FoundCommon =
false;
1125 for (
unsigned j = 0;
j < ImagMuls.size(); ++
j) {
1126 auto *Common = FindCommonInstruction(RealMuls[i], ImagMuls[j]);
1130 auto *
A = RealMuls[i].Multiplicand == Common ? RealMuls[i].Multiplier
1131 : RealMuls[i].Multiplicand;
1132 auto *
B = ImagMuls[
j].Multiplicand == Common ? ImagMuls[
j].Multiplier
1133 : ImagMuls[
j].Multiplicand;
1135 auto Node = identifyNode(
A,
B);
1138 PartialMulCandidates.push_back({Common,
Node, i,
j,
false});
1141 Node = identifyNode(
B,
A);
1144 PartialMulCandidates.push_back({Common,
Node, i,
j,
true});
1153ComplexDeinterleavingGraph::NodePtr
1154ComplexDeinterleavingGraph::identifyMultiplications(
1155 std::vector<Product> &RealMuls, std::vector<Product> &ImagMuls,
1157 if (RealMuls.size() != ImagMuls.size())
1160 std::vector<PartialMulCandidate>
Info;
1161 if (!collectPartialMuls(RealMuls, ImagMuls, Info))
1165 std::map<Value *, NodePtr> CommonToNode;
1166 std::vector<bool> Processed(
Info.size(),
false);
1167 for (
unsigned I = 0;
I <
Info.size(); ++
I) {
1171 PartialMulCandidate &InfoA =
Info[
I];
1172 for (
unsigned J =
I + 1; J <
Info.size(); ++J) {
1176 PartialMulCandidate &InfoB =
Info[J];
1177 auto *InfoReal = &InfoA;
1178 auto *InfoImag = &InfoB;
1180 auto NodeFromCommon = identifyNode(InfoReal->Common, InfoImag->Common);
1181 if (!NodeFromCommon) {
1183 NodeFromCommon = identifyNode(InfoReal->Common, InfoImag->Common);
1185 if (!NodeFromCommon)
1188 CommonToNode[InfoReal->Common] = NodeFromCommon;
1189 CommonToNode[InfoImag->Common] = NodeFromCommon;
1190 Processed[
I] =
true;
1191 Processed[J] =
true;
1195 std::vector<bool> ProcessedReal(RealMuls.size(),
false);
1196 std::vector<bool> ProcessedImag(ImagMuls.size(),
false);
1198 for (
auto &PMI : Info) {
1199 if (ProcessedReal[PMI.RealIdx] || ProcessedImag[PMI.ImagIdx])
1202 auto It = CommonToNode.find(PMI.Common);
1205 if (It == CommonToNode.end()) {
1207 dbgs() <<
"Unprocessed independent partial multiplication:\n";
1208 for (
auto *
Mul : {&RealMuls[PMI.RealIdx], &RealMuls[PMI.RealIdx]})
1210 <<
" multiplied by " << *
Mul->Multiplicand <<
"\n";
1215 auto &RealMul = RealMuls[PMI.RealIdx];
1216 auto &ImagMul = ImagMuls[PMI.ImagIdx];
1218 auto NodeA = It->second;
1219 auto NodeB = PMI.Node;
1220 auto IsMultiplicandReal = PMI.Common == NodeA->Real;
1235 if ((IsMultiplicandReal && PMI.IsNodeInverted) ||
1236 (!IsMultiplicandReal && !PMI.IsNodeInverted))
1241 if (IsMultiplicandReal) {
1243 if (RealMul.IsPositive && ImagMul.IsPositive)
1245 else if (!RealMul.IsPositive && !ImagMul.IsPositive)
1252 if (!RealMul.IsPositive && ImagMul.IsPositive)
1254 else if (RealMul.IsPositive && !ImagMul.IsPositive)
1261 dbgs() <<
"Identified partial multiplication (X, Y) * (U, V):\n";
1262 dbgs().
indent(4) <<
"X: " << *NodeA->Real <<
"\n";
1263 dbgs().
indent(4) <<
"Y: " << *NodeA->Imag <<
"\n";
1264 dbgs().
indent(4) <<
"U: " << *NodeB->Real <<
"\n";
1265 dbgs().
indent(4) <<
"V: " << *NodeB->Imag <<
"\n";
1266 dbgs().
indent(4) <<
"Rotation - " << (int)Rotation * 90 <<
"\n";
1269 NodePtr NodeMul = prepareCompositeNode(
1270 ComplexDeinterleavingOperation::CMulPartial,
nullptr,
nullptr);
1271 NodeMul->Rotation = Rotation;
1272 NodeMul->addOperand(NodeA);
1273 NodeMul->addOperand(NodeB);
1275 NodeMul->addOperand(Result);
1276 submitCompositeNode(NodeMul);
1278 ProcessedReal[PMI.RealIdx] =
true;
1279 ProcessedImag[PMI.ImagIdx] =
true;
1283 if (!
all_of(ProcessedReal, [](
bool V) {
return V; }) ||
1284 !
all_of(ProcessedImag, [](
bool V) {
return V; })) {
1289 dbgs() <<
"Unprocessed products (Real):\n";
1290 for (
size_t i = 0; i < ProcessedReal.size(); ++i) {
1291 if (!ProcessedReal[i])
1292 dbgs().
indent(4) << (RealMuls[i].IsPositive ?
"+" :
"-")
1293 << *RealMuls[i].Multiplier <<
" multiplied by "
1294 << *RealMuls[i].Multiplicand <<
"\n";
1296 dbgs() <<
"Unprocessed products (Imag):\n";
1297 for (
size_t i = 0; i < ProcessedImag.size(); ++i) {
1298 if (!ProcessedImag[i])
1299 dbgs().
indent(4) << (ImagMuls[i].IsPositive ?
"+" :
"-")
1300 << *ImagMuls[i].Multiplier <<
" multiplied by "
1301 << *ImagMuls[i].Multiplicand <<
"\n";
1310ComplexDeinterleavingGraph::NodePtr
1311ComplexDeinterleavingGraph::identifyAdditions(
1312 std::list<Addend> &RealAddends, std::list<Addend> &ImagAddends,
1313 std::optional<FastMathFlags> Flags, NodePtr
Accumulator =
nullptr) {
1314 if (RealAddends.size() != ImagAddends.size())
1323 Result = extractPositiveAddend(RealAddends, ImagAddends);
1328 while (!RealAddends.empty()) {
1329 auto ItR = RealAddends.begin();
1330 auto [
R, IsPositiveR] = *ItR;
1332 bool FoundImag =
false;
1333 for (
auto ItI = ImagAddends.begin(); ItI != ImagAddends.end(); ++ItI) {
1334 auto [
I, IsPositiveI] = *ItI;
1336 if (IsPositiveR && IsPositiveI)
1337 Rotation = ComplexDeinterleavingRotation::Rotation_0;
1338 else if (!IsPositiveR && IsPositiveI)
1339 Rotation = ComplexDeinterleavingRotation::Rotation_90;
1340 else if (!IsPositiveR && !IsPositiveI)
1341 Rotation = ComplexDeinterleavingRotation::Rotation_180;
1343 Rotation = ComplexDeinterleavingRotation::Rotation_270;
1346 if (Rotation == ComplexDeinterleavingRotation::Rotation_0 ||
1347 Rotation == ComplexDeinterleavingRotation::Rotation_180) {
1348 AddNode = identifyNode(R,
I);
1350 AddNode = identifyNode(
I, R);
1354 dbgs() <<
"Identified addition:\n";
1357 dbgs().
indent(4) <<
"Rotation - " << (int)Rotation * 90 <<
"\n";
1362 TmpNode = prepareCompositeNode(
1363 ComplexDeinterleavingOperation::Symmetric,
nullptr,
nullptr);
1365 TmpNode->Opcode = Instruction::FAdd;
1366 TmpNode->Flags = *
Flags;
1368 TmpNode->Opcode = Instruction::Add;
1370 }
else if (Rotation ==
1372 TmpNode = prepareCompositeNode(
1373 ComplexDeinterleavingOperation::Symmetric,
nullptr,
nullptr);
1375 TmpNode->Opcode = Instruction::FSub;
1376 TmpNode->Flags = *
Flags;
1378 TmpNode->Opcode = Instruction::Sub;
1381 TmpNode = prepareCompositeNode(ComplexDeinterleavingOperation::CAdd,
1383 TmpNode->Rotation = Rotation;
1386 TmpNode->addOperand(Result);
1387 TmpNode->addOperand(AddNode);
1388 submitCompositeNode(TmpNode);
1390 RealAddends.erase(ItR);
1391 ImagAddends.erase(ItI);
1402ComplexDeinterleavingGraph::NodePtr
1403ComplexDeinterleavingGraph::extractPositiveAddend(
1404 std::list<Addend> &RealAddends, std::list<Addend> &ImagAddends) {
1405 for (
auto ItR = RealAddends.begin(); ItR != RealAddends.end(); ++ItR) {
1406 for (
auto ItI = ImagAddends.begin(); ItI != ImagAddends.end(); ++ItI) {
1407 auto [
R, IsPositiveR] = *ItR;
1408 auto [
I, IsPositiveI] = *ItI;
1409 if (IsPositiveR && IsPositiveI) {
1410 auto Result = identifyNode(R,
I);
1412 RealAddends.erase(ItR);
1413 ImagAddends.erase(ItI);
1422bool ComplexDeinterleavingGraph::identifyNodes(
Instruction *RootI) {
1427 auto It = RootToNode.find(RootI);
1428 if (It != RootToNode.end()) {
1429 auto RootNode = It->second;
1430 assert(RootNode->Operation ==
1431 ComplexDeinterleavingOperation::ReductionOperation);
1434 auto *
R = cast<Instruction>(RootNode->Real);
1435 auto *
I = cast<Instruction>(RootNode->Imag);
1436 auto *ReplacementAnchor =
R->comesBefore(
I) ?
I :
R;
1437 if (ReplacementAnchor != RootI)
1443 auto RootNode = identifyRoot(RootI);
1450 dbgs() <<
"Complex deinterleaving graph for " <<
F->getName()
1451 <<
"::" <<
B->getName() <<
".\n";
1455 RootToNode[RootI] = RootNode;
1460bool ComplexDeinterleavingGraph::collectPotentialReductions(
BasicBlock *
B) {
1461 bool FoundPotentialReduction =
false;
1463 auto *Br = dyn_cast<BranchInst>(
B->getTerminator());
1464 if (!Br || Br->getNumSuccessors() != 2)
1468 if (Br->getSuccessor(0) !=
B && Br->getSuccessor(1) !=
B)
1472 for (
auto &
PHI :
B->phis()) {
1473 if (
PHI.getNumIncomingValues() != 2)
1476 if (!
PHI.getType()->isVectorTy())
1479 auto *ReductionOp = dyn_cast<Instruction>(
PHI.getIncomingValueForBlock(
B));
1486 for (
auto *U : ReductionOp->users()) {
1490 FinalReduction = dyn_cast<Instruction>(U);
1493 if (NumUsers != 2 || !FinalReduction || FinalReduction->
getParent() ==
B ||
1494 isa<PHINode>(FinalReduction))
1497 ReductionInfo[ReductionOp] = {&
PHI, FinalReduction};
1499 auto BackEdgeIdx =
PHI.getBasicBlockIndex(
B);
1500 auto IncomingIdx = BackEdgeIdx == 0 ? 1 : 0;
1502 FoundPotentialReduction =
true;
1507 dyn_cast<Instruction>(
PHI.getIncomingValueForBlock(
Incoming)))
1508 FinalInstructions.
insert(InitPHI);
1510 return FoundPotentialReduction;
1513void ComplexDeinterleavingGraph::identifyReductionNodes() {
1516 for (
auto &
P : ReductionInfo)
1521 for (
size_t i = 0; i < OperationInstruction.
size(); ++i) {
1524 for (
size_t j = i + 1;
j < OperationInstruction.
size(); ++
j) {
1528 auto *Real = OperationInstruction[i];
1529 auto *Imag = OperationInstruction[
j];
1530 if (Real->getType() != Imag->
getType())
1533 RealPHI = ReductionInfo[Real].first;
1534 ImagPHI = ReductionInfo[Imag].first;
1536 auto Node = identifyNode(Real, Imag);
1540 Node = identifyNode(Real, Imag);
1546 if (
Node && PHIsFound) {
1547 LLVM_DEBUG(
dbgs() <<
"Identified reduction starting from instructions: "
1548 << *Real <<
" / " << *Imag <<
"\n");
1549 Processed[i] =
true;
1550 Processed[
j] =
true;
1551 auto RootNode = prepareCompositeNode(
1552 ComplexDeinterleavingOperation::ReductionOperation, Real, Imag);
1553 RootNode->addOperand(
Node);
1554 RootToNode[Real] = RootNode;
1555 RootToNode[Imag] = RootNode;
1556 submitCompositeNode(RootNode);
1566bool ComplexDeinterleavingGraph::checkNodes() {
1570 for (
auto &Pair : RootToNode)
1575 while (!Worklist.
empty()) {
1576 auto *
I = Worklist.
back();
1579 if (!AllInstructions.
insert(
I).second)
1583 if (
auto *OpI = dyn_cast<Instruction>(
Op)) {
1584 if (!FinalInstructions.
count(
I))
1592 for (
auto *
I : AllInstructions) {
1594 if (RootToNode.count(
I))
1597 for (
User *U :
I->users()) {
1598 if (AllInstructions.count(cast<Instruction>(U)))
1610 while (!Worklist.
empty()) {
1611 auto *
I = Worklist.
back();
1613 if (!Visited.
insert(
I).second)
1618 if (RootToNode.count(
I)) {
1620 <<
" could be deinterleaved but its chain of complex "
1621 "operations have an outside user\n");
1622 RootToNode.erase(
I);
1625 if (!AllInstructions.count(
I) || FinalInstructions.
count(
I))
1628 for (
User *U :
I->users())
1632 if (
auto *OpI = dyn_cast<Instruction>(
Op))
1636 return !RootToNode.empty();
1639ComplexDeinterleavingGraph::NodePtr
1640ComplexDeinterleavingGraph::identifyRoot(
Instruction *RootI) {
1641 if (
auto *Intrinsic = dyn_cast<IntrinsicInst>(RootI)) {
1642 if (
Intrinsic->getIntrinsicID() != Intrinsic::vector_interleave2)
1645 auto *Real = dyn_cast<Instruction>(
Intrinsic->getOperand(0));
1646 auto *Imag = dyn_cast<Instruction>(
Intrinsic->getOperand(1));
1650 return identifyNode(Real, Imag);
1653 auto *SVI = dyn_cast<ShuffleVectorInst>(RootI);
1667 return identifyNode(Real, Imag);
1670ComplexDeinterleavingGraph::NodePtr
1671ComplexDeinterleavingGraph::identifyDeinterleave(
Instruction *Real,
1674 Value *FinalValue =
nullptr;
1677 match(
I, m_Intrinsic<Intrinsic::vector_deinterleave2>(
1679 NodePtr PlaceholderNode = prepareCompositeNode(
1681 PlaceholderNode->ReplacementNode = FinalValue;
1682 FinalInstructions.
insert(Real);
1683 FinalInstructions.
insert(Imag);
1684 return submitCompositeNode(PlaceholderNode);
1687 auto *RealShuffle = dyn_cast<ShuffleVectorInst>(Real);
1688 auto *ImagShuffle = dyn_cast<ShuffleVectorInst>(Imag);
1689 if (!RealShuffle || !ImagShuffle) {
1690 if (RealShuffle || ImagShuffle)
1691 LLVM_DEBUG(
dbgs() <<
" - There's a shuffle where there shouldn't be.\n");
1695 Value *RealOp1 = RealShuffle->getOperand(1);
1696 if (!isa<UndefValue>(RealOp1) && !isa<ConstantAggregateZero>(RealOp1)) {
1700 Value *ImagOp1 = ImagShuffle->getOperand(1);
1701 if (!isa<UndefValue>(ImagOp1) && !isa<ConstantAggregateZero>(ImagOp1)) {
1706 Value *RealOp0 = RealShuffle->getOperand(0);
1707 Value *ImagOp0 = ImagShuffle->getOperand(0);
1709 if (RealOp0 != ImagOp0) {
1721 if (RealMask[0] != 0 || ImagMask[0] != 1) {
1722 LLVM_DEBUG(
dbgs() <<
" - Masks do not have the correct initial value.\n");
1729 Value *
Op = Shuffle->getOperand(0);
1730 auto *ShuffleTy = cast<FixedVectorType>(Shuffle->getType());
1731 auto *OpTy = cast<FixedVectorType>(
Op->getType());
1733 if (OpTy->getScalarType() != ShuffleTy->getScalarType())
1735 if ((ShuffleTy->getNumElements() * 2) != OpTy->getNumElements())
1748 Value *
Op = Shuffle->getOperand(0);
1749 auto *OpTy = cast<FixedVectorType>(
Op->getType());
1750 int NumElements = OpTy->getNumElements();
1754 return Last < NumElements;
1757 if (RealShuffle->getType() != ImagShuffle->getType()) {
1761 if (!CheckDeinterleavingShuffle(RealShuffle)) {
1765 if (!CheckDeinterleavingShuffle(ImagShuffle)) {
1770 NodePtr PlaceholderNode =
1772 RealShuffle, ImagShuffle);
1773 PlaceholderNode->ReplacementNode = RealShuffle->getOperand(0);
1774 FinalInstructions.
insert(RealShuffle);
1775 FinalInstructions.
insert(ImagShuffle);
1776 return submitCompositeNode(PlaceholderNode);
1779ComplexDeinterleavingGraph::NodePtr
1780ComplexDeinterleavingGraph::identifySplat(
Value *R,
Value *
I) {
1781 auto IsSplat = [](
Value *
V) ->
bool {
1783 if (isa<ConstantDataVector>(V))
1790 if (
auto *Const = dyn_cast<ConstantExpr>(V)) {
1791 if (
Const->getOpcode() != Instruction::ShuffleVector)
1793 VTy = cast<VectorType>(
Const->getType());
1795 }
else if (
auto *Shuf = dyn_cast<ShuffleVectorInst>(V)) {
1796 VTy = Shuf->getType();
1797 Mask = Shuf->getShuffleMask();
1805 if (!VTy->isScalableTy() && VTy->getElementCount().getKnownMinValue() == 1)
1811 if (!IsSplat(R) || !IsSplat(
I))
1814 auto *Real = dyn_cast<Instruction>(R);
1815 auto *Imag = dyn_cast<Instruction>(
I);
1816 if ((!Real && Imag) || (Real && !Imag))
1824 FinalInstructions.
insert(Real);
1825 FinalInstructions.
insert(Imag);
1827 NodePtr PlaceholderNode =
1828 prepareCompositeNode(ComplexDeinterleavingOperation::Splat, R,
I);
1829 return submitCompositeNode(PlaceholderNode);
1832ComplexDeinterleavingGraph::NodePtr
1833ComplexDeinterleavingGraph::identifyPHINode(
Instruction *Real,
1835 if (Real != RealPHI || Imag != ImagPHI)
1839 NodePtr PlaceholderNode = prepareCompositeNode(
1840 ComplexDeinterleavingOperation::ReductionPHI, Real, Imag);
1841 return submitCompositeNode(PlaceholderNode);
1844ComplexDeinterleavingGraph::NodePtr
1845ComplexDeinterleavingGraph::identifySelectNode(
Instruction *Real,
1847 auto *SelectReal = dyn_cast<SelectInst>(Real);
1848 auto *SelectImag = dyn_cast<SelectInst>(Imag);
1849 if (!SelectReal || !SelectImag)
1866 auto NodeA = identifyNode(AR, AI);
1870 auto NodeB = identifyNode(
RA, BI);
1874 NodePtr PlaceholderNode = prepareCompositeNode(
1875 ComplexDeinterleavingOperation::ReductionSelect, Real, Imag);
1876 PlaceholderNode->addOperand(NodeA);
1877 PlaceholderNode->addOperand(NodeB);
1878 FinalInstructions.
insert(MaskA);
1879 FinalInstructions.
insert(MaskB);
1880 return submitCompositeNode(PlaceholderNode);
1884 std::optional<FastMathFlags> Flags,
1888 case Instruction::FNeg:
1889 I =
B.CreateFNeg(InputA);
1891 case Instruction::FAdd:
1892 I =
B.CreateFAdd(InputA, InputB);
1894 case Instruction::Add:
1895 I =
B.CreateAdd(InputA, InputB);
1897 case Instruction::FSub:
1898 I =
B.CreateFSub(InputA, InputB);
1900 case Instruction::Sub:
1901 I =
B.CreateSub(InputA, InputB);
1903 case Instruction::FMul:
1904 I =
B.CreateFMul(InputA, InputB);
1906 case Instruction::Mul:
1907 I =
B.CreateMul(InputA, InputB);
1913 cast<Instruction>(
I)->setFastMathFlags(*Flags);
1919 if (
Node->ReplacementNode)
1920 return Node->ReplacementNode;
1922 auto ReplaceOperandIfExist = [&](RawNodePtr &
Node,
unsigned Idx) ->
Value * {
1923 return Node->Operands.size() >
Idx
1924 ? replaceNode(Builder,
Node->Operands[
Idx])
1928 Value *ReplacementNode;
1929 switch (
Node->Operation) {
1930 case ComplexDeinterleavingOperation::CAdd:
1931 case ComplexDeinterleavingOperation::CMulPartial:
1932 case ComplexDeinterleavingOperation::Symmetric: {
1933 Value *Input0 = ReplaceOperandIfExist(
Node, 0);
1934 Value *Input1 = ReplaceOperandIfExist(
Node, 1);
1937 "Node inputs need to be of the same type"));
1940 "Accumulator and input need to be of the same type"));
1941 if (
Node->Operation == ComplexDeinterleavingOperation::Symmetric)
1946 Builder,
Node->Operation,
Node->Rotation, Input0, Input1,
1950 case ComplexDeinterleavingOperation::Deinterleave:
1953 case ComplexDeinterleavingOperation::Splat: {
1954 auto *NewTy = VectorType::getDoubleElementsVectorType(
1955 cast<VectorType>(
Node->Real->getType()));
1956 auto *
R = dyn_cast<Instruction>(
Node->Real);
1957 auto *
I = dyn_cast<Instruction>(
Node->Imag);
1962 ReplacementNode = IRB.CreateIntrinsic(Intrinsic::vector_interleave2,
1966 Intrinsic::vector_interleave2, NewTy, {
Node->Real,
Node->Imag});
1970 case ComplexDeinterleavingOperation::ReductionPHI: {
1973 auto *VTy = cast<VectorType>(
Node->Real->getType());
1974 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
1976 OldToNewPHI[dyn_cast<PHINode>(
Node->Real)] = NewPHI;
1977 ReplacementNode = NewPHI;
1980 case ComplexDeinterleavingOperation::ReductionOperation:
1981 ReplacementNode = replaceNode(Builder,
Node->Operands[0]);
1982 processReductionOperation(ReplacementNode,
Node);
1984 case ComplexDeinterleavingOperation::ReductionSelect: {
1985 auto *MaskReal = cast<Instruction>(
Node->Real)->getOperand(0);
1986 auto *MaskImag = cast<Instruction>(
Node->Imag)->getOperand(0);
1987 auto *
A = replaceNode(Builder,
Node->Operands[0]);
1988 auto *
B = replaceNode(Builder,
Node->Operands[1]);
1989 auto *NewMaskTy = VectorType::getDoubleElementsVectorType(
1990 cast<VectorType>(MaskReal->getType()));
1991 auto *NewMask = Builder.
CreateIntrinsic(Intrinsic::vector_interleave2,
1992 NewMaskTy, {MaskReal, MaskImag});
1998 assert(ReplacementNode &&
"Target failed to create Intrinsic call.");
1999 NumComplexTransformations += 1;
2000 Node->ReplacementNode = ReplacementNode;
2001 return ReplacementNode;
2004void ComplexDeinterleavingGraph::processReductionOperation(
2005 Value *OperationReplacement, RawNodePtr
Node) {
2006 auto *Real = cast<Instruction>(
Node->Real);
2007 auto *Imag = cast<Instruction>(
Node->Imag);
2008 auto *OldPHIReal = ReductionInfo[Real].first;
2009 auto *OldPHIImag = ReductionInfo[Imag].first;
2010 auto *NewPHI = OldToNewPHI[OldPHIReal];
2012 auto *VTy = cast<VectorType>(Real->
getType());
2013 auto *NewVTy = VectorType::getDoubleElementsVectorType(VTy);
2016 Value *InitReal = OldPHIReal->getIncomingValueForBlock(
Incoming);
2017 Value *InitImag = OldPHIImag->getIncomingValueForBlock(
Incoming);
2020 auto *NewInit = Builder.
CreateIntrinsic(Intrinsic::vector_interleave2, NewVTy,
2021 {InitReal, InitImag});
2023 NewPHI->addIncoming(NewInit,
Incoming);
2024 NewPHI->addIncoming(OperationReplacement, BackEdge);
2028 auto *FinalReductionReal = ReductionInfo[Real].second;
2029 auto *FinalReductionImag = ReductionInfo[Imag].second;
2032 &*FinalReductionReal->getParent()->getFirstInsertionPt());
2034 OperationReplacement->
getType(),
2035 OperationReplacement);
2038 FinalReductionReal->replaceUsesOfWith(Real, NewReal);
2042 FinalReductionImag->replaceUsesOfWith(Imag, NewImag);
2045void ComplexDeinterleavingGraph::replaceNodes() {
2047 for (
auto *RootInstruction : OrderedRoots) {
2050 if (!RootToNode.count(RootInstruction))
2054 auto RootNode = RootToNode[RootInstruction];
2055 Value *
R = replaceNode(Builder, RootNode.get());
2057 if (RootNode->Operation ==
2058 ComplexDeinterleavingOperation::ReductionOperation) {
2059 auto *RootReal = cast<Instruction>(RootNode->Real);
2060 auto *RootImag = cast<Instruction>(RootNode->Imag);
2061 ReductionInfo[RootReal].first->removeIncomingValue(BackEdge);
2062 ReductionInfo[RootImag].first->removeIncomingValue(BackEdge);
2063 DeadInstrRoots.
push_back(cast<Instruction>(RootReal));
2064 DeadInstrRoots.
push_back(cast<Instruction>(RootImag));
2066 assert(R &&
"Unable to find replacement for RootInstruction");
2067 DeadInstrRoots.
push_back(RootInstruction);
2068 RootInstruction->replaceAllUsesWith(R);
2072 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.
Target-Independent Code Generator Pass Configuration Options pass.
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...