From acafde09a3fa9560148605f35f9c3d3f1444bc15 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 9 Oct 2021 11:34:48 -0400 Subject: [PATCH] [InstCombine] enhance icmp with sub folds There were 2 related but over-specified folds for: C1 - X == C One allowed multi-use but was limited to equal constants. The other allowed different constants but disallowed multi-use. This combines the 2 folds into a more general match. The test diffs show the multi-use cases that were falling through the cracks. https://alive2.llvm.org/ce/z/4_hEt2 define i1 @src(i8 %x, i8 %subC, i8 %C) { %s = sub i8 %subC, %x %r = icmp eq i8 %s, %C ret i1 %r } define i1 @tgt(i8 %x, i8 %subC, i8 %C) { %newC = sub i8 %subC, %C %isneg = icmp eq i8 %x, %newC ret i1 %isneg } --- .../Transforms/InstCombine/InstCombineCompares.cpp | 25 +++++++++++----------- llvm/test/Transforms/InstCombine/icmp-sub.ll | 16 +++++++------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 03044acd..e080e7f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2579,21 +2579,25 @@ Instruction *InstCombinerImpl::foldICmpSubConstant(ICmpInst &Cmp, const APInt &C) { Value *X = Sub->getOperand(0), *Y = Sub->getOperand(1); ICmpInst::Predicate Pred = Cmp.getPredicate(); - const APInt *C2; - APInt SubResult; + Type *Ty = Sub->getType(); - // icmp eq/ne (sub C, Y), C -> icmp eq/ne Y, 0 - if (match(X, m_APInt(C2)) && *C2 == C && Cmp.isEquality()) - return new ICmpInst(Cmp.getPredicate(), Y, - ConstantInt::get(Y->getType(), 0)); + // (SubC - Y) == C) --> Y == (SubC - C) + // (SubC - Y) != C) --> Y != (SubC - C) + Constant *SubC; + if (Cmp.isEquality() && match(X, m_ImmConstant(SubC))) { + return new ICmpInst(Pred, Y, + ConstantExpr::getSub(SubC, ConstantInt::get(Ty, C))); + } // (icmp P (sub nuw|nsw C2, Y), C) -> (icmp swap(P) Y, C2-C) + const APInt *C2; + APInt SubResult; if (match(X, m_APInt(C2)) && ((Cmp.isUnsigned() && Sub->hasNoUnsignedWrap()) || (Cmp.isSigned() && Sub->hasNoSignedWrap())) && !subWithOverflow(SubResult, *C2, C, Cmp.isSigned())) return new ICmpInst(Cmp.getSwappedPredicate(), Y, - ConstantInt::get(Y->getType(), SubResult)); + ConstantInt::get(Ty, SubResult)); // The following transforms are only worth it if the only user of the subtract // is the icmp. @@ -3122,12 +3126,7 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant( break; case Instruction::Sub: if (BO->hasOneUse()) { - // Only check for constant LHS here, as constant RHS will be canonicalized - // to add and use the fold above. - if (Constant *BOC = dyn_cast(BOp0)) { - // Replace ((sub BOC, B) != C) with (B != BOC-C). - return new ICmpInst(Pred, BOp1, ConstantExpr::getSub(BOC, RHS)); - } else if (C.isZero()) { + if (C.isZero()) { // Replace ((sub A, B) != 0) with (A != B). return new ICmpInst(Pred, BOp0, BOp1); } diff --git a/llvm/test/Transforms/InstCombine/icmp-sub.ll b/llvm/test/Transforms/InstCombine/icmp-sub.ll index 4fa31be..0b62df6 100644 --- a/llvm/test/Transforms/InstCombine/icmp-sub.ll +++ b/llvm/test/Transforms/InstCombine/icmp-sub.ll @@ -204,7 +204,7 @@ define i1 @neg_eq_43(i32 %x) { ; CHECK-LABEL: @neg_eq_43( ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[NEGX]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[NEGX]], 43 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -43 ; CHECK-NEXT: ret i1 [[R]] ; %negx = sub i32 0, %x @@ -217,7 +217,7 @@ define i1 @neg_ne_44(i32 %x) { ; CHECK-LABEL: @neg_ne_44( ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[NEGX]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[NEGX]], 44 +; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -44 ; CHECK-NEXT: ret i1 [[R]] ; %negx = sub i32 0, %x @@ -230,7 +230,7 @@ define i1 @neg_nsw_eq_45(i32 %x) { ; CHECK-LABEL: @neg_nsw_eq_45( ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[NEGX]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[NEGX]], 45 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -45 ; CHECK-NEXT: ret i1 [[R]] ; %negx = sub nsw i32 0, %x @@ -243,7 +243,7 @@ define i1 @neg_nsw_ne_46(i32 %x) { ; CHECK-LABEL: @neg_nsw_ne_46( ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[NEGX]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[NEGX]], 46 +; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -46 ; CHECK-NEXT: ret i1 [[R]] ; %negx = sub nsw i32 0, %x @@ -256,7 +256,7 @@ define i1 @subC_eq(i32 %x) { ; CHECK-LABEL: @subC_eq( ; CHECK-NEXT: [[SUBX:%.*]] = sub i32 -2147483648, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[SUBX]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[SUBX]], 43 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483605 ; CHECK-NEXT: ret i1 [[R]] ; %subx = sub i32 -2147483648, %x @@ -269,7 +269,7 @@ define <2 x i1> @subC_ne(<2 x i8> %x) { ; CHECK-LABEL: @subC_ne( ; CHECK-NEXT: [[SUBX:%.*]] = sub <2 x i8> , [[X:%.*]] ; CHECK-NEXT: call void @use_vec(<2 x i8> [[SUBX]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[SUBX]], +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %subx = sub <2 x i8> , %x @@ -282,7 +282,7 @@ define i1 @subC_nsw_eq(i32 %x) { ; CHECK-LABEL: @subC_nsw_eq( ; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -100, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[SUBX]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[SUBX]], -2147483648 +; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483548 ; CHECK-NEXT: ret i1 [[R]] ; %subx = sub nsw i32 -100, %x @@ -295,7 +295,7 @@ define i1 @subC_nsw_ne(i32 %x) { ; CHECK-LABEL: @subC_nsw_ne( ; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -2147483647, [[X:%.*]] ; CHECK-NEXT: call void @use(i32 [[SUBX]]) -; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[SUBX]], 46 +; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], 2147483603 ; CHECK-NEXT: ret i1 [[R]] ; %subx = sub nsw i32 -2147483647, %x -- 2.7.4