[llvm] [ValueTracking] isNonZero sub of ptr2int's with recursive GEP (PR #68680)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 24 03:28:49 PDT 2023
https://github.com/bipmis updated https://github.com/llvm/llvm-project/pull/68680
>From a1369af8df901b4cefd2e13f5e5cd8cec4f04042 Mon Sep 17 00:00:00 2001
From: bipmis <biplob.mishra at arm.com>
Date: Mon, 9 Oct 2023 15:07:19 +0100
Subject: [PATCH 1/4] Precommit tests for ValueTracking isKnownNonZero with
recursive GEP
---
.../Analysis/ValueTracking/phi-known-bits.ll | 337 ++++++++++++++++++
1 file changed, 337 insertions(+)
diff --git a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
index 5227661c837347e..228b80129512443 100644
--- a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
+++ b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
@@ -424,3 +424,340 @@ T:
F:
br label %T
}
+
+define i1 @phi_sub_recursiveGEP_knownNonZero1(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_knownNonZero1_PhiOperandsCommuted(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero1_PhiOperandsCommuted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[VAL1]], [[ENTRY:%.*]] ], [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %val1, %entry ], [ %test.0.i, %while.cond.i ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_knownNonZero1_SubOperandsCommuted(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero1_SubOperandsCommuted(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.rhs.cast.i, %sub.ptr.lhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_knownNonZero2(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 -1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 -1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_knownNonZero3(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I_IDX:%.*]] = phi i64 [ [[A_PN_I_ADD:%.*]], [[WHILE_COND_I]] ], [ 7, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[A_PN_I_ADD]] = add nuw nsw i64 [[A_PN_I_IDX]], 1
+; CHECK-NEXT: [[TEST_0_I_PTR:%.*]] = getelementptr inbounds i8, ptr [[VAL1]], i64 [[A_PN_I_ADD]]
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I_PTR]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[A_PN_I_ADD]], 5
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %test.val1 = getelementptr inbounds i8, ptr %val1, i64 7
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %test.val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %1 = getelementptr inbounds i8, ptr %val1, i64 5
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_notknownNonZero1(ptr noundef %val1, i64 %val2) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_notknownNonZero1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[VAL1]], i64 [[VAL2:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TEST_0_I]], [[TMP1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP2]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %1 = getelementptr inbounds i8, ptr %val1, i64 %val2
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_notknownNonZero2(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_notknownNonZero2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TEST_VAL1:%.*]] = getelementptr inbounds i8, ptr [[VAL1:%.*]], i64 -1
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %test.val1 = getelementptr inbounds i8, ptr %val1, i64 -1
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %test.val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
+
+define i1 @phi_sub_recursiveGEP_notknownNonZero3(ptr noundef %val1) {
+; CHECK-LABEL: @phi_sub_recursiveGEP_notknownNonZero3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TEST_VAL1:%.*]] = getelementptr inbounds i8, ptr [[VAL1:%.*]], i64 5
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1]], null
+; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
+; CHECK: while.cond.i:
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 -1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
+; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
+; CHECK: while.end.i:
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
+; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
+; CHECK: _Z9stringlenPKs.exit:
+; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
+; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+;
+entry:
+ %test.val1 = getelementptr inbounds i8, ptr %val1, i64 5
+ %cmp.i = icmp eq ptr %val1, null
+ br i1 %cmp.i, label %_Z9stringlenPKs.exit, label %while.cond.i
+
+while.cond.i:
+ %a.pn.i = phi ptr [ %test.0.i, %while.cond.i ], [ %test.val1, %entry ]
+ %test.0.i = getelementptr inbounds i8, ptr %a.pn.i, i64 -1
+ %0 = load i8, ptr %test.0.i, align 2
+ %cmp3.not.i = icmp eq i8 %0, 0
+ br i1 %cmp3.not.i, label %while.end.i, label %while.cond.i
+
+while.end.i:
+ %sub.ptr.lhs.cast.i = ptrtoint ptr %test.0.i to i64
+ %sub.ptr.rhs.cast.i = ptrtoint ptr %val1 to i64
+ %sub.ptr.sub.i = sub i64 %sub.ptr.lhs.cast.i, %sub.ptr.rhs.cast.i
+ br label %_Z9stringlenPKs.exit
+
+_Z9stringlenPKs.exit:
+ %retval.0.i = phi i64 [ %sub.ptr.sub.i, %while.end.i ], [ 0, %entry ]
+ %bool = icmp eq i64 %retval.0.i, 0
+ ret i1 %bool
+}
>From c053b902e375a0efd31d902261001f1e74dbdecb Mon Sep 17 00:00:00 2001
From: bipmis <biplob.mishra at arm.com>
Date: Mon, 9 Oct 2023 15:19:49 +0100
Subject: [PATCH 2/4] isNonZeroSub for ptr2int with one of them being a
Recursive GEP
---
llvm/lib/Analysis/ValueTracking.cpp | 67 +++++++++++++++++++
.../Analysis/ValueTracking/phi-known-bits.ll | 30 +++------
2 files changed, 77 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f510f6a42f08c12..c367c8edc750869 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2410,9 +2410,76 @@ static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth,
.isNonZero();
}
+static bool isNonZeroSubWithRecursiveGEP(const SimplifyQuery &Q, Value *X,
+ Value *Y) {
+ // Handle sub(PtrtoInt(LHS), PtrtoInt(RHS))
+ // Where LHS is a recursive GEP for an incoming value of PHI indicating a
+ // loop. RHS can be a ptr/GEP.
+ // If the PHI has 2 incoming values, one of it being the recursive GEP
+ // and other a ptr at same base and at an same/higher offset than RHS we are
+ // only incrementing the pointer further in loop if offset of recursive GEP is
+ // greater than 0.
+ Value *LHS, *RHS;
+ // sub(PtrtoInt(LHS), PtrtoInt(RHS))
+ if (match(X, m_PtrToInt(m_Value(LHS))) &&
+ match(Y, m_PtrToInt(m_Value(RHS)))) {
+ GEPOperator *LHSGEP = dyn_cast<GEPOperator>(LHS);
+ // Make sure LHS GEP pointer operand is a PHI. If sub(A,B) is non zero, so
+ // is sub(B,A)
+ if (!LHSGEP || !isa<PHINode>(LHSGEP->getPointerOperand())) {
+ LHSGEP = dyn_cast<GEPOperator>(RHS);
+ std::swap(LHS, RHS);
+ }
+ if (LHSGEP && isa<PHINode>(LHSGEP->getPointerOperand())) {
+ // Handle 2 incoming values with one being a recursive GEP.
+ auto *PN = dyn_cast<PHINode>(LHSGEP->getPointerOperand());
+ if (PN->getNumIncomingValues() == 2) {
+ // Recursive GEP in second incoming value. Always keep Recursive GEP as
+ // FirstInst
+ Value *FirstInst = nullptr, *SecondInst = nullptr;
+ for (unsigned i = 0; i != 2; ++i) {
+ // Check if LHS is a Recursive GEP in one of the incoming values.
+ if (PN->getIncomingValue(i) == LHS && LHSGEP->getNumIndices() == 1 &&
+ isa<Constant>(LHSGEP->idx_begin())) {
+ FirstInst = PN->getIncomingValue(i);
+ SecondInst = PN->getIncomingValue(!i);
+ continue;
+ }
+ }
+
+ if (FirstInst && SecondInst) {
+ // Other incoming node base should match the RHS base.
+ // SecondInstOffset >= RHSOffset && FirstInstOffset > 0?
+ // SecondInstOffset <= RHSOffset && FirstInstOffset < 0?
+ // Is non-zero if above are true.
+ APInt FirstInstOffset(
+ Q.DL.getIndexTypeSizeInBits(FirstInst->getType()), 0);
+ FirstInst = FirstInst->stripAndAccumulateConstantOffsets(
+ Q.DL, FirstInstOffset, /* AllowNonInbounds */ true);
+ APInt SecondInstOffset(
+ Q.DL.getIndexTypeSizeInBits(SecondInst->getType()), 0);
+ SecondInst = SecondInst->stripAndAccumulateConstantOffsets(
+ Q.DL, SecondInstOffset, /* AllowNonInbounds */ true);
+ APInt RHSOffset(Q.DL.getIndexTypeSizeInBits(RHS->getType()), 0);
+ RHS = RHS->stripAndAccumulateConstantOffsets(
+ Q.DL, RHSOffset, /* AllowNonInbounds */ true);
+ if (SecondInst == RHS &&
+ ((SecondInstOffset.sge(RHSOffset) && FirstInstOffset.sgt(0)) ||
+ (SecondInstOffset.sle(RHSOffset) && FirstInstOffset.slt(0))))
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
const SimplifyQuery &Q, unsigned BitWidth, Value *X,
Value *Y) {
+ if(isNonZeroSubWithRecursiveGEP(Q, X, Y))
+ return true;
+
if (auto *C = dyn_cast<Constant>(X))
if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Depth, Q))
return true;
diff --git a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
index 228b80129512443..6b01c9d3da09f11 100644
--- a/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
+++ b/llvm/test/Analysis/ValueTracking/phi-known-bits.ll
@@ -437,11 +437,9 @@ define i1 @phi_sub_recursiveGEP_knownNonZero1(ptr noundef %val1) {
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
; CHECK: _Z9stringlenPKs.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
entry:
%cmp.i = icmp eq ptr %val1, null
@@ -478,11 +476,9 @@ define i1 @phi_sub_recursiveGEP_knownNonZero1_PhiOperandsCommuted(ptr noundef %v
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
; CHECK: _Z9stringlenPKs.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
entry:
%cmp.i = icmp eq ptr %val1, null
@@ -519,11 +515,9 @@ define i1 @phi_sub_recursiveGEP_knownNonZero1_SubOperandsCommuted(ptr noundef %v
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
; CHECK: _Z9stringlenPKs.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
entry:
%cmp.i = icmp eq ptr %val1, null
@@ -560,11 +554,9 @@ define i1 @phi_sub_recursiveGEP_knownNonZero2(ptr noundef %val1) {
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TEST_0_I]], [[VAL1]]
; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
; CHECK: _Z9stringlenPKs.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
entry:
%cmp.i = icmp eq ptr %val1, null
@@ -592,21 +584,19 @@ _Z9stringlenPKs.exit:
define i1 @phi_sub_recursiveGEP_knownNonZero3(ptr noundef %val1) {
; CHECK-LABEL: @phi_sub_recursiveGEP_knownNonZero3(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1:%.*]], null
+; CHECK-NEXT: [[TEST_VAL1:%.*]] = getelementptr inbounds i8, ptr [[VAL1:%.*]], i64 7
+; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL1]], null
; CHECK-NEXT: br i1 [[CMP_I]], label [[_Z9STRINGLENPKS_EXIT:%.*]], label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
-; CHECK-NEXT: [[A_PN_I_IDX:%.*]] = phi i64 [ [[A_PN_I_ADD:%.*]], [[WHILE_COND_I]] ], [ 7, [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[A_PN_I_ADD]] = add nuw nsw i64 [[A_PN_I_IDX]], 1
-; CHECK-NEXT: [[TEST_0_I_PTR:%.*]] = getelementptr inbounds i8, ptr [[VAL1]], i64 [[A_PN_I_ADD]]
-; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I_PTR]], align 2
+; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
+; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[A_PN_I_ADD]], 5
; CHECK-NEXT: br label [[_Z9STRINGLENPKS_EXIT]]
; CHECK: _Z9stringlenPKs.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP1]], [[WHILE_END_I]] ], [ true, [[ENTRY]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: ret i1 [[CMP_I]]
;
entry:
%test.val1 = getelementptr inbounds i8, ptr %val1, i64 7
>From 66864d8066b50215f3d8731ef4b1d7919ed91f69 Mon Sep 17 00:00:00 2001
From: bipmis <biplob.mishra at arm.com>
Date: Tue, 17 Oct 2023 17:28:40 +0100
Subject: [PATCH 3/4] Correct code formatting
---
llvm/lib/Analysis/ValueTracking.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c367c8edc750869..b017a191c88f034 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2477,7 +2477,7 @@ static bool isNonZeroSubWithRecursiveGEP(const SimplifyQuery &Q, Value *X,
static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
const SimplifyQuery &Q, unsigned BitWidth, Value *X,
Value *Y) {
- if(isNonZeroSubWithRecursiveGEP(Q, X, Y))
+ if (isNonZeroSubWithRecursiveGEP(Q, X, Y))
return true;
if (auto *C = dyn_cast<Constant>(X))
>From 662b5e4d85d8f58342cfe9571bf9c1c2d3f9d8d0 Mon Sep 17 00:00:00 2001
From: bipmis <biplob.mishra at arm.com>
Date: Tue, 24 Oct 2023 11:28:22 +0100
Subject: [PATCH 4/4] correct the CHECKS for the test sub-gep
---
llvm/test/Transforms/InstCombine/sub-gep.ll | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/llvm/test/Transforms/InstCombine/sub-gep.ll b/llvm/test/Transforms/InstCombine/sub-gep.ll
index a8f8a82e675b026..f6611c942907659 100644
--- a/llvm/test/Transforms/InstCombine/sub-gep.ll
+++ b/llvm/test/Transforms/InstCombine/sub-gep.ll
@@ -386,11 +386,10 @@ define i1 @_gep_phi1(ptr noundef %str1) {
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
-; CHECK-NEXT: [[TMP2:%.*]] = icmp ne ptr [[TEST_0_I]], [[STR1]]
; CHECK-NEXT: br label [[_Z3FOOPKC_EXIT]]
; CHECK: _Z3fooPKc.exit:
-; CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i1 [ [[TMP2]], [[WHILE_END_I]] ], [ false, [[LOR_LHS_FALSE_I]] ], [ false, [[ENTRY:%.*]] ]
-; CHECK-NEXT: ret i1 [[RETVAL_0_I]]
+; CHECK-NEXT: [[TOBOOL:%.*]] = phi i1 [ true, [[WHILE_END_I]] ], [ false, [[LOR_LHS_FALSE_I]] ], [ false, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i1 [[TOBOOL]]
;
entry:
%cmp.i = icmp eq ptr %str1, null
More information about the llvm-commits
mailing list