18bb94433SThorsten Schütt //===- CombinerHelperVectorOps.cpp-----------------------------------------===// 28bb94433SThorsten Schütt // 38bb94433SThorsten Schütt // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 48bb94433SThorsten Schütt // See https://llvm.org/LICENSE.txt for license information. 58bb94433SThorsten Schütt // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 68bb94433SThorsten Schütt // 78bb94433SThorsten Schütt //===----------------------------------------------------------------------===// 88bb94433SThorsten Schütt // 99b692e56SThorsten Schütt // This file implements CombinerHelper for G_EXTRACT_VECTOR_ELT, 109b692e56SThorsten Schütt // G_INSERT_VECTOR_ELT, and G_VSCALE 118bb94433SThorsten Schütt // 128bb94433SThorsten Schütt //===----------------------------------------------------------------------===// 138bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 148bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 158bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 168bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 178bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" 188bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 198bb94433SThorsten Schütt #include "llvm/CodeGen/GlobalISel/Utils.h" 208bb94433SThorsten Schütt #include "llvm/CodeGen/LowLevelTypeUtils.h" 218bb94433SThorsten Schütt #include "llvm/CodeGen/MachineOperand.h" 228bb94433SThorsten Schütt #include "llvm/CodeGen/MachineRegisterInfo.h" 238bb94433SThorsten Schütt #include "llvm/CodeGen/TargetLowering.h" 248bb94433SThorsten Schütt #include "llvm/CodeGen/TargetOpcodes.h" 258bb94433SThorsten Schütt #include "llvm/Support/Casting.h" 268bb94433SThorsten Schütt #include <optional> 278bb94433SThorsten Schütt 288bb94433SThorsten Schütt #define DEBUG_TYPE "gi-combiner" 298bb94433SThorsten Schütt 308bb94433SThorsten Schütt using namespace llvm; 318bb94433SThorsten Schütt using namespace MIPatternMatch; 328bb94433SThorsten Schütt 338bb94433SThorsten Schütt bool CombinerHelper::matchExtractVectorElement(MachineInstr &MI, 34*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 358bb94433SThorsten Schütt GExtractVectorElement *Extract = cast<GExtractVectorElement>(&MI); 368bb94433SThorsten Schütt 378bb94433SThorsten Schütt Register Dst = Extract->getReg(0); 388bb94433SThorsten Schütt Register Vector = Extract->getVectorReg(); 398bb94433SThorsten Schütt Register Index = Extract->getIndexReg(); 408bb94433SThorsten Schütt LLT DstTy = MRI.getType(Dst); 418bb94433SThorsten Schütt LLT VectorTy = MRI.getType(Vector); 428bb94433SThorsten Schütt 438bb94433SThorsten Schütt // The vector register can be def'd by various ops that have vector as its 448bb94433SThorsten Schütt // type. They can all be used for constant folding, scalarizing, 458bb94433SThorsten Schütt // canonicalization, or combining based on symmetry. 468bb94433SThorsten Schütt // 478bb94433SThorsten Schütt // vector like ops 488bb94433SThorsten Schütt // * build vector 498bb94433SThorsten Schütt // * build vector trunc 508bb94433SThorsten Schütt // * shuffle vector 518bb94433SThorsten Schütt // * splat vector 528bb94433SThorsten Schütt // * concat vectors 538bb94433SThorsten Schütt // * insert/extract vector element 548bb94433SThorsten Schütt // * insert/extract subvector 558bb94433SThorsten Schütt // * vector loads 568bb94433SThorsten Schütt // * scalable vector loads 578bb94433SThorsten Schütt // 588bb94433SThorsten Schütt // compute like ops 598bb94433SThorsten Schütt // * binary ops 608bb94433SThorsten Schütt // * unary ops 618bb94433SThorsten Schütt // * exts and truncs 628bb94433SThorsten Schütt // * casts 638bb94433SThorsten Schütt // * fneg 648bb94433SThorsten Schütt // * select 658bb94433SThorsten Schütt // * phis 668bb94433SThorsten Schütt // * cmps 678bb94433SThorsten Schütt // * freeze 688bb94433SThorsten Schütt // * bitcast 698bb94433SThorsten Schütt // * undef 708bb94433SThorsten Schütt 718bb94433SThorsten Schütt // We try to get the value of the Index register. 728bb94433SThorsten Schütt std::optional<ValueAndVReg> MaybeIndex = 738bb94433SThorsten Schütt getIConstantVRegValWithLookThrough(Index, MRI); 748bb94433SThorsten Schütt std::optional<APInt> IndexC = std::nullopt; 758bb94433SThorsten Schütt 768bb94433SThorsten Schütt if (MaybeIndex) 778bb94433SThorsten Schütt IndexC = MaybeIndex->Value; 788bb94433SThorsten Schütt 798bb94433SThorsten Schütt // Fold extractVectorElement(Vector, TOOLARGE) -> undef 808bb94433SThorsten Schütt if (IndexC && VectorTy.isFixedVector() && 81bc349ceaSThorsten Schütt IndexC->uge(VectorTy.getNumElements()) && 828bb94433SThorsten Schütt isLegalOrBeforeLegalizer({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) { 838bb94433SThorsten Schütt // For fixed-length vectors, it's invalid to extract out-of-range elements. 848bb94433SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { B.buildUndef(Dst); }; 858bb94433SThorsten Schütt return true; 868bb94433SThorsten Schütt } 878bb94433SThorsten Schütt 888bb94433SThorsten Schütt return false; 898bb94433SThorsten Schütt } 908bb94433SThorsten Schütt 918bb94433SThorsten Schütt bool CombinerHelper::matchExtractVectorElementWithDifferentIndices( 92*ee7ca0ddSPaul Bowen-Huggett const MachineOperand &MO, BuildFnTy &MatchInfo) const { 938bb94433SThorsten Schütt MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); 948bb94433SThorsten Schütt GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); 958bb94433SThorsten Schütt 968bb94433SThorsten Schütt // 978bb94433SThorsten Schütt // %idx1:_(s64) = G_CONSTANT i64 1 988bb94433SThorsten Schütt // %idx2:_(s64) = G_CONSTANT i64 2 998bb94433SThorsten Schütt // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), 1008bb94433SThorsten Schütt // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %insert(<2 1018bb94433SThorsten Schütt // x s32>), %idx1(s64) 1028bb94433SThorsten Schütt // 1038bb94433SThorsten Schütt // --> 1048bb94433SThorsten Schütt // 1058bb94433SThorsten Schütt // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), 1068bb94433SThorsten Schütt // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x 1078bb94433SThorsten Schütt // s32>), %idx1(s64) 1088bb94433SThorsten Schütt // 1098bb94433SThorsten Schütt // 1108bb94433SThorsten Schütt 1118bb94433SThorsten Schütt Register Index = Extract->getIndexReg(); 1128bb94433SThorsten Schütt 1138bb94433SThorsten Schütt // We try to get the value of the Index register. 1148bb94433SThorsten Schütt std::optional<ValueAndVReg> MaybeIndex = 1158bb94433SThorsten Schütt getIConstantVRegValWithLookThrough(Index, MRI); 1168bb94433SThorsten Schütt std::optional<APInt> IndexC = std::nullopt; 1178bb94433SThorsten Schütt 1188bb94433SThorsten Schütt if (!MaybeIndex) 1198bb94433SThorsten Schütt return false; 1208bb94433SThorsten Schütt else 1218bb94433SThorsten Schütt IndexC = MaybeIndex->Value; 1228bb94433SThorsten Schütt 1238bb94433SThorsten Schütt Register Vector = Extract->getVectorReg(); 1248bb94433SThorsten Schütt 1258bb94433SThorsten Schütt GInsertVectorElement *Insert = 1268bb94433SThorsten Schütt getOpcodeDef<GInsertVectorElement>(Vector, MRI); 1278bb94433SThorsten Schütt if (!Insert) 1288bb94433SThorsten Schütt return false; 1298bb94433SThorsten Schütt 1308bb94433SThorsten Schütt Register Dst = Extract->getReg(0); 1318bb94433SThorsten Schütt 1328bb94433SThorsten Schütt std::optional<ValueAndVReg> MaybeInsertIndex = 1338bb94433SThorsten Schütt getIConstantVRegValWithLookThrough(Insert->getIndexReg(), MRI); 1348bb94433SThorsten Schütt 1358bb94433SThorsten Schütt if (MaybeInsertIndex && MaybeInsertIndex->Value != *IndexC) { 1368bb94433SThorsten Schütt // There is no one-use check. We have to keep the insert. When both Index 1378bb94433SThorsten Schütt // registers are constants and not equal, we can look into the Vector 1388bb94433SThorsten Schütt // register of the insert. 1398bb94433SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 1408bb94433SThorsten Schütt B.buildExtractVectorElement(Dst, Insert->getVectorReg(), Index); 1418bb94433SThorsten Schütt }; 1428bb94433SThorsten Schütt return true; 1438bb94433SThorsten Schütt } 1448bb94433SThorsten Schütt 1458bb94433SThorsten Schütt return false; 1468bb94433SThorsten Schütt } 1478bb94433SThorsten Schütt 1488bb94433SThorsten Schütt bool CombinerHelper::matchExtractVectorElementWithBuildVector( 149*ee7ca0ddSPaul Bowen-Huggett const MachineInstr &MI, const MachineInstr &MI2, 150*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 151ccfe7d4bSThorsten Schütt const GExtractVectorElement *Extract = cast<GExtractVectorElement>(&MI); 152ccfe7d4bSThorsten Schütt const GBuildVector *Build = cast<GBuildVector>(&MI2); 1538bb94433SThorsten Schütt 1548bb94433SThorsten Schütt // 1558bb94433SThorsten Schütt // %zero:_(s64) = G_CONSTANT i64 0 1568bb94433SThorsten Schütt // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) 1578bb94433SThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) 1588bb94433SThorsten Schütt // 1598bb94433SThorsten Schütt // --> 1608bb94433SThorsten Schütt // 1618bb94433SThorsten Schütt // %extract:_(32) = COPY %arg1(s32) 1628bb94433SThorsten Schütt // 1638bb94433SThorsten Schütt // 1648bb94433SThorsten Schütt 1658bb94433SThorsten Schütt Register Vector = Extract->getVectorReg(); 1668bb94433SThorsten Schütt LLT VectorTy = MRI.getType(Vector); 1678bb94433SThorsten Schütt 1688bb94433SThorsten Schütt // There is a one-use check. There are more combines on build vectors. 1698bb94433SThorsten Schütt EVT Ty(getMVTForLLT(VectorTy)); 1708bb94433SThorsten Schütt if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || 1718bb94433SThorsten Schütt !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) 1728bb94433SThorsten Schütt return false; 1738bb94433SThorsten Schütt 174ccfe7d4bSThorsten Schütt APInt Index = getIConstantFromReg(Extract->getIndexReg(), MRI); 1758bb94433SThorsten Schütt 1768bb94433SThorsten Schütt // We now know that there is a buildVector def'd on the Vector register and 1778bb94433SThorsten Schütt // the index is const. The combine will succeed. 1788bb94433SThorsten Schütt 1798bb94433SThorsten Schütt Register Dst = Extract->getReg(0); 1808bb94433SThorsten Schütt 1818bb94433SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 182ccfe7d4bSThorsten Schütt B.buildCopy(Dst, Build->getSourceReg(Index.getZExtValue())); 1838bb94433SThorsten Schütt }; 1848bb94433SThorsten Schütt 1858bb94433SThorsten Schütt return true; 1868bb94433SThorsten Schütt } 1878bb94433SThorsten Schütt 1888bb94433SThorsten Schütt bool CombinerHelper::matchExtractVectorElementWithBuildVectorTrunc( 189*ee7ca0ddSPaul Bowen-Huggett const MachineOperand &MO, BuildFnTy &MatchInfo) const { 1908bb94433SThorsten Schütt MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); 1918bb94433SThorsten Schütt GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); 1928bb94433SThorsten Schütt 1938bb94433SThorsten Schütt // 1948bb94433SThorsten Schütt // %zero:_(s64) = G_CONSTANT i64 0 1958bb94433SThorsten Schütt // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 1968bb94433SThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) 1978bb94433SThorsten Schütt // 1988bb94433SThorsten Schütt // --> 1998bb94433SThorsten Schütt // 2008bb94433SThorsten Schütt // %extract:_(32) = G_TRUNC %arg1(s64) 2018bb94433SThorsten Schütt // 2028bb94433SThorsten Schütt // 2038bb94433SThorsten Schütt // 2048bb94433SThorsten Schütt // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 2058bb94433SThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) 2068bb94433SThorsten Schütt // 2078bb94433SThorsten Schütt // --> 2088bb94433SThorsten Schütt // 2098bb94433SThorsten Schütt // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 2108bb94433SThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) 2118bb94433SThorsten Schütt // 2128bb94433SThorsten Schütt 2138bb94433SThorsten Schütt Register Vector = Extract->getVectorReg(); 2148bb94433SThorsten Schütt 2158bb94433SThorsten Schütt // We expect a buildVectorTrunc on the Vector register. 2168bb94433SThorsten Schütt GBuildVectorTrunc *Build = getOpcodeDef<GBuildVectorTrunc>(Vector, MRI); 2178bb94433SThorsten Schütt if (!Build) 2188bb94433SThorsten Schütt return false; 2198bb94433SThorsten Schütt 2208bb94433SThorsten Schütt LLT VectorTy = MRI.getType(Vector); 2218bb94433SThorsten Schütt 2228bb94433SThorsten Schütt // There is a one-use check. There are more combines on build vectors. 2238bb94433SThorsten Schütt EVT Ty(getMVTForLLT(VectorTy)); 2248bb94433SThorsten Schütt if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || 2258bb94433SThorsten Schütt !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) 2268bb94433SThorsten Schütt return false; 2278bb94433SThorsten Schütt 2288bb94433SThorsten Schütt Register Index = Extract->getIndexReg(); 2298bb94433SThorsten Schütt 2308bb94433SThorsten Schütt // If the Index is constant, then we can extract the element from the given 2318bb94433SThorsten Schütt // offset. 2328bb94433SThorsten Schütt std::optional<ValueAndVReg> MaybeIndex = 2338bb94433SThorsten Schütt getIConstantVRegValWithLookThrough(Index, MRI); 2348bb94433SThorsten Schütt if (!MaybeIndex) 2358bb94433SThorsten Schütt return false; 2368bb94433SThorsten Schütt 2378bb94433SThorsten Schütt // We now know that there is a buildVectorTrunc def'd on the Vector register 2388bb94433SThorsten Schütt // and the index is const. The combine will succeed. 2398bb94433SThorsten Schütt 2408bb94433SThorsten Schütt Register Dst = Extract->getReg(0); 2418bb94433SThorsten Schütt LLT DstTy = MRI.getType(Dst); 2428bb94433SThorsten Schütt LLT SrcTy = MRI.getType(Build->getSourceReg(0)); 2438bb94433SThorsten Schütt 2448bb94433SThorsten Schütt // For buildVectorTrunc, the inputs are truncated. 2458bb94433SThorsten Schütt if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) 2468bb94433SThorsten Schütt return false; 2478bb94433SThorsten Schütt 2488bb94433SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 2498bb94433SThorsten Schütt B.buildTrunc(Dst, Build->getSourceReg(MaybeIndex->Value.getZExtValue())); 2508bb94433SThorsten Schütt }; 2518bb94433SThorsten Schütt 2528bb94433SThorsten Schütt return true; 2538bb94433SThorsten Schütt } 254bc349ceaSThorsten Schütt 255b42f553aSThorsten Schütt bool CombinerHelper::matchExtractVectorElementWithShuffleVector( 256*ee7ca0ddSPaul Bowen-Huggett const MachineInstr &MI, const MachineInstr &MI2, 257*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 258ccfe7d4bSThorsten Schütt const GExtractVectorElement *Extract = cast<GExtractVectorElement>(&MI); 259ccfe7d4bSThorsten Schütt const GShuffleVector *Shuffle = cast<GShuffleVector>(&MI2); 260b42f553aSThorsten Schütt 261b42f553aSThorsten Schütt // 262b42f553aSThorsten Schütt // %zero:_(s64) = G_CONSTANT i64 0 263b42f553aSThorsten Schütt // %sv:_(<4 x s32>) = G_SHUFFLE_SHUFFLE %arg1(<4 x s32>), %arg2(<4 x s32>), 264b42f553aSThorsten Schütt // shufflemask(0, 0, 0, 0) 265b42f553aSThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %sv(<4 x s32>), %zero(s64) 266b42f553aSThorsten Schütt // 267b42f553aSThorsten Schütt // --> 268b42f553aSThorsten Schütt // 269b42f553aSThorsten Schütt // %zero1:_(s64) = G_CONSTANT i64 0 270b42f553aSThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %arg1(<4 x s32>), %zero1(s64) 271b42f553aSThorsten Schütt // 272b42f553aSThorsten Schütt // 273b42f553aSThorsten Schütt // 274b42f553aSThorsten Schütt // 275b42f553aSThorsten Schütt // %three:_(s64) = G_CONSTANT i64 3 276b42f553aSThorsten Schütt // %sv:_(<4 x s32>) = G_SHUFFLE_SHUFFLE %arg1(<4 x s32>), %arg2(<4 x s32>), 277b42f553aSThorsten Schütt // shufflemask(0, 0, 0, -1) 278b42f553aSThorsten Schütt // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %sv(<4 x s32>), %three(s64) 279b42f553aSThorsten Schütt // 280b42f553aSThorsten Schütt // --> 281b42f553aSThorsten Schütt // 282b42f553aSThorsten Schütt // %extract:_(s32) = G_IMPLICIT_DEF 283b42f553aSThorsten Schütt // 284b42f553aSThorsten Schütt // 285b42f553aSThorsten Schütt 286ccfe7d4bSThorsten Schütt APInt Index = getIConstantFromReg(Extract->getIndexReg(), MRI); 287b42f553aSThorsten Schütt 288b42f553aSThorsten Schütt ArrayRef<int> Mask = Shuffle->getMask(); 289b42f553aSThorsten Schütt 290ccfe7d4bSThorsten Schütt unsigned Offset = Index.getZExtValue(); 291b42f553aSThorsten Schütt int SrcIdx = Mask[Offset]; 292b42f553aSThorsten Schütt 293b42f553aSThorsten Schütt LLT Src1Type = MRI.getType(Shuffle->getSrc1Reg()); 294b42f553aSThorsten Schütt // At the IR level a <1 x ty> shuffle vector is valid, but we want to extract 295b42f553aSThorsten Schütt // from a vector. 296b42f553aSThorsten Schütt assert(Src1Type.isVector() && "expected to extract from a vector"); 297b42f553aSThorsten Schütt unsigned LHSWidth = Src1Type.isVector() ? Src1Type.getNumElements() : 1; 298b42f553aSThorsten Schütt 299b42f553aSThorsten Schütt // Note that there is no one use check. 300b42f553aSThorsten Schütt Register Dst = Extract->getReg(0); 301b42f553aSThorsten Schütt LLT DstTy = MRI.getType(Dst); 302b42f553aSThorsten Schütt 303b42f553aSThorsten Schütt if (SrcIdx < 0 && 304b42f553aSThorsten Schütt isLegalOrBeforeLegalizer({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) { 305b42f553aSThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { B.buildUndef(Dst); }; 306b42f553aSThorsten Schütt return true; 307b42f553aSThorsten Schütt } 308b42f553aSThorsten Schütt 309b42f553aSThorsten Schütt // If the legality check failed, then we still have to abort. 310b42f553aSThorsten Schütt if (SrcIdx < 0) 311b42f553aSThorsten Schütt return false; 312b42f553aSThorsten Schütt 313b42f553aSThorsten Schütt Register NewVector; 314b42f553aSThorsten Schütt 315b42f553aSThorsten Schütt // We check in which vector and at what offset to look through. 316b42f553aSThorsten Schütt if (SrcIdx < (int)LHSWidth) { 317b42f553aSThorsten Schütt NewVector = Shuffle->getSrc1Reg(); 318b42f553aSThorsten Schütt // SrcIdx unchanged 319b42f553aSThorsten Schütt } else { // SrcIdx >= LHSWidth 320b42f553aSThorsten Schütt NewVector = Shuffle->getSrc2Reg(); 321b42f553aSThorsten Schütt SrcIdx -= LHSWidth; 322b42f553aSThorsten Schütt } 323b42f553aSThorsten Schütt 324b42f553aSThorsten Schütt LLT IdxTy = MRI.getType(Extract->getIndexReg()); 325b42f553aSThorsten Schütt LLT NewVectorTy = MRI.getType(NewVector); 326b42f553aSThorsten Schütt 327b42f553aSThorsten Schütt // We check the legality of the look through. 328b42f553aSThorsten Schütt if (!isLegalOrBeforeLegalizer( 329b42f553aSThorsten Schütt {TargetOpcode::G_EXTRACT_VECTOR_ELT, {DstTy, NewVectorTy, IdxTy}}) || 330b42f553aSThorsten Schütt !isConstantLegalOrBeforeLegalizer({IdxTy})) 331b42f553aSThorsten Schütt return false; 332b42f553aSThorsten Schütt 333b42f553aSThorsten Schütt // We look through the shuffle vector. 334b42f553aSThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 335b42f553aSThorsten Schütt auto Idx = B.buildConstant(IdxTy, SrcIdx); 336b42f553aSThorsten Schütt B.buildExtractVectorElement(Dst, NewVector, Idx); 337b42f553aSThorsten Schütt }; 338b42f553aSThorsten Schütt 339b42f553aSThorsten Schütt return true; 340b42f553aSThorsten Schütt } 341b42f553aSThorsten Schütt 342bc349ceaSThorsten Schütt bool CombinerHelper::matchInsertVectorElementOOB(MachineInstr &MI, 343*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 344bc349ceaSThorsten Schütt GInsertVectorElement *Insert = cast<GInsertVectorElement>(&MI); 345bc349ceaSThorsten Schütt 346bc349ceaSThorsten Schütt Register Dst = Insert->getReg(0); 347bc349ceaSThorsten Schütt LLT DstTy = MRI.getType(Dst); 348bc349ceaSThorsten Schütt Register Index = Insert->getIndexReg(); 349bc349ceaSThorsten Schütt 350bc349ceaSThorsten Schütt if (!DstTy.isFixedVector()) 351bc349ceaSThorsten Schütt return false; 352bc349ceaSThorsten Schütt 353bc349ceaSThorsten Schütt std::optional<ValueAndVReg> MaybeIndex = 354bc349ceaSThorsten Schütt getIConstantVRegValWithLookThrough(Index, MRI); 355bc349ceaSThorsten Schütt 356bc349ceaSThorsten Schütt if (MaybeIndex && MaybeIndex->Value.uge(DstTy.getNumElements()) && 357bc349ceaSThorsten Schütt isLegalOrBeforeLegalizer({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) { 358bc349ceaSThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { B.buildUndef(Dst); }; 359bc349ceaSThorsten Schütt return true; 360bc349ceaSThorsten Schütt } 361bc349ceaSThorsten Schütt 362bc349ceaSThorsten Schütt return false; 363bc349ceaSThorsten Schütt } 3649b692e56SThorsten Schütt 3659b692e56SThorsten Schütt bool CombinerHelper::matchAddOfVScale(const MachineOperand &MO, 366*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 3679b692e56SThorsten Schütt GAdd *Add = cast<GAdd>(MRI.getVRegDef(MO.getReg())); 3689b692e56SThorsten Schütt GVScale *LHSVScale = cast<GVScale>(MRI.getVRegDef(Add->getLHSReg())); 3699b692e56SThorsten Schütt GVScale *RHSVScale = cast<GVScale>(MRI.getVRegDef(Add->getRHSReg())); 3709b692e56SThorsten Schütt 3719b692e56SThorsten Schütt Register Dst = Add->getReg(0); 3729b692e56SThorsten Schütt 3739b692e56SThorsten Schütt if (!MRI.hasOneNonDBGUse(LHSVScale->getReg(0)) || 3749b692e56SThorsten Schütt !MRI.hasOneNonDBGUse(RHSVScale->getReg(0))) 3759b692e56SThorsten Schütt return false; 3769b692e56SThorsten Schütt 3779b692e56SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 3789b692e56SThorsten Schütt B.buildVScale(Dst, LHSVScale->getSrc() + RHSVScale->getSrc()); 3799b692e56SThorsten Schütt }; 3809b692e56SThorsten Schütt 3819b692e56SThorsten Schütt return true; 3829b692e56SThorsten Schütt } 3839b692e56SThorsten Schütt 3849b692e56SThorsten Schütt bool CombinerHelper::matchMulOfVScale(const MachineOperand &MO, 385*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 3869b692e56SThorsten Schütt GMul *Mul = cast<GMul>(MRI.getVRegDef(MO.getReg())); 3879b692e56SThorsten Schütt GVScale *LHSVScale = cast<GVScale>(MRI.getVRegDef(Mul->getLHSReg())); 3889b692e56SThorsten Schütt 3899b692e56SThorsten Schütt std::optional<APInt> MaybeRHS = getIConstantVRegVal(Mul->getRHSReg(), MRI); 3909b692e56SThorsten Schütt if (!MaybeRHS) 3919b692e56SThorsten Schütt return false; 3929b692e56SThorsten Schütt 3939b692e56SThorsten Schütt Register Dst = MO.getReg(); 3949b692e56SThorsten Schütt 3959b692e56SThorsten Schütt if (!MRI.hasOneNonDBGUse(LHSVScale->getReg(0))) 3969b692e56SThorsten Schütt return false; 3979b692e56SThorsten Schütt 3989b692e56SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 3999b692e56SThorsten Schütt B.buildVScale(Dst, LHSVScale->getSrc() * *MaybeRHS); 4009b692e56SThorsten Schütt }; 4019b692e56SThorsten Schütt 4029b692e56SThorsten Schütt return true; 4039b692e56SThorsten Schütt } 4049b692e56SThorsten Schütt 4059b692e56SThorsten Schütt bool CombinerHelper::matchSubOfVScale(const MachineOperand &MO, 406*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 4079b692e56SThorsten Schütt GSub *Sub = cast<GSub>(MRI.getVRegDef(MO.getReg())); 4089b692e56SThorsten Schütt GVScale *RHSVScale = cast<GVScale>(MRI.getVRegDef(Sub->getRHSReg())); 4099b692e56SThorsten Schütt 4109b692e56SThorsten Schütt Register Dst = MO.getReg(); 4119b692e56SThorsten Schütt LLT DstTy = MRI.getType(Dst); 4129b692e56SThorsten Schütt 4139b692e56SThorsten Schütt if (!MRI.hasOneNonDBGUse(RHSVScale->getReg(0)) || 4149b692e56SThorsten Schütt !isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, DstTy})) 4159b692e56SThorsten Schütt return false; 4169b692e56SThorsten Schütt 4179b692e56SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 4189b692e56SThorsten Schütt auto VScale = B.buildVScale(DstTy, -RHSVScale->getSrc()); 4199b692e56SThorsten Schütt B.buildAdd(Dst, Sub->getLHSReg(), VScale, Sub->getFlags()); 4209b692e56SThorsten Schütt }; 4219b692e56SThorsten Schütt 4229b692e56SThorsten Schütt return true; 4239b692e56SThorsten Schütt } 4249b692e56SThorsten Schütt 4259b692e56SThorsten Schütt bool CombinerHelper::matchShlOfVScale(const MachineOperand &MO, 426*ee7ca0ddSPaul Bowen-Huggett BuildFnTy &MatchInfo) const { 4279b692e56SThorsten Schütt GShl *Shl = cast<GShl>(MRI.getVRegDef(MO.getReg())); 4289b692e56SThorsten Schütt GVScale *LHSVScale = cast<GVScale>(MRI.getVRegDef(Shl->getSrcReg())); 4299b692e56SThorsten Schütt 4309b692e56SThorsten Schütt std::optional<APInt> MaybeRHS = getIConstantVRegVal(Shl->getShiftReg(), MRI); 4319b692e56SThorsten Schütt if (!MaybeRHS) 4329b692e56SThorsten Schütt return false; 4339b692e56SThorsten Schütt 4349b692e56SThorsten Schütt Register Dst = MO.getReg(); 4359b692e56SThorsten Schütt LLT DstTy = MRI.getType(Dst); 4369b692e56SThorsten Schütt 4379b692e56SThorsten Schütt if (!MRI.hasOneNonDBGUse(LHSVScale->getReg(0)) || 4389b692e56SThorsten Schütt !isLegalOrBeforeLegalizer({TargetOpcode::G_VSCALE, DstTy})) 4399b692e56SThorsten Schütt return false; 4409b692e56SThorsten Schütt 4419b692e56SThorsten Schütt MatchInfo = [=](MachineIRBuilder &B) { 4429b692e56SThorsten Schütt B.buildVScale(Dst, LHSVScale->getSrc().shl(*MaybeRHS)); 4439b692e56SThorsten Schütt }; 4449b692e56SThorsten Schütt 4459b692e56SThorsten Schütt return true; 4469b692e56SThorsten Schütt } 447