Skip to content

Commit c3259f5

Browse files
author
git apple-llvm automerger
committed
Merge commit '9e0c0a09392f' from llvm.org/main into next
2 parents 6f031c8 + 9e0c0a0 commit c3259f5

File tree

4 files changed

+97
-61
lines changed

4 files changed

+97
-61
lines changed

llvm/include/llvm/Analysis/ScalarEvolutionPatternMatch.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ m_scev_PtrToInt(const Op0_t &Op0) {
184184

185185
/// Match a binary SCEV.
186186
template <typename SCEVTy, typename Op0_t, typename Op1_t,
187+
SCEV::NoWrapFlags WrapFlags = SCEV::FlagAnyWrap,
187188
bool Commutable = false>
188189
struct SCEVBinaryExpr_match {
189190
Op0_t Op0;
@@ -192,6 +193,10 @@ struct SCEVBinaryExpr_match {
192193
SCEVBinaryExpr_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
193194

194195
bool match(const SCEV *S) const {
196+
if (auto WrappingS = dyn_cast<SCEVNAryExpr>(S))
197+
if (WrappingS->getNoWrapFlags(WrapFlags) != WrapFlags)
198+
return false;
199+
195200
auto *E = dyn_cast<SCEVTy>(S);
196201
return E && E->getNumOperands() == 2 &&
197202
((Op0.match(E->getOperand(0)) && Op1.match(E->getOperand(1))) ||
@@ -201,10 +206,12 @@ struct SCEVBinaryExpr_match {
201206
};
202207

203208
template <typename SCEVTy, typename Op0_t, typename Op1_t,
209+
SCEV::NoWrapFlags WrapFlags = SCEV::FlagAnyWrap,
204210
bool Commutable = false>
205-
inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, Commutable>
211+
inline SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>
206212
m_scev_Binary(const Op0_t &Op0, const Op1_t &Op1) {
207-
return SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, Commutable>(Op0, Op1);
213+
return SCEVBinaryExpr_match<SCEVTy, Op0_t, Op1_t, WrapFlags, Commutable>(Op0,
214+
Op1);
208215
}
209216

210217
template <typename Op0_t, typename Op1_t>
@@ -220,9 +227,17 @@ m_scev_Mul(const Op0_t &Op0, const Op1_t &Op1) {
220227
}
221228

222229
template <typename Op0_t, typename Op1_t>
223-
inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, true>
230+
inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true>
224231
m_scev_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
225-
return m_scev_Binary<SCEVMulExpr, Op0_t, Op1_t, true>(Op0, Op1);
232+
return m_scev_Binary<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagAnyWrap, true>(Op0,
233+
Op1);
234+
}
235+
236+
template <typename Op0_t, typename Op1_t>
237+
inline SCEVBinaryExpr_match<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>
238+
m_scev_c_NUWMul(const Op0_t &Op0, const Op1_t &Op1) {
239+
return m_scev_Binary<SCEVMulExpr, Op0_t, Op1_t, SCEV::FlagNUW, true>(Op0,
240+
Op1);
226241
}
227242

228243
template <typename Op0_t, typename Op1_t>

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3598,6 +3598,13 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
35983598
}
35993599
}
36003600

3601+
// TODO: Generalize to handle any common factors.
3602+
// udiv (mul nuw a, vscale), (mul nuw b, vscale) --> udiv a, b
3603+
const SCEV *NewLHS, *NewRHS;
3604+
if (match(LHS, m_scev_c_NUWMul(m_SCEV(NewLHS), m_SCEVVScale())) &&
3605+
match(RHS, m_scev_c_NUWMul(m_SCEV(NewRHS), m_SCEVVScale())))
3606+
return getUDivExpr(NewLHS, NewRHS);
3607+
36013608
// The Insertion Point (IP) might be invalid by now (due to UniqueSCEVs
36023609
// changes). Make sure we get a new one.
36033610
IP = nullptr;

llvm/test/Analysis/ScalarEvolution/mul-udiv-folds.ll

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,43 @@ loop:
188188
exit:
189189
ret void
190190
}
191+
192+
define noundef i64 @udiv_mul_common_vscale_factor(i64 %a, i64 %b) {
193+
; CHECK-LABEL: 'udiv_mul_common_vscale_factor'
194+
; CHECK-NEXT: Classifying expressions for: @udiv_mul_common_vscale_factor
195+
; CHECK-NEXT: %vs = call i64 @llvm.vscale.i64()
196+
; CHECK-NEXT: --> vscale U: [1,0) S: [1,0)
197+
; CHECK-NEXT: %a.vs = mul i64 %a, %vs
198+
; CHECK-NEXT: --> (vscale * %a) U: full-set S: full-set
199+
; CHECK-NEXT: %b.vs = mul i64 %b, %vs
200+
; CHECK-NEXT: --> (vscale * %b) U: full-set S: full-set
201+
; CHECK-NEXT: %div = udiv i64 %a.vs, %b.vs
202+
; CHECK-NEXT: --> ((vscale * %a) /u (vscale * %b)) U: full-set S: full-set
203+
; CHECK-NEXT: Determining loop execution counts for: @udiv_mul_common_vscale_factor
204+
;
205+
%vs = call i64 @llvm.vscale()
206+
%a.vs = mul i64 %a, %vs
207+
%b.vs = mul i64 %b, %vs
208+
%div = udiv i64 %a.vs, %b.vs
209+
ret i64 %div
210+
}
211+
212+
define noundef i64 @udiv_mul_nuw_common_vscale_factor(i64 %a, i64 %b) {
213+
; CHECK-LABEL: 'udiv_mul_nuw_common_vscale_factor'
214+
; CHECK-NEXT: Classifying expressions for: @udiv_mul_nuw_common_vscale_factor
215+
; CHECK-NEXT: %vs = call i64 @llvm.vscale.i64()
216+
; CHECK-NEXT: --> vscale U: [1,0) S: [1,0)
217+
; CHECK-NEXT: %a.vs = mul nuw i64 %a, %vs
218+
; CHECK-NEXT: --> (vscale * %a)<nuw> U: full-set S: full-set
219+
; CHECK-NEXT: %b.vs = mul nuw i64 %b, %vs
220+
; CHECK-NEXT: --> (vscale * %b)<nuw> U: full-set S: full-set
221+
; CHECK-NEXT: %div = udiv i64 %a.vs, %b.vs
222+
; CHECK-NEXT: --> (%a /u %b) U: full-set S: full-set
223+
; CHECK-NEXT: Determining loop execution counts for: @udiv_mul_nuw_common_vscale_factor
224+
;
225+
%vs = call i64 @llvm.vscale()
226+
%a.vs = mul nuw i64 %a, %vs
227+
%b.vs = mul nuw i64 %b, %vs
228+
%div = udiv i64 %a.vs, %b.vs
229+
ret i64 %div
230+
}

0 commit comments

Comments
 (0)