-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[CodeGenPrepare] Create USubWithOverflow_match #160327
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
base: main
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 |
|---|---|---|
|
|
@@ -2685,6 +2685,81 @@ m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { | |
| return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S); | ||
| } | ||
|
|
||
| template <typename LHS_t, typename RHS_t, typename Diff_t> | ||
| struct USubWithOverflow_match { | ||
| LHS_t L; | ||
| RHS_t R; | ||
| Diff_t S; | ||
|
|
||
| USubWithOverflow_match(const LHS_t &L, const RHS_t &R, const Diff_t &S) | ||
| : L(L), R(R), S(S) {} | ||
|
|
||
| template <typename OpTy> bool match(OpTy *V) const { | ||
| Value *ICmpLHS = nullptr, *ICmpRHS = nullptr; | ||
| CmpPredicate Pred; | ||
| if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) | ||
| return false; | ||
|
|
||
| Value *SubLHS = nullptr, *SubRHS = nullptr; | ||
|
Collaborator
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. Why do these need to be initialized? |
||
| auto SubExpr = m_Sub(m_Value(SubLHS), m_Value(SubRHS)); | ||
|
|
||
| Value *AddLHS = nullptr, *AddRHS = nullptr; | ||
|
Collaborator
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. Why do these need to be initialized? |
||
| auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); | ||
|
|
||
| // (a - b) >u a OR (a + (-c)) >u a (allow add-canonicalized forms | ||
| // but only where the RHS is a constant APInt that is negative) | ||
| if (Pred == ICmpInst::ICMP_UGT) { | ||
| if (SubExpr.match(ICmpLHS) && ICmpRHS == SubLHS) | ||
| return L.match(SubLHS) && R.match(SubRHS) && S.match(ICmpLHS); | ||
|
|
||
| if (AddExpr.match(ICmpLHS)) { | ||
| const APInt *AddC = nullptr; | ||
| if (m_APInt(AddC).match(AddRHS) && ICmpRHS == AddLHS) { | ||
| APInt NegC = -(*AddC); | ||
| Constant *NegConst = ConstantInt::get(AddRHS->getType(), NegC); | ||
| return L.match(AddLHS) && R.match(NegConst) && S.match(ICmpLHS); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // a <u (a - b) OR a <u (a + (-c)) | ||
| if (Pred == ICmpInst::ICMP_ULT) { | ||
| if (SubExpr.match(ICmpRHS) && ICmpLHS == SubLHS) | ||
| return L.match(SubLHS) && R.match(SubRHS) && S.match(ICmpRHS); | ||
|
|
||
| if (AddExpr.match(ICmpRHS)) { | ||
| const APInt *AddC = nullptr; | ||
| if (m_APInt(AddC).match(AddRHS) && ICmpLHS == AddLHS) { | ||
| APInt NegC = -(*AddC); | ||
| Constant *NegConst = ConstantInt::get(AddRHS->getType(), NegC); | ||
| return L.match(AddLHS) && R.match(NegConst) && S.match(ICmpRHS); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Special-case for 0 - a != 0 (common canonicalization) | ||
| if (Pred == ICmpInst::ICMP_NE) { | ||
| // (0 - a) != 0 | ||
| if (SubExpr.match(ICmpLHS) && m_Zero().match(ICmpRHS) && | ||
|
Collaborator
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. m_Zero -> m_ZeroInt |
||
| m_Zero().match(SubLHS)) | ||
| return L.match(SubLHS) && R.match(SubRHS) && S.match(ICmpLHS); | ||
|
|
||
| // 0 != (0 - a) | ||
| if (m_Zero().match(ICmpLHS) && SubExpr.match(ICmpRHS) && | ||
|
Collaborator
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. m_ZeroInt |
||
| m_Zero().match(SubLHS)) | ||
|
Collaborator
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. m_ZeroInt |
||
| return L.match(SubLHS) && R.match(SubRHS) && S.match(ICmpRHS); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| }; | ||
|
|
||
| template <typename LHS_t, typename RHS_t, typename Diff_t> | ||
| USubWithOverflow_match<LHS_t, RHS_t, Diff_t> | ||
| m_USubWithOverflow(const LHS_t &L, const RHS_t &R, const Diff_t &S) { | ||
| return USubWithOverflow_match<LHS_t, RHS_t, Diff_t>(L, R, S); | ||
| } | ||
|
|
||
| template <typename Opnd_t> struct Argument_match { | ||
| unsigned OpI; | ||
| Opnd_t Val; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7829,6 +7829,23 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| Instruction *SubI = nullptr; | ||||||
| if (match(&I, m_USubWithOverflow(m_Value(X), m_Value(Y), | ||||||
| m_Instruction(SubI))) && | ||||||
| isa<IntegerType>(X->getType())) { | ||||||
| Value *Result; | ||||||
| Constant *Overflow; | ||||||
| // m_UAddWithOverflow can match patterns that do not include an explicit | ||||||
|
Collaborator
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. m_USubWithOverflow?
Collaborator
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.
Suggested change
|
||||||
| // "add" instruction, so check the opcode of the matched op. | ||||||
|
Collaborator
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. "sub"? |
||||||
| if (SubI->getOpcode() == Instruction::Sub && | ||||||
| OptimizeOverflowCheck(Instruction::Sub, /*Signed*/ false, X, Y, *SubI, | ||||||
| Result, Overflow)) { | ||||||
| replaceInstUsesWith(*SubI, Result); | ||||||
| eraseInstFromFunction(*SubI); | ||||||
| return replaceInstUsesWith(I, Overflow); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // (zext X) * (zext Y) --> llvm.umul.with.overflow. | ||||||
| if (match(Op0, m_NUWMul(m_ZExt(m_Value(X)), m_ZExt(m_Value(Y)))) && | ||||||
| match(Op1, m_APInt(C))) { | ||||||
|
|
||||||
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.
Why do these need to be initialized? They aren't initialized in
UAddWithOverflow_match