Skip to content

Commit

Permalink
[InstCombine] add fold for (ShiftC >> X) <u C
Browse files Browse the repository at this point in the history
https://alive2.llvm.org/ce/z/RcdzM-

This fixes a regression noted in issue #56046.
  • Loading branch information
rotateright committed Jun 19, 2022
1 parent 1ebe5ca commit 0399473
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 14 deletions.
27 changes: 20 additions & 7 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -2215,22 +2215,35 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
if (Cmp.isEquality() && Shr->isExact() && C.isZero())
return new ICmpInst(Pred, X, Cmp.getOperand(1));

const APInt *ShiftVal;
if (Cmp.isEquality() && match(Shr->getOperand(0), m_APInt(ShiftVal)))
return foldICmpShrConstConst(Cmp, Shr->getOperand(1), C, *ShiftVal);
bool IsAShr = Shr->getOpcode() == Instruction::AShr;
const APInt *ShiftValC;
if (match(Shr->getOperand(0), m_APInt(ShiftValC))) {
if (Cmp.isEquality())
return foldICmpShrConstConst(Cmp, Shr->getOperand(1), C, *ShiftValC);

const APInt *ShiftAmt;
if (!match(Shr->getOperand(1), m_APInt(ShiftAmt)))
// If the shifted constant is a power-of-2, test the shift amount directly:
// (ShiftValC >> X) >u C --> X <u (LZ(C) - LZ(ShiftValC))
// TODO: Handle ult.
if (!IsAShr && Pred == CmpInst::ICMP_UGT && ShiftValC->isPowerOf2()) {
assert(ShiftValC->ugt(C) && "Expected simplify of compare");
unsigned CmpLZ = C.countLeadingZeros();
unsigned ShiftLZ = ShiftValC->countLeadingZeros();
Constant *NewC = ConstantInt::get(Shr->getType(), CmpLZ - ShiftLZ);
return new ICmpInst(ICmpInst::ICMP_ULT, Shr->User::getOperand(1), NewC);
}
}

const APInt *ShiftAmtC;
if (!match(Shr->getOperand(1), m_APInt(ShiftAmtC)))
return nullptr;

// Check that the shift amount is in range. If not, don't perform undefined
// shifts. When the shift is visited it will be simplified.
unsigned TypeBits = C.getBitWidth();
unsigned ShAmtVal = ShiftAmt->getLimitedValue(TypeBits);
unsigned ShAmtVal = ShiftAmtC->getLimitedValue(TypeBits);
if (ShAmtVal >= TypeBits || ShAmtVal == 0)
return nullptr;

bool IsAShr = Shr->getOpcode() == Instruction::AShr;
bool IsExact = Shr->isExact();
Type *ShrTy = Shr->getType();
// TODO: If we could guarantee that InstSimplify would handle all of the
Expand Down
17 changes: 10 additions & 7 deletions llvm/test/Transforms/InstCombine/icmp-shr.ll
Expand Up @@ -1008,8 +1008,7 @@ define i1 @ashr_exact_ne_0_multiuse(i8 %x) {

define i1 @lshr_pow2_ugt(i8 %x) {
; CHECK-LABEL: @lshr_pow2_ugt(
; CHECK-NEXT: [[S:%.*]] = lshr i8 2, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[S]], 1
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = lshr i8 2, %x
Expand All @@ -1021,7 +1020,7 @@ define i1 @lshr_pow2_ugt_use(i8 %x) {
; CHECK-LABEL: @lshr_pow2_ugt_use(
; CHECK-NEXT: [[S:%.*]] = lshr i8 -128, [[X:%.*]]
; CHECK-NEXT: call void @use(i8 [[S]])
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[S]], 5
; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X]], 5
; CHECK-NEXT: ret i1 [[R]]
;
%s = lshr i8 128, %x
Expand All @@ -1032,15 +1031,16 @@ define i1 @lshr_pow2_ugt_use(i8 %x) {

define <2 x i1> @lshr_pow2_ugt_vec(<2 x i8> %x) {
; CHECK-LABEL: @lshr_pow2_ugt_vec(
; CHECK-NEXT: [[S:%.*]] = lshr <2 x i8> <i8 8, i8 8>, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[S]], <i8 6, i8 6>
; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%s = lshr <2 x i8> <i8 8, i8 8>, %x
%r = icmp ugt <2 x i8> %s, <i8 6, i8 6>
ret <2 x i1> %r
}

; negative test - need power-of-2

define i1 @lshr_not_pow2_ugt(i8 %x) {
; CHECK-LABEL: @lshr_not_pow2_ugt(
; CHECK-NEXT: [[S:%.*]] = lshr i8 3, [[X:%.*]]
Expand All @@ -1054,15 +1054,16 @@ define i1 @lshr_not_pow2_ugt(i8 %x) {

define i1 @lshr_pow2_ugt1(i8 %x) {
; CHECK-LABEL: @lshr_pow2_ugt1(
; CHECK-NEXT: [[S:%.*]] = lshr i8 -128, [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[S]], 1
; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X:%.*]], 7
; CHECK-NEXT: ret i1 [[R]]
;
%s = lshr i8 128, %x
%r = icmp ugt i8 %s, 1
ret i1 %r
}

; negative test - need logical shift

define i1 @ashr_pow2_ugt(i8 %x) {
; CHECK-LABEL: @ashr_pow2_ugt(
; CHECK-NEXT: [[S:%.*]] = ashr i8 -128, [[X:%.*]]
Expand All @@ -1074,6 +1075,8 @@ define i1 @ashr_pow2_ugt(i8 %x) {
ret i1 %r
}

; negative test - need unsigned pred

define i1 @lshr_pow2_sgt(i8 %x) {
; CHECK-LABEL: @lshr_pow2_sgt(
; CHECK-NEXT: [[S:%.*]] = lshr i8 -128, [[X:%.*]]
Expand Down

0 comments on commit 0399473

Please sign in to comment.