-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[PatternMatching] Add generic API for matching constants using custom conditions #85676
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
fb801f9
625121b
9705962
436c5a2
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 |
---|---|---|
|
@@ -460,6 +460,39 @@ template <typename Predicate> struct apf_pred_ty : public Predicate { | |
// | ||
/////////////////////////////////////////////////////////////////////////////// | ||
|
||
template <typename APTy> struct custom_checkfn { | ||
function_ref<bool(const APTy &)> CheckFn; | ||
bool isValue(const APTy &C) { return CheckFn(C); } | ||
}; | ||
|
||
/// Match an integer or vector where CheckFn(ele) for each element is true. | ||
/// For vectors, poison elements are assumed to match. | ||
inline cst_pred_ty<custom_checkfn<APInt>> | ||
m_CheckedInt(function_ref<bool(const APInt &)> CheckFn) { | ||
return cst_pred_ty<custom_checkfn<APInt>>{CheckFn}; | ||
} | ||
|
||
inline api_pred_ty<custom_checkfn<APInt>> | ||
m_CheckedInt(const APInt *&V, function_ref<bool(const APInt &)> CheckFn) { | ||
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. Looking at this again just now, what's the point of these methods returning a I think this should be providing the result as 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. Missed this... yeah think you are right. Should be a constant. 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. Interesting the norm case seems to be to always export these as Any objection to me replacing all of these? 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. Assuming there are not a lot of uses of them, replacing them should be fine. Something to be careful about is that the direct replacement here would be m_APIntAllowPoison, not m_APInt. If there are many uses, it may make sense to retain them as a convenience (I don't think m_CheckedInt with APInt makes sense as a convenience though, it's strictly more complicated than just writing out the check). 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. See: #91377 decided not to do the other. Didn't seem like much upside and made code less compact. |
||
api_pred_ty<custom_checkfn<APInt>> P(V); | ||
P.CheckFn = CheckFn; | ||
return P; | ||
} | ||
|
||
/// Match a float or vector where CheckFn(ele) for each element is true. | ||
/// For vectors, poison elements are assumed to match. | ||
inline cstfp_pred_ty<custom_checkfn<APFloat>> | ||
m_CheckedFp(function_ref<bool(const APFloat &)> CheckFn) { | ||
return cstfp_pred_ty<custom_checkfn<APFloat>>{CheckFn}; | ||
} | ||
|
||
inline apf_pred_ty<custom_checkfn<APFloat>> | ||
m_CheckedFp(const APFloat *&V, function_ref<bool(const APFloat &)> CheckFn) { | ||
apf_pred_ty<custom_checkfn<APFloat>> P(V); | ||
P.CheckFn = CheckFn; | ||
return P; | ||
} | ||
|
||
struct is_any_apint { | ||
bool isValue(const APInt &C) { return true; } | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,8 +118,8 @@ define i32 @icmp_div(i16 %a, i16 %c) { | |
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 | ||
; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] | ||
; CHECK: then: | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 | ||
; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP]] to i32 | ||
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0 | ||
; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32 | ||
; CHECK-NEXT: br label [[EXIT]] | ||
; CHECK: exit: | ||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ] | ||
|
@@ -173,8 +173,8 @@ define i32 @icmp_div3(i16 %a, i16 %c) { | |
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0 | ||
; CHECK-NEXT: br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]] | ||
; CHECK: then: | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[C:%.*]], 0 | ||
; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP]] to i32 | ||
; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0 | ||
; CHECK-NEXT: [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32 | ||
; CHECK-NEXT: br label [[EXIT]] | ||
; CHECK: exit: | ||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ] | ||
|
@@ -381,8 +381,8 @@ define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) { | |
|
||
define i1 @sdiv_x_by_const_cmp_x(i32 %x) { | ||
; CHECK-LABEL: @sdiv_x_by_const_cmp_x( | ||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0 | ||
; CHECK-NEXT: ret i1 [[TMP1]] | ||
; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 0 | ||
; CHECK-NEXT: ret i1 [[R]] | ||
; | ||
%v = sdiv i32 %x, 13 | ||
%r = icmp eq i32 %v, %x | ||
|
@@ -399,12 +399,33 @@ define i1 @udiv_x_by_const_cmp_x(i32 %x) { | |
ret i1 %2 | ||
} | ||
|
||
define <2 x i1> @udiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) { | ||
; CHECK-LABEL: @udiv_x_by_const_cmp_x_non_splat( | ||
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i32> [[X:%.*]], zeroinitializer | ||
; CHECK-NEXT: ret <2 x i1> [[TMP1]] | ||
; | ||
%1 = udiv <2 x i32> %x, <i32 123, i32 -123> | ||
%2 = icmp slt <2 x i32> %1, %x | ||
ret <2 x i1> %2 | ||
} | ||
|
||
|
||
define <2 x i1> @sdiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) { | ||
; CHECK-LABEL: @sdiv_x_by_const_cmp_x_non_splat( | ||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer | ||
; CHECK-NEXT: ret <2 x i1> [[TMP1]] | ||
; | ||
%1 = sdiv <2 x i32> %x, <i32 2, i32 3> | ||
%2 = icmp eq <2 x i32> %1, %x | ||
ret <2 x i1> %2 | ||
} | ||
|
||
; Same as above but with right shift instead of division (C != 0) | ||
|
||
define i1 @lshr_x_by_const_cmp_x(i32 %x) { | ||
; CHECK-LABEL: @lshr_x_by_const_cmp_x( | ||
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0 | ||
; CHECK-NEXT: ret i1 [[TMP1]] | ||
; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X:%.*]], 0 | ||
; CHECK-NEXT: ret i1 [[R]] | ||
; | ||
%v = lshr i32 %x, 1 | ||
%r = icmp eq i32 %v, %x | ||
|
@@ -421,6 +442,28 @@ define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) { | |
ret <4 x i1> %r | ||
} | ||
|
||
define <4 x i1> @lshr_by_const_cmp_sle_value_non_splat(<4 x i32> %x) { | ||
; CHECK-LABEL: @lshr_by_const_cmp_sle_value_non_splat( | ||
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1> | ||
; CHECK-NEXT: ret <4 x i1> [[R]] | ||
; | ||
%v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 5> | ||
%r = icmp sle <4 x i32> %v, %x | ||
ret <4 x i1> %r | ||
} | ||
nikic marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
define <4 x i1> @ashr_by_const_cmp_sge_value_non_splat(<4 x i32> %x) { | ||
; CHECK-LABEL: @ashr_by_const_cmp_sge_value_non_splat( | ||
; CHECK-NEXT: [[R:%.*]] = icmp slt <4 x i32> [[X:%.*]], <i32 1, i32 1, i32 1, i32 1> | ||
; CHECK-NEXT: ret <4 x i1> [[R]] | ||
; | ||
%v = ashr <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4> | ||
%r = icmp sge <4 x i32> %v, %x | ||
ret <4 x i1> %r | ||
} | ||
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. Also add a negative non-splat test that does not pass the check? 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. Already had non-splat negative tests (i.e |
||
|
||
|
||
define i1 @lshr_by_const_cmp_sge_value(i32 %x) { | ||
; CHECK-LABEL: @lshr_by_const_cmp_sge_value( | ||
; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[X:%.*]], 1 | ||
|
Uh oh!
There was an error while loading. Please reload this page.