Skip to content

Commit 49d040d

Browse files
committed
[GlobalIsel] Speedup select to integer min/max
llvm#92309
1 parent 70a926c commit 49d040d

File tree

4 files changed

+78
-65
lines changed

4 files changed

+78
-65
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,9 @@ class CombinerHelper {
822822
// Given a binop \p MI, commute operands 1 and 2.
823823
void applyCommuteBinOpOperands(MachineInstr &MI);
824824

825+
/// Combine select to integer min/max.
826+
bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo);
827+
825828
/// Combine selects.
826829
bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo);
827830

@@ -962,9 +965,6 @@ class CombinerHelper {
962965

963966
bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo);
964967

965-
/// Try to fold (icmp X, Y) ? X : Y -> integer minmax.
966-
bool tryFoldSelectToIntMinMax(GSelect *Select, BuildFnTy &MatchInfo);
967-
968968
bool isOneOrOneSplat(Register Src, bool AllowUndefs);
969969
bool isZeroOrZeroSplat(Register Src, bool AllowUndefs);
970970
bool isConstantSplatVector(Register Src, int64_t SplatValue,

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,13 @@ def select_to_minmax: GICombineRule<
13071307
[{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]),
13081308
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
13091309

1310+
def select_to_iminmax: GICombineRule<
1311+
(defs root:$root, build_fn_matchinfo:$info),
1312+
(match (G_ICMP $tst, $tst1, $x, $y),
1313+
(G_SELECT $root, $tst, $x, $y),
1314+
[{ return Helper.matchSelectIMinMax(${root}, ${info}); }]),
1315+
(apply [{ Helper.applyBuildFnMO(${root}, ${info}); }])>;
1316+
13101317
def match_selects : GICombineRule<
13111318
(defs root:$root, build_fn_matchinfo:$matchinfo),
13121319
(match (wip_match_opcode G_SELECT):$root,
@@ -1670,7 +1677,7 @@ def phi_combines : GICombineGroup<[extend_through_phis]>;
16701677
def bitreverse_shift : GICombineGroup<[bitreverse_shl, bitreverse_lshr]>;
16711678

16721679
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp,
1673-
match_selects]>;
1680+
select_to_iminmax, match_selects]>;
16741681

16751682
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
16761683
mul_by_neg_one, idempotent_prop]>;

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

+39-61
Original file line numberDiff line numberDiff line change
@@ -6717,22 +6717,19 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,
67176717
return false;
67186718
}
67196719

6720-
bool CombinerHelper::tryFoldSelectToIntMinMax(GSelect *Select,
6721-
BuildFnTy &MatchInfo) {
6720+
bool CombinerHelper::matchSelectIMinMax(const MachineOperand &MO,
6721+
BuildFnTy &MatchInfo) {
6722+
GSelect *Select = cast<GSelect>(MRI.getVRegDef(MO.getReg()));
6723+
GICmp *Cmp = cast<GICmp>(MRI.getVRegDef(Select->getCondReg()));
6724+
67226725
Register DstReg = Select->getReg(0);
6723-
Register Cond = Select->getCondReg();
67246726
Register True = Select->getTrueReg();
67256727
Register False = Select->getFalseReg();
67266728
LLT DstTy = MRI.getType(DstReg);
67276729

67286730
if (DstTy.isPointer())
67296731
return false;
67306732

6731-
// We need an G_ICMP on the condition register.
6732-
GICmp *Cmp = getOpcodeDef<GICmp>(Cond, MRI);
6733-
if (!Cmp)
6734-
return false;
6735-
67366733
// We want to fold the icmp and replace the select.
67376734
if (!MRI.hasOneNonDBGUse(Cmp->getReg(0)))
67386735
return false;
@@ -6743,62 +6740,46 @@ bool CombinerHelper::tryFoldSelectToIntMinMax(GSelect *Select,
67436740
if (CmpInst::isEquality(Pred))
67446741
return false;
67456742

6746-
Register CmpLHS = Cmp->getLHSReg();
6747-
Register CmpRHS = Cmp->getRHSReg();
6748-
6749-
// We can swap CmpLHS and CmpRHS for higher hitrate.
6750-
if (True == CmpRHS && False == CmpLHS) {
6751-
std::swap(CmpLHS, CmpRHS);
6752-
Pred = CmpInst::getSwappedPredicate(Pred);
6753-
}
6743+
[[maybe_unused]] Register CmpLHS = Cmp->getLHSReg();
6744+
[[maybe_unused]] Register CmpRHS = Cmp->getRHSReg();
67546745

67556746
// (icmp X, Y) ? X : Y -> integer minmax.
67566747
// see matchSelectPattern in ValueTracking.
67576748
// Legality between G_SELECT and integer minmax can differ.
6758-
if (True == CmpLHS && False == CmpRHS) {
6759-
switch (Pred) {
6760-
case ICmpInst::ICMP_UGT:
6761-
case ICmpInst::ICMP_UGE: {
6762-
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
6763-
return false;
6764-
MatchInfo = [=](MachineIRBuilder &B) {
6765-
B.buildUMax(DstReg, True, False);
6766-
};
6767-
return true;
6768-
}
6769-
case ICmpInst::ICMP_SGT:
6770-
case ICmpInst::ICMP_SGE: {
6771-
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
6772-
return false;
6773-
MatchInfo = [=](MachineIRBuilder &B) {
6774-
B.buildSMax(DstReg, True, False);
6775-
};
6776-
return true;
6777-
}
6778-
case ICmpInst::ICMP_ULT:
6779-
case ICmpInst::ICMP_ULE: {
6780-
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
6781-
return false;
6782-
MatchInfo = [=](MachineIRBuilder &B) {
6783-
B.buildUMin(DstReg, True, False);
6784-
};
6785-
return true;
6786-
}
6787-
case ICmpInst::ICMP_SLT:
6788-
case ICmpInst::ICMP_SLE: {
6789-
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
6790-
return false;
6791-
MatchInfo = [=](MachineIRBuilder &B) {
6792-
B.buildSMin(DstReg, True, False);
6793-
};
6794-
return true;
6795-
}
6796-
default:
6749+
assert(True == CmpLHS && False == CmpRHS && "unexpected MIR pattern");
6750+
6751+
switch (Pred) {
6752+
case ICmpInst::ICMP_UGT:
6753+
case ICmpInst::ICMP_UGE: {
6754+
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy}))
67976755
return false;
6798-
}
6756+
MatchInfo = [=](MachineIRBuilder &B) { B.buildUMax(DstReg, True, False); };
6757+
return true;
6758+
}
6759+
case ICmpInst::ICMP_SGT:
6760+
case ICmpInst::ICMP_SGE: {
6761+
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy}))
6762+
return false;
6763+
MatchInfo = [=](MachineIRBuilder &B) { B.buildSMax(DstReg, True, False); };
6764+
return true;
6765+
}
6766+
case ICmpInst::ICMP_ULT:
6767+
case ICmpInst::ICMP_ULE: {
6768+
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy}))
6769+
return false;
6770+
MatchInfo = [=](MachineIRBuilder &B) { B.buildUMin(DstReg, True, False); };
6771+
return true;
6772+
}
6773+
case ICmpInst::ICMP_SLT:
6774+
case ICmpInst::ICMP_SLE: {
6775+
if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy}))
6776+
return false;
6777+
MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(DstReg, True, False); };
6778+
return true;
6779+
}
6780+
default:
6781+
return false;
67996782
}
6800-
6801-
return false;
68026783
}
68036784

