Skip to content

Commit

Permalink
[InstCombine] Fold or of icmp ne trunc/and
Browse files Browse the repository at this point in the history
This adds the de Morgan conjugated variant for the existing
"and eq" style fold.

Proof: https://alive2.llvm.org/ce/z/tkNAcG
  • Loading branch information
nikic committed Apr 28, 2022
1 parent b5b3e50 commit 90dba83
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 43 deletions.
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Expand Up @@ -2550,10 +2550,11 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
return nullptr;

// (trunc x) == C1 & (and x, CA) == C2 -> (and x, CA|CMAX) == C1|C2
// (trunc x) != C1 | (and x, CA) != C2 -> (and x, CA|CMAX) != C1|C2
// where CMAX is the all ones value for the truncated type,
// iff the lower bits of C2 and CA are zero.
if (IsAnd && PredL == ICmpInst::ICMP_EQ && PredL == PredR &&
LHS->hasOneUse() && RHS->hasOneUse()) {
if (PredL == (IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE) &&
PredL == PredR && LHS->hasOneUse() && RHS->hasOneUse()) {
Value *V;
const APInt *AndC, *SmallC = nullptr, *BigC = nullptr;

Expand Down
60 changes: 19 additions & 41 deletions llvm/test/Transforms/InstCombine/merge-icmp.ll
Expand Up @@ -97,12 +97,8 @@ define <2 x i1> @and_test2_vector(<2 x i16>* %x) {

define i1 @or_basic(i16 %load) {
; CHECK-LABEL: @or_basic(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD:%.*]] to i8
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[TRUNC]], 127
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD]], -256
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i16 [[AND]], 17664
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i16 [[LOAD:%.*]], 17791
; CHECK-NEXT: ret i1 [[TMP1]]
;
%trunc = trunc i16 %load to i8
%cmp1 = icmp ne i8 %trunc, 127
Expand All @@ -114,12 +110,8 @@ define i1 @or_basic(i16 %load) {

define i1 @or_basic_commuted(i16 %load) {
; CHECK-LABEL: @or_basic_commuted(
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD:%.*]], -256
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i16 [[AND]], 32512
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD]] to i8
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[TRUNC]], 69
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i16 [[LOAD:%.*]], 32581
; CHECK-NEXT: ret i1 [[TMP1]]
;
%and = and i16 %load, -256
%cmp1 = icmp ne i16 %and, 32512
Expand All @@ -131,12 +123,8 @@ define i1 @or_basic_commuted(i16 %load) {

define <2 x i1> @or_vector(<2 x i16> %load) {
; CHECK-LABEL: @or_vector(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i16> [[LOAD:%.*]] to <2 x i8>
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne <2 x i8> [[TRUNC]], <i8 127, i8 127>
; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> [[LOAD]], <i16 -256, i16 -256>
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne <2 x i16> [[AND]], <i16 17664, i16 17664>
; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret <2 x i1> [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i16> [[LOAD:%.*]], <i16 17791, i16 17791>
; CHECK-NEXT: ret <2 x i1> [[TMP1]]
;
%trunc = trunc <2 x i16> %load to <2 x i8>
%cmp1 = icmp ne <2 x i8> %trunc, <i8 127, i8 127>
Expand All @@ -148,12 +136,9 @@ define <2 x i1> @or_vector(<2 x i16> %load) {

define i1 @or_nontrivial_mask1(i16 %load) {
; CHECK-LABEL: @or_nontrivial_mask1(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD:%.*]] to i8
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[TRUNC]], 127
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD]], 3840
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i16 [[AND]], 1280
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[LOAD:%.*]], 4095
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i16 [[TMP1]], 1407
; CHECK-NEXT: ret i1 [[TMP2]]
;
%trunc = trunc i16 %load to i8
%cmp1 = icmp ne i8 %trunc, 127
Expand All @@ -165,12 +150,9 @@ define i1 @or_nontrivial_mask1(i16 %load) {

define i1 @or_nontrivial_mask2(i16 %load) {
; CHECK-LABEL: @or_nontrivial_mask2(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD:%.*]] to i8
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[TRUNC]], 127
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD]], -4096
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i16 [[AND]], 20480
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[LOAD:%.*]], -3841
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i16 [[TMP1]], 20607
; CHECK-NEXT: ret i1 [[TMP2]]
;
%trunc = trunc i16 %load to i8
%cmp1 = icmp ne i8 %trunc, 127
Expand Down Expand Up @@ -222,11 +204,9 @@ define i1 @or_extra_use3(i16 %load) {
; CHECK-LABEL: @or_extra_use3(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD:%.*]] to i8
; CHECK-NEXT: call void @use.i8(i8 [[TRUNC]])
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[TRUNC]], 127
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD]], -4096
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i16 [[AND]], 20480
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[LOAD]], -3841
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i16 [[TMP1]], 20607
; CHECK-NEXT: ret i1 [[TMP2]]
;
%trunc = trunc i16 %load to i8
call void @use.i8(i8 %trunc)
Expand All @@ -239,13 +219,11 @@ define i1 @or_extra_use3(i16 %load) {

define i1 @or_extra_use4(i16 %load) {
; CHECK-LABEL: @or_extra_use4(
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i16 [[LOAD:%.*]] to i8
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[TRUNC]], 127
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD]], -4096
; CHECK-NEXT: [[AND:%.*]] = and i16 [[LOAD:%.*]], -4096
; CHECK-NEXT: call void @use.i16(i16 [[AND]])
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i16 [[AND]], 20480
; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
; CHECK-NEXT: ret i1 [[OR]]
; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[LOAD]], -3841
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i16 [[TMP1]], 20607
; CHECK-NEXT: ret i1 [[TMP2]]
;
%trunc = trunc i16 %load to i8
%cmp1 = icmp ne i8 %trunc, 127
Expand Down

0 comments on commit 90dba83

Please sign in to comment.