From 90dba831ae50f2c3dc5de1029b1821790411ca9a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 28 Apr 2022 14:44:24 +0200 Subject: [PATCH] [InstCombine] Fold or of icmp ne trunc/and This adds the de Morgan conjugated variant for the existing "and eq" style fold. Proof: https://alive2.llvm.org/ce/z/tkNAcG --- .../Transforms/InstCombine/InstCombineAndOrXor.cpp | 5 +- llvm/test/Transforms/InstCombine/merge-icmp.ll | 60 +++++++--------------- 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 8c25d49..bd910fc 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -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; diff --git a/llvm/test/Transforms/InstCombine/merge-icmp.ll b/llvm/test/Transforms/InstCombine/merge-icmp.ll index 4ca63cd..aaecdf8 100644 --- a/llvm/test/Transforms/InstCombine/merge-icmp.ll +++ b/llvm/test/Transforms/InstCombine/merge-icmp.ll @@ -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 @@ -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 @@ -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]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i16> [[LOAD]], -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne <2 x i16> [[AND]], -; 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:%.*]], +; CHECK-NEXT: ret <2 x i1> [[TMP1]] ; %trunc = trunc <2 x i16> %load to <2 x i8> %cmp1 = icmp ne <2 x i8> %trunc, @@ -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 @@ -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 @@ -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) @@ -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 -- 2.7.4