Skip to content

Commit

Permalink
[InstCombine] Fold X + Y + C u< X
Browse files Browse the repository at this point in the history
This is a variation on the X + Y u< X fold with an extra constant.
Proof: https://alive2.llvm.org/ce/z/VNb8pY
  • Loading branch information
nikic committed Apr 25, 2022
1 parent e38b1f7 commit 2bec8d6
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 31 deletions.
18 changes: 18 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -3970,6 +3970,24 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
(Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE))
return new ICmpInst(Pred, X, Builder.CreateNot(Op0));

{
// (Op1 + X) + C u</u>= Op1 --> ~C - X u</u>= Op1
Constant *C;
if (match(Op0, m_OneUse(m_Add(m_c_Add(m_Specific(Op1), m_Value(X)),
m_ImmConstant(C)))) &&
(Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_UGE)) {
Constant *C2 = ConstantExpr::getNot(C);
return new ICmpInst(Pred, Builder.CreateSub(C2, X), Op1);
}
// Op0 u>/u<= (Op0 + X) + C --> Op0 u>/u<= ~C - X
if (match(Op1, m_OneUse(m_Add(m_c_Add(m_Specific(Op0), m_Value(X)),
m_ImmConstant(C)))) &&
(Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE)) {
Constant *C2 = ConstantExpr::getNot(C);
return new ICmpInst(Pred, Op0, Builder.CreateSub(C2, X));
}
}

{
// Similar to above: an unsigned overflow comparison may use offset + mask:
// ((Op1 + C) & C) u< Op1 --> Op1 != 0
Expand Down
49 changes: 20 additions & 29 deletions llvm/test/Transforms/InstCombine/icmp-add.ll
Expand Up @@ -1027,9 +1027,8 @@ define i32 @decrement_min(i32 %x) {

define i1 @icmp_add_add_C(i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C(
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add1 = add i32 %a, %b
Expand All @@ -1040,9 +1039,8 @@ define i1 @icmp_add_add_C(i32 %a, i32 %b) {

define i1 @icmp_add_add_C_pred(i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_pred(
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add1 = add i32 %a, %b
Expand Down Expand Up @@ -1079,9 +1077,8 @@ define i1 @icmp_add_add_C_wrong_operand(i32 %a, i32 %b, i32 %c) {

define i1 @icmp_add_add_C_different_const(i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_different_const(
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], 42
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 -43, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add1 = add i32 %a, %b
Expand All @@ -1092,9 +1089,8 @@ define i1 @icmp_add_add_C_different_const(i32 %a, i32 %b) {

define <2 x i1> @icmp_add_add_C_vector(<2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @icmp_add_add_C_vector(
; CHECK-NEXT: [[ADD1:%.*]] = add <2 x i8> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add <2 x i8> [[ADD1]], <i8 10, i8 20>
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> <i8 -11, i8 -21>, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%add1 = add <2 x i8> %a, %b
Expand All @@ -1105,9 +1101,8 @@ define <2 x i1> @icmp_add_add_C_vector(<2 x i8> %a, <2 x i8> %b) {

define <2 x i1> @icmp_add_add_C_vector_undef(<2 x i8> %a, <2 x i8> %b) {
; CHECK-LABEL: @icmp_add_add_C_vector_undef(
; CHECK-NEXT: [[ADD1:%.*]] = add <2 x i8> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add <2 x i8> [[ADD1]], <i8 10, i8 undef>
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> <i8 -11, i8 undef>, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret <2 x i1> [[CMP]]
;
%add1 = add <2 x i8> %a, %b
Expand All @@ -1118,9 +1113,8 @@ define <2 x i1> @icmp_add_add_C_vector_undef(<2 x i8> %a, <2 x i8> %b) {

define i1 @icmp_add_add_C_comm1(i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_comm1(
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A:%.*]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add1 = add i32 %b, %a
Expand All @@ -1132,9 +1126,8 @@ define i1 @icmp_add_add_C_comm1(i32 %a, i32 %b) {
define i1 @icmp_add_add_C_comm2(i32 %X, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_comm2(
; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[X:%.*]]
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A]], [[ADD2]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A]], [[TMP1]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = udiv i32 42, %X ; thwart complexity-based canonicalization
Expand All @@ -1147,9 +1140,8 @@ define i1 @icmp_add_add_C_comm2(i32 %X, i32 %b) {
define i1 @icmp_add_add_C_comm2_pred(i32 %X, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_comm2_pred(
; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[X:%.*]]
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A]], [[ADD2]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[A]], [[TMP1]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = udiv i32 42, %X ; thwart complexity-based canonicalization
Expand Down Expand Up @@ -1177,9 +1169,8 @@ define i1 @icmp_add_add_C_comm2_wrong_pred(i32 %X, i32 %b) {
define i1 @icmp_add_add_C_comm3(i32 %X, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_comm3(
; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[X:%.*]]
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A]], [[B:%.*]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A]], [[ADD2]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[A]], [[TMP1]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%a = udiv i32 42, %X ; thwart complexity-based canonicalization
Expand Down Expand Up @@ -1208,8 +1199,8 @@ define i1 @icmp_add_add_C_extra_use2(i32 %a, i32 %b) {
; CHECK-LABEL: @icmp_add_add_C_extra_use2(
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: call void @use(i32 [[ADD1]])
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], -1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD2]], [[A]]
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[B]]
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP1]], [[A]]
; CHECK-NEXT: ret i1 [[CMP]]
;
%add1 = add i32 %a, %b
Expand Down
Expand Up @@ -254,7 +254,7 @@ define i1 @t7(i8 %base, i8 %offset) {
; CHECK-LABEL: @t7(
; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
; CHECK-NEXT: ret i1 [[TMP2]]
;
Expand All @@ -270,7 +270,7 @@ define i1 @t7_logical(i8 %base, i8 %offset) {
; CHECK-LABEL: @t7_logical(
; CHECK-NEXT: [[ADJUSTED:%.*]] = add i8 [[BASE:%.*]], [[OFFSET:%.*]]
; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]])
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[ADJUSTED]], -1
; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[OFFSET]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i8 [[TMP1]], [[BASE]]
; CHECK-NEXT: ret i1 [[TMP2]]
;
Expand Down

0 comments on commit 2bec8d6

Please sign in to comment.