Skip to content

Commit 0e8caf4

Browse files
committed
[InstCombine] Detect different vscales in div by shift combine.
This attempts to fix a regression in code that performs `svcntb() / svcntw()` (which is just a constant). https://godbolt.org/z/4o3a67s6n. We would previous expand the svcnt into two different vscale intrinsics, CSE them in a later pass and then fold udiv of shifts into a constant in a second instcombine. After llvm#121386 we now introduce a cttz. This patch just adds an additional check for vscale to the div of shift fold, allowing it to happen earlier and avoiding the need to look through the awkward (but probably not impossible) cttz that was introduced.
1 parent 4b0a7e6 commit 0e8caf4

File tree

3 files changed

+7
-17
lines changed

3 files changed

+7
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,14 +1205,16 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
12051205

12061206
// If X << Y and X << Z does not overflow, then:
12071207
// (X << Y) / (X << Z) -> (1 << Y) / (1 << Z) -> 1 << Y >> Z
1208-
if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
1209-
match(Op1, m_Shl(m_Specific(X), m_Value(Z)))) {
1208+
if ((match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
1209+
match(Op1, m_Shl(m_Specific(X), m_Value(Z)))) ||
1210+
(match(Op0, m_Shl(m_VScale(), m_Value(Y))) &&
1211+
match(Op1, m_Shl(m_VScale(), m_Value(Z))))) {
12101212
auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
12111213
auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
12121214

12131215
if (IsSigned ? (Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap())
12141216
: (Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap())) {
1215-
Constant *One = ConstantInt::get(X->getType(), 1);
1217+
Constant *One = ConstantInt::get(Op0->getType(), 1);
12161218
// Only preserve the nsw flag if dividend has nsw
12171219
// or divisor has nsw and operator is sdiv.
12181220
Value *Dividend = Builder.CreateShl(

llvm/test/Transforms/InstCombine/AArch64/sve-intrinsic-opts-counting-elems.ll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,7 @@ define i64 @cntd_all() {
242242

243243
define i64 @udiv() vscale_range(1, 16) {
244244
; CHECK-LABEL: @udiv(
245-
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64()
246-
; CHECK-NEXT: [[B:%.*]] = shl nuw nsw i64 [[TMP2]], 4
247-
; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64()
248-
; CHECK-NEXT: [[B1:%.*]] = shl nuw nsw i64 [[TMP3]], 2
249-
; CHECK-NEXT: [[TMP4:%.*]] = call range(i64 2, 65) i64 @llvm.cttz.i64(i64 [[B1]], i1 true)
250-
; CHECK-NEXT: [[C:%.*]] = lshr i64 [[B]], [[TMP4]]
251-
; CHECK-NEXT: ret i64 [[C]]
245+
; CHECK-NEXT: ret i64 4
252246
;
253247
%a = call i64 @llvm.aarch64.sve.cntb(i32 31)
254248
%b = call i64 @llvm.aarch64.sve.cntw(i32 31)

llvm/test/Transforms/InstCombine/div-shift.ll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,13 +1403,7 @@ start:
14031403
define i32 @udiv_shl_pair_const_vscale() vscale_range(1, 16) {
14041404
; CHECK-LABEL: @udiv_shl_pair_const_vscale(
14051405
; CHECK-NEXT: entry:
1406-
; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.vscale.i32()
1407-
; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.vscale.i32()
1408-
; CHECK-NEXT: [[LHS:%.*]] = shl nuw nsw i32 [[A]], 2
1409-
; CHECK-NEXT: [[RHS:%.*]] = shl nuw nsw i32 [[B]], 1
1410-
; CHECK-NEXT: [[TMP0:%.*]] = call range(i32 1, 33) i32 @llvm.cttz.i32(i32 [[RHS]], i1 true)
1411-
; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[LHS]], [[TMP0]]
1412-
; CHECK-NEXT: ret i32 [[DIV]]
1406+
; CHECK-NEXT: ret i32 2
14131407
;
14141408
entry:
14151409
%a = call i32 @llvm.vscale()

0 commit comments

Comments
 (0)