Skip to content

Commit d08de49

Browse files
author
Thorsten Schütt
committed
[GlobalIsel] Combine G_UNMERGE_VALUES from opaque vectors into scalars
%opaque:_(<2 x s64>) = G_OPAQUE %un1:_(s64), %un2:_(s64) = G_UNMERGE_VALUES %opaque(<2 x s64>) -> %zero:_(s64) = G_CONSTANT i64 0 %one:_(s64) = G_CONSTANT i64 1 %un1:_(s64) = G_EXTRACT_VECTOR_ELT %opaque, $zero %un2:_(s64) = G_EXTRACT_VECTOR_ELT %opaque, $one unable to legalize instruction: %5:_(s128) = G_EXTRACT_VECTOR_ELT %3:_(<2 x s128>), %7:_(s64) (in function: fabs_v2f128) Test: llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
1 parent d8b17f2 commit d08de49

File tree

94 files changed

+9544
-4033
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+9544
-4033
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,10 @@ class CombinerHelper {
922922
bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
923923
BuildFnTy &MatchInfo);
924924

925+
// unmerge_values(opaque vector) -> extract vector elt
926+
bool matchUnmergeValuesOfScalarAndVector(const MachineInstr &MI,
927+
BuildFnTy &MatchInfo);
928+
925929
private:
926930
/// Checks for legality of an indexed variant of \p LdSt.
927931
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,14 @@ def unmerge_anyext_build_vector : GICombineRule<
840840
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
841841
>;
842842

843+
// Transform unmerge opaque vector -> extract vector elt
844+
def unmerge_opaque_vector : GICombineRule<
845+
(defs root:$root, build_fn_matchinfo:$matchinfo),
846+
(match (wip_match_opcode G_UNMERGE_VALUES): $root,
847+
[{ return Helper.matchUnmergeValuesOfScalarAndVector(*${root}, ${matchinfo}); }]),
848+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
849+
>;
850+
843851
// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0.
844852
def unmerge_zext_to_zext : GICombineRule<
845853
(defs root:$d),
@@ -855,7 +863,8 @@ def merge_combines: GICombineGroup<[
855863
unmerge_cst,
856864
unmerge_undef,
857865
unmerge_dead_to_trunc,
858-
unmerge_zext_to_zext
866+
unmerge_zext_to_zext,
867+
unmerge_opaque_vector
859868
]>;
860869

861870
// Under certain conditions, transform:

llvm/lib/CodeGen/GlobalISel/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMGlobalISel
66
GlobalISel.cpp
77
Combiner.cpp
88
CombinerHelper.cpp
9+
CombinerHelperArtifacts.cpp
910
CombinerHelperCasts.cpp
1011
CombinerHelperCompares.cpp
1112
CombinerHelperVectorOps.cpp

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7611,85 +7611,3 @@ bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
76117611

