Skip to content

Commit 43ee392

Browse files
rotaterighttstellar
authored andcommitted
[InstCombine] try to fold low-mask of ashr to lshr
With one-use, we handle this via demanded-bits. But We need to handle extra uses to improve issue llvm#54750. https://alive2.llvm.org/ce/z/aDYkPv (cherry picked from commit 7783db5)
1 parent 5ea5e3c commit 43ee392

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,12 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
19611961
}
19621962
}
19631963

1964+
// If this 'and' clears the sign-bits added by ashr, replace with lshr:
1965+
// and (ashr X, ShiftC), C --> lshr X, ShiftC
1966+
if (match(Op0, m_AShr(m_Value(X), m_APInt(ShiftC))) && ShiftC->ult(Width) &&
1967+
C->isMask(Width - ShiftC->getZExtValue()))
1968+
return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, *ShiftC));
1969+
19641970
const APInt *AddC;
19651971
if (match(Op0, m_Add(m_Value(X), m_APInt(AddC)))) {
19661972
// If we add zeros to every bit below a mask, the add has no effect:

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ define i32 @ashr_lowmask_use(i32 %x) {
406406
; CHECK-LABEL: @ashr_lowmask_use(
407407
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 1
408408
; CHECK-NEXT: call void @use32(i32 [[A]])
409-
; CHECK-NEXT: [[R:%.*]] = and i32 [[A]], 2147483647
409+
; CHECK-NEXT: [[R:%.*]] = lshr i32 [[X]], 1
410410
; CHECK-NEXT: ret i32 [[R]]
411411
;
412412
%a = ashr i32 %x, 1
@@ -419,7 +419,7 @@ define <2 x i8> @ashr_lowmask_use_splat(<2 x i8> %x, <2 x i8>* %p) {
419419
; CHECK-LABEL: @ashr_lowmask_use_splat(
420420
; CHECK-NEXT: [[A:%.*]] = ashr <2 x i8> [[X:%.*]], <i8 7, i8 7>
421421
; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
422-
; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], <i8 1, i8 1>
422+
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> [[X]], <i8 7, i8 7>
423423
; CHECK-NEXT: ret <2 x i8> [[R]]
424424
;
425425
%a = ashr <2 x i8> %x, <i8 7, i8 7>
@@ -428,6 +428,8 @@ define <2 x i8> @ashr_lowmask_use_splat(<2 x i8> %x, <2 x i8>* %p) {
428428
ret <2 x i8> %r
429429
}
430430

431+
; negative test - must keep all low bits
432+
431433
define i32 @ashr_not_lowmask1_use(i32 %x) {
432434
; CHECK-LABEL: @ashr_not_lowmask1_use(
433435
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 24
@@ -441,6 +443,8 @@ define i32 @ashr_not_lowmask1_use(i32 %x) {
441443
ret i32 %r
442444
}
443445

446+
; negative test - must keep all low bits
447+
444448
define i32 @ashr_not_lowmask2_use(i32 %x) {
445449
; CHECK-LABEL: @ashr_not_lowmask2_use(
446450
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 24
@@ -454,6 +458,8 @@ define i32 @ashr_not_lowmask2_use(i32 %x) {
454458
ret i32 %r
455459
}
456460

461+
; negative test - must keep only low bits
462+
457463
define i32 @ashr_not_lowmask3_use(i32 %x) {
458464
; CHECK-LABEL: @ashr_not_lowmask3_use(
459465
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 24
@@ -1231,14 +1237,14 @@ define i32 @lowmask_sext_in_reg(i32 %x) {
12311237
ret i32 %and
12321238
}
12331239

1234-
; Negative test - mismatched shift amounts
1240+
; Mismatched shift amounts, but the mask op can be replaced by a shift.
12351241

12361242
define i32 @lowmask_not_sext_in_reg(i32 %x) {
12371243
; CHECK-LABEL: @lowmask_not_sext_in_reg(
12381244
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 19
12391245
; CHECK-NEXT: [[R:%.*]] = ashr i32 [[L]], 20
12401246
; CHECK-NEXT: call void @use32(i32 [[R]])
1241-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095
1247+
; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[L]], 20
12421248
; CHECK-NEXT: ret i32 [[AND]]
12431249
;
12441250
%l = shl i32 %x, 19

0 commit comments

Comments
 (0)