Skip to content

Commit

Permalink
[InstCombine] Inefficient pattern for high-bits checking (PR38708)
Browse files Browse the repository at this point in the history
Summary:
It is sometimes important to check that some newly-computed value
is non-negative and only `n` bits wide (where `n` is a variable.)
There are **many** ways to check that:
https://godbolt.org/z/o4RB8D
The last variant seems best?
(I'm sure there are some other variations i haven't thought of..)

Let's handle the second variant first, since it is much simpler.
https://rise4fun.com/Alive/LYjY

https://bugs.llvm.org/show_bug.cgi?id=38708

Reviewers: spatel, craig.topper, RKSimon

Reviewed By: spatel

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D51985

llvm-svn: 342067
  • Loading branch information
LebedevRI committed Sep 12, 2018
1 parent aad4027 commit 75404fb
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 16 deletions.
38 changes: 38 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -4623,6 +4623,41 @@ static Instruction *canonicalizeICmpBool(ICmpInst &I,
}
}

// Transform pattern like:
// (1 << Y) u<= X
// (1 << Y) u> X
// Into:
// (X l>> Y) != 0
// (X l>> Y) == 0
static Instruction *foldICmpWithHighBitMask(ICmpInst &Cmp,
InstCombiner::BuilderTy &Builder) {
ICmpInst::Predicate Pred;
Value *X, *Y;
if (!match(&Cmp,
m_c_ICmp(Pred, m_OneUse(m_Shl(m_One(), m_Value(Y))), m_Value(X))))
return nullptr;

// We want X to be the icmp's second operand, so swap predicate if it is not.
if (Cmp.getOperand(0) == X)
Pred = Cmp.getSwappedPredicate();

ICmpInst::Predicate NewPred;
switch (Pred) {
case ICmpInst::ICMP_ULE:
NewPred = ICmpInst::ICMP_NE;
break;
case ICmpInst::ICMP_UGT:
NewPred = ICmpInst::ICMP_EQ;
break;
default:
return nullptr;
}

Value *NewX = Builder.CreateLShr(X, Y, X->getName() + ".highbits");
Constant *Zero = Constant::getNullValue(NewX->getType());
return CmpInst::Create(Instruction::ICmp, NewPred, NewX, Zero);
}

static Instruction *foldVectorCmp(CmpInst &Cmp,
InstCombiner::BuilderTy &Builder) {
// If both arguments of the cmp are shuffles that use the same mask and
Expand Down Expand Up @@ -4913,6 +4948,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
return foldICmpAddOpConst(X, *C, I.getSwappedPredicate());
}

if (Instruction *Res = foldICmpWithHighBitMask(I, Builder))
return Res;

if (I.getType()->isVectorTy())
if (Instruction *Res = foldVectorCmp(I, Builder))
return Res;
Expand Down
Expand Up @@ -14,8 +14,8 @@

define i1 @p0(i8 %val, i8 %bits) {
; CHECK-LABEL: @p0(
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
Expand All @@ -29,8 +29,8 @@ define i1 @p0(i8 %val, i8 %bits) {

define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
; CHECK-LABEL: @p1_vec(
; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt <2 x i8> [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%t0 = shl <2 x i8> <i8 1, i8 1>, %bits
Expand All @@ -40,8 +40,8 @@ define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {

define <3 x i1> @p2_vec_undef(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef(
; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ugt <3 x i8> [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <3 x i1> [[R]]
;
%t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
Expand All @@ -57,9 +57,9 @@ declare i8 @gen8()

define i1 @c0(i8 %bits) {
; CHECK-LABEL: @c0(
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[VAL]], [[T0]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
Expand Down
Expand Up @@ -14,8 +14,8 @@

define i1 @p0(i8 %val, i8 %bits) {
; CHECK-LABEL: @p0(
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
Expand All @@ -29,8 +29,8 @@ define i1 @p0(i8 %val, i8 %bits) {

define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
; CHECK-LABEL: @p1_vec(
; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ule <2 x i8> [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <2 x i1> [[R]]
;
%t0 = shl <2 x i8> <i8 1, i8 1>, %bits
Expand All @@ -40,8 +40,8 @@ define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {

define <3 x i1> @p2_vec_undef(<3 x i8> %val, <3 x i8> %bits) {
; CHECK-LABEL: @p2_vec_undef(
; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ule <3 x i8> [[T0]], [[VAL:%.*]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
; CHECK-NEXT: ret <3 x i1> [[R]]
;
%t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
Expand All @@ -57,9 +57,9 @@ declare i8 @gen8()

define i1 @c0(i8 %bits) {
; CHECK-LABEL: @c0(
; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[VAL]], [[T0]]
; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%t0 = shl i8 1, %bits
Expand Down

0 comments on commit 75404fb

Please sign in to comment.