diff options
author | Thorsten Schütt <schuett@gmail.com> | 2024-04-02 09:01:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-02 09:01:24 +0200 |
commit | 8bb9443333e0117ab61feecce9de339b11b924fc (patch) | |
tree | 31b077992d48fb1a82348685930f40ed69eb6e4e | |
parent | 93c387df908923f17875ab9cf0463d5f181318bb (diff) | |
download | llvm-8bb9443333e0117ab61feecce9de339b11b924fc.zip llvm-8bb9443333e0117ab61feecce9de339b11b924fc.tar.gz llvm-8bb9443333e0117ab61feecce9de339b11b924fc.tar.bz2 |
[GlobalIsel] Combine G_EXTRACT_VECTOR_ELT (#85321)
preliminary steps
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 25 | ||||
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h | 41 | ||||
-rw-r--r-- | llvm/include/llvm/Target/GlobalISel/Combine.td | 230 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp | 326 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir | 299 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/extract-vector-elt.ll | 18 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/extractvector-oob-load.mir | 7 |
9 files changed, 930 insertions, 25 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 28d9cf6..3af3204 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -594,6 +594,10 @@ public: /// This variant does not erase \p MI after calling the build function. void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo); + /// Use a function which takes in a MachineIRBuilder to perform a combine. + /// By default, it erases the instruction \p MI from the function. + void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo); + bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo); bool matchFunnelShiftToRotate(MachineInstr &MI); void applyFunnelShiftToRotate(MachineInstr &MI); @@ -823,6 +827,27 @@ public: /// Combine addos. bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo); + /// Combine extract vector element. + bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo); + + /// Combine extract vector element with freeze on the vector register. + bool matchExtractVectorElementWithFreeze(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a build vector on the vector register. + bool matchExtractVectorElementWithBuildVector(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a build vector trunc on the vector + /// register. + bool matchExtractVectorElementWithBuildVectorTrunc(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a insert vector element on the vector + /// register and different indices. + bool matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO, + BuildFnTy &MatchInfo); + private: /// Checks for legality of an indexed variant of \p LdSt. bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const; diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h index 261cfcf5..25e4711 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h @@ -286,6 +286,14 @@ public: } }; +/// Represents a G_BUILD_VECTOR_TRUNC. +class GBuildVectorTrunc : public GMergeLikeInstr { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC; + } +}; + /// Represents a G_PTR_ADD. class GPtrAdd : public GenericMachineInstr { public: @@ -739,6 +747,39 @@ public: }; }; +/// Represents an extract vector element. +class GExtractVectorElement : public GenericMachineInstr { +public: + Register getVectorReg() const { return getOperand(1).getReg(); } + Register getIndexReg() const { return getOperand(2).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT; + } +}; + +/// Represents an insert vector element. +class GInsertVectorElement : public GenericMachineInstr { +public: + Register getVectorReg() const { return getOperand(1).getReg(); } + Register getElementReg() const { return getOperand(2).getReg(); } + Register getIndexReg() const { return getOperand(3).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT; + } +}; + +/// Represents a freeze. +class GFreeze : public GenericMachineInstr { +public: + Register getSourceReg() const { return getOperand(1).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_FREEZE; + } +}; + } // namespace llvm #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 72d3c0e..778ff7e 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -1305,6 +1305,200 @@ def match_addos : GICombineRule< [{ return Helper.matchAddOverflow(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; +def match_extract_of_element_undef_vector: GICombineRule < + (defs root:$root), + (match (G_IMPLICIT_DEF $vector), + (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), + (apply (G_IMPLICIT_DEF $root)) +>; + +def match_extract_of_element_undef_index: GICombineRule < + (defs root:$root), + (match (G_IMPLICIT_DEF $idx), + (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), + (apply (G_IMPLICIT_DEF $root)) +>; + +def match_extract_of_element : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, + [{ return Helper.matchExtractVectorElement(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +def extract_vector_element_not_const : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx)), + (apply (GIReplaceReg $root, $value))>; + +def extract_vector_element_different_indices : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx2), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx1), + [{ return Helper.matchExtractVectorElementWithDifferentIndices(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector2 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector3 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector4 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector5 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector6 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector7 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector8 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector9 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector10 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector11 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector12 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector13 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector14 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector15 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector16 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc2 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc3 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc4 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc5 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc6 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc7 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc8 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d, $e), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_freeze : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_FREEZE $src, $input), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithFreeze(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + // Combines concat operations def concat_matchinfo : GIDefMatchData<"SmallVector<Register>">; def combine_concat_vector : GICombineRule< @@ -1313,6 +1507,37 @@ def combine_concat_vector : GICombineRule< [{ return Helper.matchCombineConcatVectors(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyCombineConcatVectors(*${root}, ${matchinfo}); }])>; +// match_extract_of_element must be the first! +def vector_ops_combines: GICombineGroup<[ +match_extract_of_element_undef_vector, +match_extract_of_element_undef_index, +match_extract_of_element, +extract_vector_element_not_const, +extract_vector_element_different_indices, +extract_vector_element_build_vector2, +extract_vector_element_build_vector3, +extract_vector_element_build_vector4, +extract_vector_element_build_vector5, +extract_vector_element_build_vector7, +extract_vector_element_build_vector8, +extract_vector_element_build_vector9, +extract_vector_element_build_vector10, +extract_vector_element_build_vector11, +extract_vector_element_build_vector12, +extract_vector_element_build_vector13, +extract_vector_element_build_vector14, +extract_vector_element_build_vector15, +extract_vector_element_build_vector16, +extract_vector_element_build_vector_trunc2, +extract_vector_element_build_vector_trunc3, +extract_vector_element_build_vector_trunc4, +extract_vector_element_build_vector_trunc5, +extract_vector_element_build_vector_trunc6, +extract_vector_element_build_vector_trunc7, +extract_vector_element_build_vector_trunc8, +extract_vector_element_freeze +]>; + // FIXME: These should use the custom predicate feature once it lands. def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, undef_to_negative_one, @@ -1368,8 +1593,9 @@ def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, def constant_fold_binops : GICombineGroup<[constant_fold_binop, constant_fold_fp_binop]>; -def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, - extract_vec_elt_combines, combines_for_extload, combine_extracted_vector_load, +def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines, + insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload, + combine_extracted_vector_load, undef_combines, identity_combines, phi_combines, simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big, reassocs, ptr_add_immed_chain, diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index 46e6c6d..54ac7f7 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMGlobalISel GlobalISel.cpp Combiner.cpp CombinerHelper.cpp + CombinerHelperVectorOps.cpp GIMatchTableExecutor.cpp GISelChangeObserver.cpp IRTranslator.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 98e7c73..5cf7a33 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4058,6 +4058,14 @@ void CombinerHelper::applyBuildFn( MI.eraseFromParent(); } +void CombinerHelper::applyBuildFnMO(const MachineOperand &MO, + BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + Builder.setInstrAndDebugLoc(*Root); + MatchInfo(Builder); + Root->eraseFromParent(); +} + void CombinerHelper::applyBuildFnNoErase( MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) { MatchInfo(Builder); diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp new file mode 100644 index 0000000..123bf21 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp @@ -0,0 +1,326 @@ +//===- CombinerHelperVectorOps.cpp-----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements CombinerHelper for G_EXTRACT_VECTOR_ELT. +// +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/LowLevelTypeUtils.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/Support/Casting.h" +#include <optional> + +#define DEBUG_TYPE "gi-combiner" + +using namespace llvm; +using namespace MIPatternMatch; + +bool CombinerHelper::matchExtractVectorElement(MachineInstr &MI, + BuildFnTy &MatchInfo) { + GExtractVectorElement *Extract = cast<GExtractVectorElement>(&MI); + + Register Dst = Extract->getReg(0); + Register Vector = Extract->getVectorReg(); + Register Index = Extract->getIndexReg(); + LLT DstTy = MRI.getType(Dst); + LLT VectorTy = MRI.getType(Vector); + + // The vector register can be def'd by various ops that have vector as its + // type. They can all be used for constant folding, scalarizing, + // canonicalization, or combining based on symmetry. + // + // vector like ops + // * build vector + // * build vector trunc + // * shuffle vector + // * splat vector + // * concat vectors + // * insert/extract vector element + // * insert/extract subvector + // * vector loads + // * scalable vector loads + // + // compute like ops + // * binary ops + // * unary ops + // * exts and truncs + // * casts + // * fneg + // * select + // * phis + // * cmps + // * freeze + // * bitcast + // * undef + + // We try to get the value of the Index register. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + std::optional<APInt> IndexC = std::nullopt; + + if (MaybeIndex) + IndexC = MaybeIndex->Value; + + // Fold extractVectorElement(Vector, TOOLARGE) -> undef + if (IndexC && VectorTy.isFixedVector() && + IndexC->getZExtValue() >= VectorTy.getNumElements() && + isLegalOrBeforeLegalizer({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) { + // For fixed-length vectors, it's invalid to extract out-of-range elements. + MatchInfo = [=](MachineIRBuilder &B) { B.buildUndef(Dst); }; + return true; + } + + return false; +} + +bool CombinerHelper::matchExtractVectorElementWithDifferentIndices( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %idx1:_(s64) = G_CONSTANT i64 1 + // %idx2:_(s64) = G_CONSTANT i64 2 + // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), + // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %insert(<2 + // x s32>), %idx1(s64) + // + // --> + // + // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), + // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x + // s32>), %idx1(s64) + // + // + + Register Index = Extract->getIndexReg(); + + // We try to get the value of the Index register. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + std::optional<APInt> IndexC = std::nullopt; + + if (!MaybeIndex) + return false; + else + IndexC = MaybeIndex->Value; + + Register Vector = Extract->getVectorReg(); + + GInsertVectorElement *Insert = + getOpcodeDef<GInsertVectorElement>(Vector, MRI); + if (!Insert) + return false; + + Register Dst = Extract->getReg(0); + + std::optional<ValueAndVReg> MaybeInsertIndex = + getIConstantVRegValWithLookThrough(Insert->getIndexReg(), MRI); + + if (MaybeInsertIndex && MaybeInsertIndex->Value != *IndexC) { + // There is no one-use check. We have to keep the insert. When both Index + // registers are constants and not equal, we can look into the Vector + // register of the insert. + MatchInfo = [=](MachineIRBuilder &B) { + B.buildExtractVectorElement(Dst, Insert->getVectorReg(), Index); + }; + return true; + } + + return false; +} + +bool CombinerHelper::matchExtractVectorElementWithFreeze( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + Register Vector = Extract->getVectorReg(); + + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %freeze:_(<2 x s32>) = G_FREEZE %bv(<2 x s32>) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // %freeze:_(s32) = G_FREEZE %extract(s32) + // + // + + // For G_FREEZE, the input and the output types are identical. Moving the + // freeze from the Vector into the front of the extract preserves the freeze + // semantics. The result is still freeze'd. Furthermore, the Vector register + // becomes easier to analyze. A build vector could have been hidden behind the + // freeze. + + // We expect a freeze on the Vector register. + GFreeze *Freeze = getOpcodeDef<GFreeze>(Vector, MRI); + if (!Freeze) + return false; + + Register Dst = Extract->getReg(0); + LLT DstTy = MRI.getType(Dst); + + // We first have to check for one-use and legality of the freeze. + // The type of the extractVectorElement did not change. + if (!MRI.hasOneNonDBGUse(Freeze->getReg(0)) || + !isLegalOrBeforeLegalizer({TargetOpcode::G_FREEZE, {DstTy}})) + return false; + + Register Index = Extract->getIndexReg(); + + // We move the freeze from the Vector register in front of the + // extractVectorElement. + MatchInfo = [=](MachineIRBuilder &B) { + auto Extract = + B.buildExtractVectorElement(DstTy, Freeze->getSourceReg(), Index); + B.buildFreeze(Dst, Extract); + }; + + return true; +} + +bool CombinerHelper::matchExtractVectorElementWithBuildVector( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %zero:_(s64) = G_CONSTANT i64 0 + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) + // + // --> + // + // %extract:_(32) = COPY %arg1(s32) + // + // + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + + Register Vector = Extract->getVectorReg(); + + // We expect a buildVector on the Vector register. + GBuildVector *Build = getOpcodeDef<GBuildVector>(Vector, MRI); + if (!Build) + return false; + + LLT VectorTy = MRI.getType(Vector); + + // There is a one-use check. There are more combines on build vectors. + EVT Ty(getMVTForLLT(VectorTy)); + if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || + !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) + return false; + + Register Index = Extract->getIndexReg(); + + // If the Index is constant, then we can extract the element from the given + // offset. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + if (!MaybeIndex) + return false; + + // We now know that there is a buildVector def'd on the Vector register and + // the index is const. The combine will succeed. + + Register Dst = Extract->getReg(0); + + MatchInfo = [=](MachineIRBuilder &B) { + B.buildCopy(Dst, Build->getSourceReg(MaybeIndex->Value.getZExtValue())); + }; + + return true; +} + +bool CombinerHelper::matchExtractVectorElementWithBuildVectorTrunc( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %zero:_(s64) = G_CONSTANT i64 0 + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) + // + // --> + // + // %extract:_(32) = G_TRUNC %arg1(s64) + // + // + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + + Register Vector = Extract->getVectorReg(); + + // We expect a buildVectorTrunc on the Vector register. + GBuildVectorTrunc *Build = getOpcodeDef<GBuildVectorTrunc>(Vector, MRI); + if (!Build) + return false; + + LLT VectorTy = MRI.getType(Vector); + + // There is a one-use check. There are more combines on build vectors. + EVT Ty(getMVTForLLT(VectorTy)); + if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || + !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) + return false; + + Register Index = Extract->getIndexReg(); + + // If the Index is constant, then we can extract the element from the given + // offset. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + if (!MaybeIndex) + return false; + + // We now know that there is a buildVectorTrunc def'd on the Vector register + // and the index is const. The combine will succeed. + + Register Dst = Extract->getReg(0); + LLT DstTy = MRI.getType(Dst); + LLT SrcTy = MRI.getType(Build->getSourceReg(0)); + + // For buildVectorTrunc, the inputs are truncated. + if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) + return false; + + MatchInfo = [=](MachineIRBuilder &B) { + B.buildTrunc(Dst, Build->getSourceReg(MaybeIndex->Value.getZExtValue())); + }; + + return true; +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir index a2116cc..c2a38e2 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir @@ -192,8 +192,8 @@ body: | ... --- +# This test checks that this combine runs after the insertvec->build_vector name: extract_from_insert -alignment: 4 tracksRegLiveness: true liveins: - { reg: '$x0' } @@ -203,8 +203,6 @@ frameInfo: body: | bb.1: liveins: $x0, $x1 - ; This test checks that this combine runs after the insertvec->build_vector - ; combine. ; CHECK-LABEL: name: extract_from_insert ; CHECK: liveins: $x0, $x1 ; CHECK-NEXT: {{ $}} @@ -247,3 +245,298 @@ body: | RET_ReallyLR implicit $x0 ... +--- +name: extract_from_vector_undef +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_vector_undef + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = G_IMPLICIT_DEF + %idx:_(s32) = G_CONSTANT i32 -2 + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_index_undef +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + ; CHECK-LABEL: name: extract_from_index_undef + ; CHECK: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_IMPLICIT_DEF + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_index_too_large +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_index_too_large + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 3000 + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_with_freeze +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_with_freeze + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %vec:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: %idx:_(s32) = COPY $w1 + ; CHECK-NEXT: [[EVEC:%[0-9]+]]:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + ; CHECK-NEXT: %extract:_(s64) = G_FREEZE [[EVEC]] + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w1 + %fvec:_(<2 x s64>) = G_FREEZE %vec + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %fvec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_insert_symmetry +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_insert_symmetry + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %element:_(s64) = COPY $x1 + ; CHECK-NEXT: $x0 = COPY %element(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w1 + %element:_(s64) = COPY $x1 + %invec:_(<2 x s64>) = G_INSERT_VECTOR_ELT %vec(<2 x s64>), %element(s64), %idx(s32) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %invec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_insert_with_different_consts +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_insert_with_different_consts + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %vec:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: %idx2:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx2(s32) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 0 + %idx2:_(s32) = G_CONSTANT i32 1 + %element:_(s64) = COPY $x1 + %invec:_(<2 x s64>) = G_INSERT_VECTOR_ELT %vec(<2 x s64>), %element(s64), %idx(s32) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %invec(<2 x s64>), %idx2(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_non_const +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_non_const + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %idx:_(s32) = COPY $w0 + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %arg2:_(s64) = COPY $x1 + ; CHECK-NEXT: %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + ; CHECK-NEXT: %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_const +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_const + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: $x0 = COPY %arg1(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_trunc_const2 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc_const2 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %extract:_(s32) = G_TRUNC %arg1(s64) + ; CHECK-NEXT: $w0 = COPY %extract(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %arg3:_(s64) = COPY $x0 + %arg4:_(s64) = COPY $x1 + %idx:_(s32) = G_CONSTANT i32 0 + %bv:_(<4 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64), %arg3(s64), %arg4(s64) + %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %idx(s32) + $w0 = COPY %extract(s32) + RET_ReallyLR implicit $x0 +... +--- +name: extract_from_build_vector_trunc2 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc2 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %arg2:_(s64) = COPY $x1 + ; CHECK-NEXT: %idx:_(s32) = COPY $w0 + ; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %idx(s32) + ; CHECK-NEXT: $w0 = COPY %extract(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %idx:_(s32) = COPY $w0 + %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %idx(s32) + $w0 = COPY %extract(s32) + RET_ReallyLR implicit $x0 +... +--- +name: extract_from_build_vector_trunc_const3 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc_const3 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s128) = COPY $q0 + ; CHECK-NEXT: %extract:_(s64) = G_TRUNC %arg1(s128) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %arg1:_(s128) = COPY $q0 + %arg2:_(s128) = COPY $q1 + %idx:_(s32) = G_CONSTANT i32 0 + %bv:_(<2 x s64>) = G_BUILD_VECTOR_TRUNC %arg1(s128), %arg2(s128) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 +... +--- diff --git a/llvm/test/CodeGen/AArch64/extract-vector-elt.ll b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll index c5c525a..504222e 100644 --- a/llvm/test/CodeGen/AArch64/extract-vector-elt.ll +++ b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll @@ -25,20 +25,9 @@ entry: } define i64 @extract_v2i64_undef_vector(<2 x i64> %a, i32 %c) { -; CHECK-SD-LABEL: extract_v2i64_undef_vector: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: extract_v2i64_undef_vector: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: sub sp, sp, #16 -; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 -; CHECK-GI-NEXT: mov w9, w0 -; CHECK-GI-NEXT: mov x8, sp -; CHECK-GI-NEXT: and x9, x9, #0x1 -; CHECK-GI-NEXT: ldr x0, [x8, x9, lsl #3] -; CHECK-GI-NEXT: add sp, sp, #16 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: extract_v2i64_undef_vector: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ret entry: %d = extractelement <2 x i64> undef, i32 %c ret i64 %d @@ -130,7 +119,6 @@ define i64 @extract_v2i64_extract_of_insert_different_const(<2 x i64> %a, i64 %e ; ; CHECK-GI-LABEL: extract_v2i64_extract_of_insert_different_const: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: mov v0.d[0], x0 ; CHECK-GI-NEXT: mov d0, v0.d[1] ; CHECK-GI-NEXT: fmov x0, d0 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir b/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir index e8c5819..e7e8c93 100644 --- a/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir +++ b/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir @@ -22,11 +22,8 @@ body: | ; CHECK-LABEL: name: f ; CHECK: liveins: $x0 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64) - ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[PTR_ADD]](p0) :: (load (s64)) - ; CHECK-NEXT: $x0 = COPY [[LOAD]](s64) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY [[DEF]](s64) ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:_(p0) = COPY $x0 %3:_(s64) = G_CONSTANT i64 224567957 |