1//===- CombinerHelperVectorOps.cpp-----------------------------------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 9// This file implements CombinerHelper for G_EXTRACT_VECTOR_ELT, 10// G_INSERT_VECTOR_ELT, and G_VSCALE 12//===----------------------------------------------------------------------===// 28#define DEBUG_TYPE "gi-combiner" 31using namespaceMIPatternMatch;
43// The vector register can be def'd by various ops that have vector as its 44// type. They can all be used for constant folding, scalarizing, 45// canonicalization, or combining based on symmetry. 49// * build vector trunc 53// * insert/extract vector element 54// * insert/extract subvector 56// * scalable vector loads 71// We try to get the value of the Index register. 72 std::optional<ValueAndVReg> MaybeIndex =
74 std::optional<APInt> IndexC = std::nullopt;
77 IndexC = MaybeIndex->Value;
79// Fold extractVectorElement(Vector, TOOLARGE) -> undef 83// For fixed-length vectors, it's invalid to extract out-of-range elements. 97// %idx1:_(s64) = G_CONSTANT i64 1 98// %idx2:_(s64) = G_CONSTANT i64 2 99// %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), 100// %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %insert(<2 101// x s32>), %idx1(s64) 105// %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), 106// %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x 113// We try to get the value of the Index register. 114 std::optional<ValueAndVReg> MaybeIndex =
116 std::optional<APInt> IndexC = std::nullopt;
121 IndexC = MaybeIndex->Value;
126 getOpcodeDef<GInsertVectorElement>(
Vector,
MRI);
132 std::optional<ValueAndVReg> MaybeInsertIndex =
135if (MaybeInsertIndex && MaybeInsertIndex->Value != *IndexC) {
136// There is no one-use check. We have to keep the insert. When both Index 137// registers are constants and not equal, we can look into the Vector 138// register of the insert. 140B.buildExtractVectorElement(Dst, Insert->getVectorReg(), Index);
155// %zero:_(s64) = G_CONSTANT i64 0 156// %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) 157// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) 161// %extract:_(32) = COPY %arg1(s32) 168// There is a one-use check. There are more combines on build vectors. 176// We now know that there is a buildVector def'd on the Vector register and 177// the index is const. The combine will succeed. 194// %zero:_(s64) = G_CONSTANT i64 0 195// %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 196// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) 200// %extract:_(32) = G_TRUNC %arg1(s64) 204// %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 205// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) 209// %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) 210// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) 215// We expect a buildVectorTrunc on the Vector register. 222// There is a one-use check. There are more combines on build vectors. 230// If the Index is constant, then we can extract the element from the given 232 std::optional<ValueAndVReg> MaybeIndex =
237// We now know that there is a buildVectorTrunc def'd on the Vector register 238// and the index is const. The combine will succeed. 244// For buildVectorTrunc, the inputs are truncated. 249B.buildTrunc(Dst, Build->
getSourceReg(MaybeIndex->Value.getZExtValue()));
262// %zero:_(s64) = G_CONSTANT i64 0 263// %sv:_(<4 x s32>) = G_SHUFFLE_SHUFFLE %arg1(<4 x s32>), %arg2(<4 x s32>), 264// shufflemask(0, 0, 0, 0) 265// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %sv(<4 x s32>), %zero(s64) 269// %zero1:_(s64) = G_CONSTANT i64 0 270// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %arg1(<4 x s32>), %zero1(s64) 275// %three:_(s64) = G_CONSTANT i64 3 276// %sv:_(<4 x s32>) = G_SHUFFLE_SHUFFLE %arg1(<4 x s32>), %arg2(<4 x s32>), 277// shufflemask(0, 0, 0, -1) 278// %extract:_(s32) = G_EXTRACT_VECTOR_ELT %sv(<4 x s32>), %three(s64) 282// %extract:_(s32) = G_IMPLICIT_DEF 290unsignedOffset = Index.getZExtValue();
294// At the IR level a <1 x ty> shuffle vector is valid, but we want to extract 299// Note that there is no one use check. 309// If the legality check failed, then we still have to abort. 315// We check in which vector and at what offset to look through. 316if (SrcIdx < (
int)LHSWidth) {
319 }
else {
// SrcIdx >= LHSWidth 327// We check the legality of the look through. 329 {TargetOpcode::G_EXTRACT_VECTOR_ELT, {DstTy, NewVectorTy, IdxTy}}) ||
333// We look through the shuffle vector. 335autoIdx =
B.buildConstant(IdxTy, SrcIdx);
336B.buildExtractVectorElement(Dst, NewVector,
Idx);
348Register Index = Insert->getIndexReg();
353 std::optional<ValueAndVReg> MaybeIndex =
378B.buildVScale(Dst, LHSVScale->
getSrc() + RHSVScale->
getSrc());
399B.buildVScale(Dst, LHSVScale->
getSrc() * *MaybeRHS);
418auto VScale =
B.buildVScale(DstTy, -RHSVScale->
getSrc());
442B.buildVScale(Dst, LHSVScale->
getSrc().
shl(*MaybeRHS));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This contains common combine transformations that may be used in a combine pass,or by the target else...
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
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Interface for Targets to specify which operations they can successfully select and how the others sho...
Implement a low-level type suitable for MachineInstr level instruction selection.
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file describes how to lower LLVM code to machine code.
Class for arbitrary precision integers.
APInt shl(unsigned shiftAmt) const
Left-shift function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool matchExtractVectorElementWithBuildVectorTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine extract vector element with a build vector trunc on the vector register.
const TargetLowering & getTargetLowering() const
bool matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO, BuildFnTy &MatchInfo) const
Combine extract vector element with a insert vector element on the vector register and different indi...
bool matchInsertVectorElementOOB(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine insert vector element OOB.
bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo) const
Combine extract vector element.
bool matchMulOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchAddOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchShlOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchExtractVectorElementWithShuffleVector(const MachineInstr &MI, const MachineInstr &MI2, BuildFnTy &MatchInfo) const
Combine extract vector element with a shuffle vector on the vector register.
bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const
MachineRegisterInfo & MRI
bool isLegalOrBeforeLegalizer(const LegalityQuery &Query) const
bool matchSubOfVScale(const MachineOperand &MO, BuildFnTy &MatchInfo) const
bool matchExtractVectorElementWithBuildVector(const MachineInstr &MI, const MachineInstr &MI2, BuildFnTy &MatchInfo) const
Combine extract vector element with a build vector on the vector register.
Represents an integer addition.
Register getLHSReg() const
Register getRHSReg() const
Represents a G_BUILD_VECTOR_TRUNC.
Represents a G_BUILD_VECTOR.
Represents an extract vector element.
Register getVectorReg() const
Register getIndexReg() const
Represents an insert vector element.
Register getSourceReg(unsigned I) const
Returns the I'th source register.
Represents an integer multiplication.
Register getShiftReg() const
Register getSrcReg() const
Represents a G_SHUFFLE_VECTOR.
Register getSrc2Reg() const
Register getSrc1Reg() const
ArrayRef< int > getMask() const
Represents an integer subtraction.
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
Helper class to build MachineInstr.
Representation of each machine instruction.
uint32_t getFlags() const
Return the MI flags bitvector.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Wrapper class representing virtual and physical registers.
This is an optimization pass for GlobalISel generic memory operations.
std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
MVT getMVTForLLT(LLT Ty)
Get a rough equivalent of an MVT for a given LLT.
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
std::function< void(MachineIRBuilder &)> BuildFnTy
const APInt & getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI)
VReg is defined by a G_CONSTANT, return the corresponding value.
@ Mul
Product of integers.
std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...