From 4b7a4383be4dd7b775a7def50430eacfa1476344 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 30 Sep 2024 20:52:05 +0800 Subject: [PATCH 1/5] [InstCombine] Add pre-commit tests. NFC. --- llvm/test/Transforms/InstCombine/icmp-add.ll | 96 ++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index dd8e9c1a45ea1..265403f0b0d8c 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3183,3 +3183,99 @@ define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) { %cmp2 = icmp ult i8 %add, 2 ret i1 %cmp2 } + +define i1 @zext_range_check_ult(i8 %x) { +; CHECK-LABEL: @zext_range_check_ult( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = zext i8 %x to i32 + %add = add i32 %conv, -4 + %cmp = icmp ult i32 %add, 3 + ret i1 %cmp +} + +; TODO: should be canonicalized to (x - 4) u> 2 +define i1 @zext_range_check_ugt(i8 %x) { +; CHECK-LABEL: @zext_range_check_ugt( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[CONV]], -7 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[TMP0]], -3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = zext i8 %x to i32 + %add = add i32 %conv, -4 + %cmp = icmp ugt i32 %add, 2 + ret i1 %cmp +} + +; TODO: should be canonicalized to (x - 4) u> 2 +define i1 @zext_range_check_ult_alter(i8 %x) { +; CHECK-LABEL: @zext_range_check_ult_alter( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -7 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], -3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = zext i8 %x to i32 + %add = add i32 %conv, -7 + %cmp = icmp ult i32 %add, -3 + ret i1 %cmp +} + +define i1 @zext_range_check_mergable(i8 %x) { +; CHECK-LABEL: @zext_range_check_mergable( +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[ADD]], 3 +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[X]], 4 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP1]] +; CHECK-NEXT: ret i1 [[COND]] +; + %conv = zext i8 %x to i32 + %add = add nsw i32 %conv, -4 + %cmp1 = icmp ult i32 %add, 3 + %cmp2 = icmp slt i8 %x, 4 + %cond = select i1 %cmp2, i1 true, i1 %cmp1 + ret i1 %cond +} + +; Negative tests + +define i1 @sext_range_check_ult(i8 %x) { +; CHECK-LABEL: @sext_range_check_ult( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = sext i8 %x to i32 + %add = add i32 %conv, -4 + %cmp = icmp ult i32 %add, 3 + ret i1 %cmp +} + +define i1 @zext_range_check_ult_illegal_type(i7 %x) { +; CHECK-LABEL: @zext_range_check_ult_illegal_type( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i7 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = zext i7 %x to i32 + %add = add i32 %conv, -4 + %cmp = icmp ult i32 %add, 3 + ret i1 %cmp +} From cd86ab258d274d5d78b61977cdef405f16099875 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 30 Sep 2024 21:31:02 +0800 Subject: [PATCH 2/5] [InstCombine] Fold `zext(X) + C2 u< C -> X + trunc(C2) u< trunc(C)` --- .../InstCombine/InstCombineCompares.cpp | 20 +++++++++++++++++++ llvm/test/Transforms/InstCombine/icmp-add.ll | 11 +++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d602a907e72bc..d81ad1d27d502 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3183,6 +3183,26 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)), ConstantInt::get(Ty, ~C)); + // zext(V) + C2 V + trunc(C2) 0 + Value *V; + if (Pred == ICmpInst::ICMP_ULT && match(X, m_ZExt(m_Value(V)))) { + Type *NewCmpTy = V->getType(); + unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits(); + if (shouldChangeType(Ty, NewCmpTy) && + C2->getSignificantBits() <= NewCmpBW && + C.getSignificantBits() <= NewCmpBW) { + APInt TruncatedOffset = C2->trunc(NewCmpBW); + APInt TruncatedRHS = C.trunc(NewCmpBW); + if (TruncatedOffset.isNegative() && TruncatedRHS.isNonNegative()) { + Value *TruncatedOffsetV = ConstantInt::get(NewCmpTy, TruncatedOffset); + Value *TruncatedRV = ConstantInt::get(NewCmpTy, TruncatedRHS); + return new ICmpInst(ICmpInst::ICMP_ULT, + Builder.CreateAdd(V, TruncatedOffsetV), + TruncatedRV); + } + } + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index 265403f0b0d8c..6aaea4109adcb 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3187,9 +3187,8 @@ define i1 @icmp_of_ucmp_plus_const_with_const(i32 %x, i32 %y) { define i1 @zext_range_check_ult(i8 %x) { ; CHECK-LABEL: @zext_range_check_ult( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 3 +; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[X:%.*]], -4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[TMP0]], 3 ; CHECK-NEXT: ret i1 [[CMP]] ; entry: @@ -3233,11 +3232,7 @@ entry: define i1 @zext_range_check_mergable(i8 %x) { ; CHECK-LABEL: @zext_range_check_mergable( -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 -; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[ADD]], 3 -; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[X]], 4 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP1]] +; CHECK-NEXT: [[COND:%.*]] = icmp slt i8 [[X:%.*]], 7 ; CHECK-NEXT: ret i1 [[COND]] ; %conv = zext i8 %x to i32 From 6b5d6c95c50ab429c36c3496ebe55e337f972e4d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 6 Oct 2024 15:26:31 +0800 Subject: [PATCH 3/5] [InstCombine] Convert to using ConstantRange API --- .../InstCombine/InstCombineCompares.cpp | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index d81ad1d27d502..1442a9daad5ec 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3183,22 +3183,27 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, Builder.CreateAdd(X, ConstantInt::get(Ty, *C2 - C - 1)), ConstantInt::get(Ty, ~C)); - // zext(V) + C2 V + trunc(C2) 0 + // zext(V) + C2 pred C -> V + C3 pred' C4 Value *V; - if (Pred == ICmpInst::ICMP_ULT && match(X, m_ZExt(m_Value(V)))) { + if (match(X, m_ZExt(m_Value(V)))) { Type *NewCmpTy = V->getType(); + unsigned CmpBW = Ty->getScalarSizeInBits(); unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits(); - if (shouldChangeType(Ty, NewCmpTy) && - C2->getSignificantBits() <= NewCmpBW && - C.getSignificantBits() <= NewCmpBW) { - APInt TruncatedOffset = C2->trunc(NewCmpBW); - APInt TruncatedRHS = C.trunc(NewCmpBW); - if (TruncatedOffset.isNegative() && TruncatedRHS.isNonNegative()) { - Value *TruncatedOffsetV = ConstantInt::get(NewCmpTy, TruncatedOffset); - Value *TruncatedRV = ConstantInt::get(NewCmpTy, TruncatedRHS); - return new ICmpInst(ICmpInst::ICMP_ULT, - Builder.CreateAdd(V, TruncatedOffsetV), - TruncatedRV); + if (shouldChangeType(Ty, NewCmpTy)) { + if (auto ZExtCR = CR.exactIntersectWith(ConstantRange( + APInt::getZero(CmpBW), APInt::getOneBitSet(CmpBW, NewCmpBW)))) { + ConstantRange SrcCR = ZExtCR->truncate(NewCmpBW); + CmpInst::Predicate EquivPred; + APInt EquivInt; + APInt EquivOffset; + + SrcCR.getEquivalentICmp(EquivPred, EquivInt, EquivOffset); + return new ICmpInst( + EquivPred, + EquivOffset.isZero() + ? V + : Builder.CreateAdd(V, ConstantInt::get(NewCmpTy, EquivOffset)), + ConstantInt::get(NewCmpTy, EquivInt)); } } } From f86d2bc28f2fd342f4d0bc7125f537ffd40f9c18 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 21 Nov 2024 17:00:19 +0800 Subject: [PATCH 4/5] [InstCombine] Address review comments. NFC. --- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 1442a9daad5ec..4be576c8ce3b0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3190,9 +3190,8 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, unsigned CmpBW = Ty->getScalarSizeInBits(); unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits(); if (shouldChangeType(Ty, NewCmpTy)) { - if (auto ZExtCR = CR.exactIntersectWith(ConstantRange( - APInt::getZero(CmpBW), APInt::getOneBitSet(CmpBW, NewCmpBW)))) { - ConstantRange SrcCR = ZExtCR->truncate(NewCmpBW); + if (CR.getActiveBits() <= NewCmpBW) { + ConstantRange SrcCR = CR.truncate(NewCmpBW); CmpInst::Predicate EquivPred; APInt EquivInt; APInt EquivOffset; From ec1a880bedaee93ceba83398c9a1a0ca25c08628 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 21 Nov 2024 17:08:50 +0800 Subject: [PATCH 5/5] [InstCombine] Add negative tests. NFC. --- llvm/test/Transforms/InstCombine/icmp-add.ll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index 6aaea4109adcb..579247aaccf28 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3274,3 +3274,18 @@ entry: %cmp = icmp ult i32 %add, 3 ret i1 %cmp } + +define i1 @zext_range_check_ult_range_check_failure(i8 %x) { +; CHECK-LABEL: @zext_range_check_ult_range_check_failure( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[X:%.*]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], -4 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[ADD]], 253 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %conv = zext i8 %x to i32 + %add = add i32 %conv, -4 + %cmp = icmp ult i32 %add, 253 + ret i1 %cmp +}