-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[GlobalIsel] Combine select of binops #76763
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
e713bb6
4eab254
85ef024
8f4734a
73dfaf4
b6ee5a5
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 |
---|---|---|
|
@@ -6390,8 +6390,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue.isZero() && FalseValue.isOne()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(CondTy); | ||
B.buildNot(Inner, Cond); | ||
auto Inner = B.buildNot(CondTy, Cond); | ||
B.buildZExtOrTrunc(Dest, Inner); | ||
}; | ||
return true; | ||
|
@@ -6401,8 +6400,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue.isZero() && FalseValue.isAllOnes()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(CondTy); | ||
B.buildNot(Inner, Cond); | ||
auto Inner = B.buildNot(CondTy, Cond); | ||
B.buildSExtOrTrunc(Dest, Inner); | ||
}; | ||
return true; | ||
|
@@ -6412,8 +6410,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue - 1 == FalseValue) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Inner, Cond); | ||
auto Inner = B.buildZExtOrTrunc(TrueTy, Cond); | ||
B.buildAdd(Dest, Inner, False); | ||
}; | ||
return true; | ||
|
@@ -6423,8 +6420,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue + 1 == FalseValue) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildSExtOrTrunc(Inner, Cond); | ||
auto Inner = B.buildSExtOrTrunc(TrueTy, Cond); | ||
B.buildAdd(Dest, Inner, False); | ||
}; | ||
return true; | ||
|
@@ -6434,8 +6430,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue.isPowerOf2() && FalseValue.isZero()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Inner, Cond); | ||
auto Inner = B.buildZExtOrTrunc(TrueTy, Cond); | ||
// The shift amount must be scalar. | ||
LLT ShiftTy = TrueTy.isVector() ? TrueTy.getElementType() : TrueTy; | ||
auto ShAmtC = B.buildConstant(ShiftTy, TrueValue.exactLogBase2()); | ||
|
@@ -6447,8 +6442,7 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (TrueValue.isAllOnes()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Inner = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildSExtOrTrunc(Inner, Cond); | ||
auto Inner = B.buildSExtOrTrunc(TrueTy, Cond); | ||
B.buildOr(Dest, Inner, False, Flags); | ||
}; | ||
return true; | ||
|
@@ -6458,10 +6452,8 @@ bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, | |
if (FalseValue.isAllOnes()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Not = MRI.createGenericVirtualRegister(CondTy); | ||
B.buildNot(Not, Cond); | ||
Register Inner = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildSExtOrTrunc(Inner, Not); | ||
auto Not = B.buildNot(CondTy, Cond); | ||
auto Inner = B.buildSExtOrTrunc(TrueTy, Not); | ||
B.buildOr(Dest, Inner, True, Flags); | ||
}; | ||
return true; | ||
|
@@ -6496,8 +6488,7 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
if ((Cond == True) || isOneOrOneSplat(True, /* AllowUndefs */ true)) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Ext = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Ext, Cond); | ||
auto Ext = B.buildZExtOrTrunc(TrueTy, Cond); | ||
B.buildOr(DstReg, Ext, False, Flags); | ||
}; | ||
return true; | ||
|
@@ -6508,8 +6499,7 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
if ((Cond == False) || isZeroOrZeroSplat(False, /* AllowUndefs */ true)) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
Register Ext = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Ext, Cond); | ||
auto Ext = B.buildZExtOrTrunc(TrueTy, Cond); | ||
B.buildAnd(DstReg, Ext, True); | ||
}; | ||
return true; | ||
|
@@ -6520,11 +6510,9 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
// First the not. | ||
Register Inner = MRI.createGenericVirtualRegister(CondTy); | ||
B.buildNot(Inner, Cond); | ||
auto Inner = B.buildNot(CondTy, Cond); | ||
// Then an ext to match the destination register. | ||
Register Ext = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Ext, Inner); | ||
auto Ext = B.buildZExtOrTrunc(TrueTy, Inner); | ||
B.buildOr(DstReg, Ext, True, Flags); | ||
}; | ||
return true; | ||
|
@@ -6535,11 +6523,9 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
// First the not. | ||
Register Inner = MRI.createGenericVirtualRegister(CondTy); | ||
B.buildNot(Inner, Cond); | ||
auto Inner = B.buildNot(CondTy, Cond); | ||
// Then an ext to match the destination register. | ||
Register Ext = MRI.createGenericVirtualRegister(TrueTy); | ||
B.buildZExtOrTrunc(Ext, Inner); | ||
auto Ext = B.buildZExtOrTrunc(TrueTy, Inner); | ||
B.buildAnd(DstReg, Ext, False); | ||
}; | ||
return true; | ||
|
@@ -6548,6 +6534,54 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select, | |
return false; | ||
} | ||
|
||
bool CombinerHelper::tryFoldSelectOfBinOps(GSelect *Select, | ||
BuildFnTy &MatchInfo) { | ||
Register DstReg = Select->getReg(0); | ||
Register Cond = Select->getCondReg(); | ||
Register False = Select->getFalseReg(); | ||
Register True = Select->getTrueReg(); | ||
LLT DstTy = MRI.getType(DstReg); | ||
|
||
GBinOp *LHS = getOpcodeDef<GBinOp>(True, MRI); | ||
GBinOp *RHS = getOpcodeDef<GBinOp>(False, MRI); | ||
|
||
// We need two binops of the same kind on the true/false registers. | ||
if (!LHS || !RHS || LHS->getOpcode() != RHS->getOpcode()) | ||
return false; | ||
|
||
// Note that there are no constraints on CondTy. | ||
unsigned Flags = (LHS->getFlags() & RHS->getFlags()) | Select->getFlags(); | ||
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. This line differs from the Dag combiner. 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 have split this by matching the DAG behavior in the initial commit but doesn't really matter. I think this is OK but would be nice to have alive verify |
||
unsigned Opcode = LHS->getOpcode(); | ||
|
||
// Fold select(cond, binop(x, y), binop(z, y)) | ||
// --> binop(select(cond, x, z), y) | ||
if (LHS->getRHSReg() == RHS->getRHSReg()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
auto Sel = B.buildSelect(DstTy, Cond, LHS->getLHSReg(), RHS->getLHSReg(), | ||
Select->getFlags()); | ||
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. And Flags are added to selects. |
||
B.buildInstr(Opcode, {DstReg}, {Sel, LHS->getRHSReg()}, Flags); | ||
}; | ||
return true; | ||
} | ||
|
||
// Fold select(cond, binop(x, y), binop(x, z)) | ||
// --> binop(x, select(cond, y, z)) | ||
if (LHS->getLHSReg() == RHS->getLHSReg()) { | ||
MatchInfo = [=](MachineIRBuilder &B) { | ||
B.setInstrAndDebugLoc(*Select); | ||
auto Sel = B.buildSelect(DstTy, Cond, LHS->getRHSReg(), RHS->getRHSReg(), | ||
Select->getFlags()); | ||
B.buildInstr(Opcode, {DstReg}, {LHS->getLHSReg(), Sel}, Flags); | ||
}; | ||
return true; | ||
} | ||
|
||
// FIXME: use isCommutable(). | ||
|
||
return false; | ||
} | ||
|
||
bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) { | ||
GSelect *Select = cast<GSelect>(&MI); | ||
|
||
|
@@ -6557,5 +6591,8 @@ bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) { | |
if (tryFoldBoolSelectToLogic(Select, MatchInfo)) | ||
return true; | ||
|
||
if (tryFoldSelectOfBinOps(Select, MatchInfo)) | ||
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.
Could you implement this in terms of GIntBinOp::classof and GFBinOp::classof to avoid listing the opcodes in multiple places?
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.
I was going to suggest that too but it won't compile due to not yet seeing the definition of
GIntBinOp
when parsing this class.