76127612
return true;
76137613
}
7614-
7615-
bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
7616-
BuildFnTy &MatchInfo) {
7617-
const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
7618-
7619-
if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
7620-
return false;
7621-
7622-
const MachineInstr *Source = MRI.getVRegDef(Unmerge->getSourceReg());
7623-
7624-
LLT DstTy = MRI.getType(Unmerge->getReg(0));
7625-
7626-
// $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
7627-
// $any:_(<8 x s16>) = G_ANYEXT $bv
7628-
// $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
7629-
//
7630-
// ->
7631-
//
7632-
// $any:_(s16) = G_ANYEXT $bv[0]
7633-
// $any1:_(s16) = G_ANYEXT $bv[1]
7634-
// $any2:_(s16) = G_ANYEXT $bv[2]
7635-
// $any3:_(s16) = G_ANYEXT $bv[3]
7636-
// $any4:_(s16) = G_ANYEXT $bv[4]
7637-
// $any5:_(s16) = G_ANYEXT $bv[5]
7638-
// $any6:_(s16) = G_ANYEXT $bv[6]
7639-
// $any7:_(s16) = G_ANYEXT $bv[7]
7640-
// $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
7641-
// $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
7642-
7643-
// We want to unmerge into vectors.
7644-
if (!DstTy.isFixedVector())
7645-
return false;
7646-
7647-
const GAnyExt *Any = dyn_cast<GAnyExt>(Source);
7648-
if (!Any)
7649-
return false;
7650-
7651-
const MachineInstr *NextSource = MRI.getVRegDef(Any->getSrcReg());
7652-
7653-
if (const GBuildVector *BV = dyn_cast<GBuildVector>(NextSource)) {
7654-
// G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
7655-
7656-
if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
7657-
return false;
7658-
7659-
// FIXME: check element types?
7660-
if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
7661-
return false;
7662-
7663-
LLT BigBvTy = MRI.getType(BV->getReg(0));
7664-
LLT SmallBvTy = DstTy;
7665-
LLT SmallBvElemenTy = SmallBvTy.getElementType();
7666-
7667-
if (!isLegalOrBeforeLegalizer(
7668-
{TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
7669-
return false;
7670-
7671-
// We check the legality of scalar anyext.
7672-
if (!isLegalOrBeforeLegalizer(
7673-
{TargetOpcode::G_ANYEXT,
7674-
{SmallBvElemenTy, BigBvTy.getElementType()}}))
7675-
return false;
7676-
7677-
MatchInfo = [=](MachineIRBuilder &B) {
7678-
// Build into each G_UNMERGE_VALUES def
7679-
// a small build vector with anyext from the source build vector.
7680-
for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
7681-
SmallVector<Register> Ops;
7682-
for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
7683-
Register SourceArray =
7684-
BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
7685-
auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
7686-
Ops.push_back(AnyExt.getReg(0));
7687-
}
7688-
B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
7689-
};
7690-
};
7691-
return true;
7692-
};
7693-
7694-
return false;
7695-
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//===- CombinerHelperArtifacts.cpp-----------------------------------------===//
2+
//
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
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements CombinerHelper for legalization artifacts.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// G_UNMERGE_VALUES
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
17+
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18+
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
19+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
20+
#include "llvm/CodeGen/GlobalISel/Utils.h"
21+
#include "llvm/CodeGen/LowLevelTypeUtils.h"
22+
#include "llvm/CodeGen/MachineOperand.h"
23+
#include "llvm/CodeGen/MachineRegisterInfo.h"
24+
#include "llvm/CodeGen/TargetOpcodes.h"
25+
#include "llvm/Support/Casting.h"
26+
27+
#define DEBUG_TYPE "gi-combiner"
28+
29+
using namespace llvm;
30+
31+
bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
32+
BuildFnTy &MatchInfo) {
33+
const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
34+
35+
if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
36+
return false;
37+
38+
const MachineInstr *Source = MRI.getVRegDef(Unmerge->getSourceReg());
39+
40+
LLT DstTy = MRI.getType(Unmerge->getReg(0));
41+
42+
// $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
43+
// $any:_(<8 x s16>) = G_ANYEXT $bv
44+
// $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
45+
//
46+
// ->
47+
//
48+
// $any:_(s16) = G_ANYEXT $bv[0]
49+
// $any1:_(s16) = G_ANYEXT $bv[1]
50+
// $any2:_(s16) = G_ANYEXT $bv[2]
51+
// $any3:_(s16) = G_ANYEXT $bv[3]
52+
// $any4:_(s16) = G_ANYEXT $bv[4]
53+
// $any5:_(s16) = G_ANYEXT $bv[5]
54+
// $any6:_(s16) = G_ANYEXT $bv[6]
55+
// $any7:_(s16) = G_ANYEXT $bv[7]
56+
// $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
57+
// $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
58+
59+
// We want to unmerge into vectors.
60+
if (!DstTy.isFixedVector())
61+
return false;
62+
63+
const GAnyExt *Any = dyn_cast<GAnyExt>(Source);
64+
if (!Any)
65+
return false;
66+
67+
const MachineInstr *NextSource = MRI.getVRegDef(Any->getSrcReg());
68+
69+
if (const GBuildVector *BV = dyn_cast<GBuildVector>(NextSource)) {
70+
// G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
71+
72+
if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
73+
return false;
74+
75+
// FIXME: check element types?
76+
if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
77+
return false;
78+
79+
LLT BigBvTy = MRI.getType(BV->getReg(0));
80+
LLT SmallBvTy = DstTy;
81+
LLT SmallBvElemenTy = SmallBvTy.getElementType();
82+
83+
if (!isLegalOrBeforeLegalizer(
84+
{TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
85+
return false;
86+
87+
// We check the legality of scalar anyext.
88+
if (!isLegalOrBeforeLegalizer(
89+
{TargetOpcode::G_ANYEXT,
90+
{SmallBvElemenTy, BigBvTy.getElementType()}}))
91+
return false;
92+
93+
MatchInfo = [=](MachineIRBuilder &B) {
94+
// Build into each G_UNMERGE_VALUES def
95+
// a small build vector with anyext from the source build vector.
96+
for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
97+
SmallVector<Register> Ops;
98+
for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
99+
Register SourceArray =
100+
BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
101+
auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
102+
Ops.push_back(AnyExt.getReg(0));
103+
}
104+
B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
105+
};
106+
};
107+
return true;
108+
};
109+
110+
return false;
111+
}
112+
113+
bool CombinerHelper::matchUnmergeValuesOfScalarAndVector(const MachineInstr &MI,
114+
BuildFnTy &MatchInfo) {
115+
116+
constexpr unsigned MAX_NUM_DEFS_LIMIT = 8;
117+
118+
// %opaque:_(<2 x s64>) = G_OPAQUE
119+
// %un1:_(s64), %un2:_(s64) = G_UNMERGE_VALUES %opaque(<2 x s64>)
120+
//
121+
// ->
122+
//
123+
// %zero:_(s64) = G_CONSTANT i64 0
124+
// %one:_(s64) = G_CONSTANT i64 1
125+
// %un1:_(s64) = G_EXTRACT_VECTOR_ELT %opaque, $zero
126+
// %un2:_(s64) = G_EXTRACT_VECTOR_ELT %opaque, $one
127+
128+
const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
129+
130+
if (Unmerge->getNumDefs() > MAX_NUM_DEFS_LIMIT)
131+
return false;
132+
133+
LLT DstTy = MRI.getType(Unmerge->getReg(0));
134+
LLT SrcTy = MRI.getType(Unmerge->getSourceReg());
135+
136+
// We want to unmerge a vector into scalars.
137+
if (!DstTy.isScalar() || !SrcTy.isFixedVector() || DstTy.getSizeInBits() > 64)
138+
return false;
139+
140+
if (DstTy != SrcTy.getElementType())
141+
return false;
142+
143+
// We want to unmerge from an opaque vector.
144+
const MachineInstr *Source = MRI.getVRegDef(Unmerge->getSourceReg());
145+
if (isa<GBuildVector>(Source))
146+
return false;
147+
148+
unsigned PreferredVecIdxWidth =
149+
getTargetLowering().getVectorIdxTy(getDataLayout()).getSizeInBits();
150+
151+
LLT IdxTy = LLT::scalar(PreferredVecIdxWidth);
152+
153+
if (!isLegalOrBeforeLegalizer(
154+
{TargetOpcode::G_EXTRACT_VECTOR_ELT, {DstTy, SrcTy, IdxTy}}))
155+
return false;
156+
157+
if (!isConstantLegalOrBeforeLegalizer(IdxTy))
158+
return false;
159+
160+
MatchInfo = [=](MachineIRBuilder &B) {
161+
for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
162+
auto Index = B.buildConstant(IdxTy, I);
163+
B.buildExtractVectorElement(Unmerge->getOperand(I).getReg(),
164+
Unmerge->getSourceReg(), Index);
165+
}
166+
};
167+
168+
return true;
169+
}

llvm/lib/Target/AArch64/AArch64Combine.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def AArch64PostLegalizerCombiner
322322
extractvecelt_pairwise_add, redundant_or,
323323
mul_const, redundant_sext_inreg,
324324
form_bitfield_extract, rotate_out_of_range,
325-
icmp_to_true_false_known_bits,
325+
icmp_to_true_false_known_bits, vector_ops_combines,
326326
select_combines, fold_merge_to_zext,
327327
constant_fold_binops, identity_combines,
328328
ptr_add_immed_chain, overlapping_and,

0 commit comments

Comments
 (0)