Skip to content

Commit

Permalink
[InstCombine] remove constant by inverting compare + logic (PR27105)
Browse files Browse the repository at this point in the history
https://llvm.org/bugs/show_bug.cgi?id=27105

We can check if all bits outside of a constant mask are set with a 
single constant.

As noted in the bug report, although this form should be considered the
canonical IR, backends may want to transform this into an 'andn' / 'andc' 
comparison against zero because that could be a single machine instruction.

Differential Revision: http://reviews.llvm.org/D18842


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266362 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
rotateright committed Apr 14, 2016
1 parent 755d4ed commit fc164bf
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/Transforms/InstCombine/InstCombineCompares.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2248,6 +2248,15 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
Constant *NotCI = ConstantExpr::getNot(RHS);
if (!ConstantExpr::getAnd(BOC, NotCI)->isNullValue())
return replaceInstUsesWith(ICI, Builder->getInt1(isICMP_NE));

// Comparing if all bits outside of a constant mask are set?
// Replace (X | C) == -1 with (X & ~C) == ~C.
// This removes the -1 constant.
if (BO->hasOneUse() && RHS->isAllOnesValue()) {
Constant *NotBOC = ConstantExpr::getNot(BOC);
Value *And = Builder->CreateAnd(BO->getOperand(0), NotBOC);
return new ICmpInst(ICI.getPredicate(), And, NotBOC);
}
}
break;

Expand Down
23 changes: 23 additions & 0 deletions test/Transforms/InstCombine/icmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1956,3 +1956,26 @@ define i1 @PR26407(i32 %x, i32 %y) {
%cmp = icmp uge i32 %addx, %addy
ret i1 %cmp
}

define i1 @cmp_inverse_mask_bits_set_eq(i32 %x) {
; CHECK-LABEL: @cmp_inverse_mask_bits_set_eq(
; CHECK-NEXT: [[TMP1:%.*]] = and i32 %x, -43
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], -43
; CHECK-NEXT: ret i1 [[CMP]]
;
%or = or i32 %x, 42
%cmp = icmp eq i32 %or, -1
ret i1 %cmp
}

define i1 @cmp_inverse_mask_bits_set_ne(i32 %x) {
; CHECK-LABEL: @cmp_inverse_mask_bits_set_ne(
; CHECK-NEXT: [[TMP1:%.*]] = and i32 %x, -43
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], -43
; CHECK-NEXT: ret i1 [[CMP]]
;
%or = or i32 %x, 42
%cmp = icmp ne i32 %or, -1
ret i1 %cmp
}

0 comments on commit fc164bf

Please sign in to comment.