xref: /llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp (revision ee7ca0dddafb609090ad1789570c099d95c0afb6)
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