68046785
bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {
@@ -6810,9 +6791,6 @@ bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {
68106791
if (tryFoldBoolSelectToLogic(Select, MatchInfo))
68116792
return true;
68126793

6813-
if (tryFoldSelectToIntMinMax(Select, MatchInfo))
6814-
return true;
6815-
68166794
return false;
68176795
}
68186796

llvm/test/CodeGen/AArch64/GlobalISel/combine-select.mir

+28
Original file line numberDiff line numberDiff line change
@@ -896,3 +896,31 @@ body: |
896896
RET_ReallyLR
897897
898898
...
899+
---
900+
# test failed_select icmp_sle f,t_t_f --> smin(t,f)
901+
name: select_icmp_sle_f_t_t_f_smin_t_f
902+
body: |
903+
bb.1:
904+
liveins: $x0, $x1, $x2
905+
; CHECK-LABEL: name: select_icmp_sle_f_t_t_f_smin_t_f
906+
; CHECK: liveins: $x0, $x1, $x2
907+
; CHECK-NEXT: {{ $}}
908+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
909+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
910+
; CHECK-NEXT: %t1:_(s32) = G_TRUNC [[COPY]](s64)
911+
; CHECK-NEXT: %f1:_(s32) = G_TRUNC [[COPY1]](s64)
912+
; CHECK-NEXT: %t:_(<4 x s32>) = G_BUILD_VECTOR %t1(s32), %t1(s32), %t1(s32), %t1(s32)
913+
; CHECK-NEXT: %f:_(<4 x s32>) = G_BUILD_VECTOR %f1(s32), %f1(s32), %f1(s32), %f1(s32)
914+
; CHECK-NEXT: %c:_(<4 x s32>) = G_ICMP intpred(sle), %f(<4 x s32>), %t
915+
; CHECK-NEXT: %sel:_(<4 x s32>) = exact G_SELECT %c(<4 x s32>), %t, %f
916+
; CHECK-NEXT: $q0 = COPY %sel(<4 x s32>)
917+
%0:_(s64) = COPY $x0
918+
%1:_(s64) = COPY $x1
919+
%t1:_(s32) = G_TRUNC %0
920+
%f1:_(s32) = G_TRUNC %1
921+
%t:_(<4 x s32>) = G_BUILD_VECTOR %t1, %t1, %t1, %t1
922+
%f:_(<4 x s32>) = G_BUILD_VECTOR %f1, %f1, %f1, %f1
923+
%c:_(<4 x s32>) = G_ICMP intpred(sle), %f(<4 x s32>), %t(<4 x s32>)
924+
%sel:_(<4 x s32>) = exact G_SELECT %c, %t, %f
925+
$q0 = COPY %sel(<4 x s32>)
926+
...

0 commit comments

Comments
 (0)