-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GlobalISel] Match G_SHUFFLE_VECTORs representing sub-vector extracts #224
base: aie-public
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -1527,6 +1527,16 @@ def combine_shuffle_concat : GICombineRule< | |||
[{ return Helper.matchCombineShuffleConcat(*${root}, ${matchinfo}); }]), | ||||
(apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>; | ||||
|
||||
// Combines Shuffles representing vector extracts into Unmerges | ||||
// res = G_SHUFFLE_VECTORS a, b, <0, 1> | ||||
// ===> | ||||
// res, undef = G_UNMERGE_VALUES a | ||||
def combine_shuffle_to_extract_vector : GICombineRule< | ||||
(defs root:$root, build_fn_matchinfo:$matchinfo), | ||||
(match (wip_match_opcode G_SHUFFLE_VECTOR):$root, | ||||
[{ return Helper.matchShuffleToExtractSubvector(*${root}, ${matchinfo}); }]), | ||||
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; | ||||
|
||||
def combine_inttoptr_constant : GICombineRule< | ||||
(defs root:$root, build_fn_matchinfo:$info), | ||||
(match (wip_match_opcode G_INTTOPTR):$root, | ||||
|
@@ -1642,7 +1652,7 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines, | |||
sub_add_reg, select_to_minmax, redundant_binop_in_equality, | ||||
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors, | ||||
combine_concat_vector, double_icmp_zero_and_or_combine, match_addos, | ||||
combine_shuffle_concat]>; | ||||
combine_shuffle_concat, combine_shuffle_to_extract_vector]>; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: this is a bit of an expensive combiner to run since it iterates through a decent chunk of elements twice. Previously, this was an explicitly opt in combiner that a target enabled by calling a specific function. This will now run it on all targets, this is probably worth it. Also, upstream will probably be running those checks now anyways, so it doesn't matter as much.
See MR linked in: #41 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What upstream checks are you referring to? I think the current There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, checking elements to the shuffle vector is just an O(n²) operations unless you use a hashmap. At the moment, this is done in |
||||
|
||||
// A combine group used to for prelegalizer combiners at -O0. The combines in | ||||
// this group have been selected based on experiments to balance code size and | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
#include "llvm/ADT/SetVector.h" | ||
#include "llvm/ADT/SmallBitVector.h" | ||
#include "llvm/Analysis/CmpInstAnalysis.h" | ||
#include "llvm/Analysis/VectorUtils.h" | ||
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" | ||
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" | ||
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" | ||
|
@@ -7254,6 +7255,60 @@ bool CombinerHelper::matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) { | |
return false; | ||
} | ||
|
||
bool CombinerHelper::matchShuffleToExtractSubvector(MachineInstr &MI, | ||
BuildFnTy &MatchInfo) { | ||
|
||
assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR); | ||
const Register DstReg = MI.getOperand(0).getReg(); | ||
const Register Src1Reg = MI.getOperand(1).getReg(); | ||
ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
|
||
const LLT DstTy = MRI.getType(DstReg); | ||
const LLT Src1Ty = MRI.getType(Src1Reg); | ||
|
||
if (!DstTy.isVector() || !Src1Ty.isVector()) | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that this misses the following edge case:
In this case, you could unmerge the first array into the destination. Since the target is not a vector, this would skip it. How useful this is? Who knows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that case could even be matched to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it is a bit obscure and the overhead it would cause is minimal. |
||
|
||
const unsigned NumDstElems = DstTy.getNumElements(); | ||
const unsigned NumSrc1Elems = Src1Ty.getNumElements(); | ||
|
||
if (NumDstElems * 2 != NumSrc1Elems) | ||
return false; | ||
|
||
auto CheckExtractMask = [=](unsigned Start, unsigned NumElems) -> bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: we can use by-reference capture and automatic return type deduction. |
||
auto ExtractMask = createSequentialMask(Start, NumElems, 0); | ||
|
||
for (unsigned I = 0; I < NumDstElems; I++) { | ||
if (Mask[I] == -1) | ||
continue; | ||
|
||
if (Mask[I] != ExtractMask[I]) | ||
return false; | ||
} | ||
|
||
return true; | ||
}; | ||
Comment on lines
+7278
to
+7290
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this is a lot, this is great. |
||
|
||
const Register UndefReg = MRI.createGenericVirtualRegister(DstTy); | ||
Register UnmergeDst1; | ||
Register UnmergeDst2; | ||
if (CheckExtractMask(0, NumDstElems)) { | ||
UnmergeDst1 = DstReg; | ||
UnmergeDst2 = UndefReg; | ||
} else if (CheckExtractMask(NumDstElems, NumDstElems)) { | ||
UnmergeDst1 = UndefReg; | ||
UnmergeDst2 = DstReg; | ||
} else { | ||
return false; | ||
} | ||
|
||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.buildUnmerge({UnmergeDst1, UnmergeDst2}, Src1Reg); | ||
}; | ||
|
||
return true; | ||
} | ||
|
||
bool CombinerHelper::matchIntToPtrContant(MachineInstr &MI, | ||
MachineRegisterInfo &MRI, | ||
BuildFnTy &MatchInfo) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using
wip_match_opcode
, upstream really doesn't like this since it causes imprecise patterns and slows down the compilation. In this case, it should be very little difference compared to just matching SHUFFLE_VECTOR directly.https://llvm.org/docs/GlobalISel/MIRPatterns.html#gallery
See MR linked in: #41 (comment)