Skip to content

Commit

Permalink
[InstCombine] Fold BW/2+1 tops bits are same pattern
Browse files Browse the repository at this point in the history
Match "icmp eq (trunc (lsr A, BW), (ashr (trunc A), BW-1))", which checks
the top BW/2 + 1 bits are all the same. Create "A >=s INT_MIN && A <=s
INT_MAX", which we generate as "icmp ult (add A, 2^BW-1), 2^BW" to skip
a few steps of instcombining.
https://alive2.llvm.org/ce/z/NjH6Ty
https://alive2.llvm.org/ce/z/_fEQ9P

Differential Revision: https://reviews.llvm.org/D109155
  • Loading branch information
davemgreen committed Oct 29, 2021
1 parent ec32d54 commit 11630db
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 155 deletions.
16 changes: 16 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4586,6 +4586,22 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
: new ICmpInst(ICmpInst::ICMP_UGT, CtPop, ConstantInt::get(Ty, 1));
}

// Match icmp eq (trunc (lshr A, BW), (ashr (trunc A), BW-1)), which checks the
// top BW/2 + 1 bits are all the same. Create "A >=s INT_MIN && A <=s INT_MAX",
// which we generate as "icmp ult (add A, 2^(BW-1)), 2^BW" to skip a few steps
// of instcombine.
unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
if (match(Op0, m_AShr(m_Trunc(m_Value(A)), m_SpecificInt(BitWidth - 1))) &&
match(Op1, m_Trunc(m_LShr(m_Specific(A), m_SpecificInt(BitWidth)))) &&
A->getType()->getScalarSizeInBits() == BitWidth * 2 &&
(I.getOperand(0)->hasOneUse() || I.getOperand(1)->hasOneUse())) {
APInt C = APInt::getOneBitSet(BitWidth * 2, BitWidth - 1);
Value *Add = Builder.CreateAdd(A, ConstantInt::get(A->getType(), C));
return new ICmpInst(Pred == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_ULT
: ICmpInst::ICMP_UGE,
Add, ConstantInt::get(A->getType(), C.shl(1)));
}

return nullptr;
}

Expand Down
54 changes: 17 additions & 37 deletions llvm/test/Transforms/InstCombine/icmp-topbitssame.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ declare void @use16(i16)

define i1 @testi16i8(i16 %add) {
; CHECK-LABEL: @testi16i8(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i16 %add, 8
Expand All @@ -24,11 +21,8 @@ define i1 @testi16i8(i16 %add) {

define i1 @testi16i8_com(i16 %add) {
; CHECK-LABEL: @testi16i8_com(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i16 %add, 8
Expand All @@ -41,11 +35,8 @@ define i1 @testi16i8_com(i16 %add) {

define i1 @testi16i8_ne(i16 %add) {
; CHECK-LABEL: @testi16i8_ne(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ne i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ugt i16 [[TMP1]], 255
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i16 %add, 8
Expand All @@ -58,11 +49,8 @@ define i1 @testi16i8_ne(i16 %add) {

define i1 @testi16i8_ne_com(i16 %add) {
; CHECK-LABEL: @testi16i8_ne_com(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ne i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD:%.*]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ugt i16 [[TMP1]], 255
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i16 %add, 8
Expand All @@ -75,11 +63,8 @@ define i1 @testi16i8_ne_com(i16 %add) {

define i1 @testi64i32(i64 %add) {
; CHECK-LABEL: @testi64i32(
; CHECK-NEXT: [[SH:%.*]] = lshr i64 [[ADD:%.*]], 32
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i64 [[SH]] to i32
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[ADD:%.*]], 2147483648
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i64 [[TMP1]], 4294967296
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i64 %add, 32
Expand All @@ -92,11 +77,8 @@ define i1 @testi64i32(i64 %add) {

define i1 @testi64i32_ne(i64 %add) {
; CHECK-LABEL: @testi64i32_ne(
; CHECK-NEXT: [[SH:%.*]] = lshr i64 [[ADD:%.*]], 32
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i64 [[SH]] to i32
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i64 [[ADD]] to i32
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i32 [[CONV1_I]], 31
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ne i32 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[ADD:%.*]], 2147483648
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ugt i64 [[TMP1]], 4294967295
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
%sh = lshr i64 %add, 32
Expand Down Expand Up @@ -181,11 +163,10 @@ define i1 @slt(i64 %add) {

define i1 @extrause_a(i16 %add) {
; CHECK-LABEL: @extrause_a(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD:%.*]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256
; CHECK-NEXT: call void @use(i8 [[SHR2_I]])
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
Expand All @@ -202,9 +183,8 @@ define i1 @extrause_l(i16 %add) {
; CHECK-LABEL: @extrause_l(
; CHECK-NEXT: [[SH:%.*]] = lshr i16 [[ADD:%.*]], 8
; CHECK-NEXT: [[CONV_I:%.*]] = trunc i16 [[SH]] to i8
; CHECK-NEXT: [[CONV1_I:%.*]] = trunc i16 [[ADD]] to i8
; CHECK-NEXT: [[SHR2_I:%.*]] = ashr i8 [[CONV1_I]], 7
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[SHR2_I]], [[CONV_I]]
; CHECK-NEXT: [[TMP1:%.*]] = add i16 [[ADD]], 128
; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i16 [[TMP1]], 256
; CHECK-NEXT: call void @use(i8 [[CONV_I]])
; CHECK-NEXT: ret i1 [[CMP_NOT_I]]
;
Expand Down
Loading

0 comments on commit 11630db

Please sign in to comment.