-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[GlobalIsel] Speedup select to integer min/max #92378
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
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 |
---|---|---|
|
@@ -6749,22 +6749,19 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
return false; | ||
} | ||
|
||
bool CombinerHelper::tryFoldSelectToIntMinMax(GSelect *Select, | ||
BuildFnTy &MatchInfo) { | ||
bool CombinerHelper::matchSelectIMinMax(const MachineOperand &MO, | ||
BuildFnTy &MatchInfo) { | ||
GSelect *Select = cast<GSelect>(MRI.getVRegDef(MO.getReg())); | ||
GICmp *Cmp = cast<GICmp>(MRI.getVRegDef(Select->getCondReg())); | ||
|
||
Register DstReg = Select->getReg(0); | ||
Register Cond = Select->getCondReg(); | ||
Register True = Select->getTrueReg(); | ||
Register False = Select->getFalseReg(); | ||
LLT DstTy = MRI.getType(DstReg); | ||
|
||
if (DstTy.isPointer()) | ||
return false; | ||
|
||
// We need an G_ICMP on the condition register. | ||
GICmp *Cmp = getOpcodeDef<GICmp>(Cond, MRI); | ||
if (!Cmp) | ||
return false; | ||
|
||
// We want to fold the icmp and replace the select. | ||
if (!MRI.hasOneNonDBGUse(Cmp->getReg(0))) | ||
return false; | ||
|
@@ -6775,62 +6772,46 @@ bool CombinerHelper::tryFoldSelectToIntMinMax(GSelect *Select, | |
if (CmpInst::isEquality(Pred)) | ||
return false; | ||
|
||
Register CmpLHS = Cmp->getLHSReg(); | ||
Register CmpRHS = Cmp->getRHSReg(); | ||
|
||
// We can swap CmpLHS and CmpRHS for higher hitrate. | ||
if (True == CmpRHS && False == CmpLHS) { | ||
std::swap(CmpLHS, CmpRHS); | ||
Pred = CmpInst::getSwappedPredicate(Pred); | ||
} | ||
[[maybe_unused]] Register CmpLHS = Cmp->getLHSReg(); | ||
[[maybe_unused]] Register CmpRHS = Cmp->getRHSReg(); | ||
|
||
// (icmp X, Y) ? X : Y -> integer minmax. | ||
// see matchSelectPattern in ValueTracking. | ||
// Legality between G_SELECT and integer minmax can differ. | ||
if (True == CmpLHS && False == CmpRHS) { | ||
switch (Pred) { | ||
case ICmpInst::ICMP_UGT: | ||
case ICmpInst::ICMP_UGE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.buildUMax(DstReg, True, False); | ||
}; | ||
return true; | ||
} | ||
case ICmpInst::ICMP_SGT: | ||
case ICmpInst::ICMP_SGE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.buildSMax(DstReg, True, False); | ||
}; | ||
return true; | ||
} | ||
case ICmpInst::ICMP_ULT: | ||
case ICmpInst::ICMP_ULE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.buildUMin(DstReg, True, False); | ||
}; | ||
return true; | ||
} | ||
case ICmpInst::ICMP_SLT: | ||
case ICmpInst::ICMP_SLE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.buildSMin(DstReg, True, False); | ||
}; | ||
return true; | ||
} | ||
default: | ||
assert(True == CmpLHS && False == CmpRHS && "unexpected MIR pattern"); | ||
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. You no longer match the swapped form 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 cannot. The alternative would be two patterns?!? 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. Sure, either write two patterns or move the 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. If this pattern works, it is evidently missing test coverage 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. Please don't merge with outstanding concerns about the patch. Please add back matching for the swapped form |
||
|
||
switch (Pred) { | ||
case ICmpInst::ICMP_UGT: | ||
case ICmpInst::ICMP_UGE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy})) | ||
return false; | ||
} | ||
MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, 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. Instead of using a lambda, which is kinda expensive, why not make the MatchData an 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 would still need to pass 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 but after #92239 it is completely pointless :) because we want the "match" and "apply" parts to be combined into one function anyway! So we should think about a better solution, e.g. allowing the user to write their own combined "match+apply" function in the first place. 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.
Can you open an issue to track this idea? I'm not sure I like it yet, i'd need to think about how the TableGen would look. 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! I really like the standard 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.
OK, I've tried to explain my thoughts in #92410. I hope it makes sense. |
||
return true; | ||
} | ||
case ICmpInst::ICMP_SGT: | ||
case ICmpInst::ICMP_SGE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); }; | ||
return true; | ||
} | ||
case ICmpInst::ICMP_ULT: | ||
case ICmpInst::ICMP_ULE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); }; | ||
return true; | ||
} | ||
case ICmpInst::ICMP_SLT: | ||
case ICmpInst::ICMP_SLE: { | ||
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy})) | ||
return false; | ||
MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); }; | ||
return true; | ||
} | ||
default: | ||
return false; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) { | ||
|
@@ -6842,9 +6823,6 @@ bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) { | |
if (tryFoldBoolSelectToLogic(Select, MatchInfo)) | ||
return true; | ||
|
||
if (tryFoldSelectToIntMinMax(Select, MatchInfo)) | ||
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. It was invoked for many selects in the function and probably failed a lot for no win. |
||
return true; | ||
|
||
return false; | ||
} | ||
|
||
|
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.
Now that we compile apply+match as a single C++ function we should check whether the buildfn here gets inlined. If not, maybe we need to rethink our use of applyBuildFn?
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.
When the pattern matches, the propability for a combine is higher and the pattern hits less often.