[llvm] [ValueTracking] Compute known bits from recursive select/phi (PR #113707)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 25 09:26:46 PDT 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/113707
This patch is inspired by https://github.com/llvm/llvm-project/pull/113686. I found that it removes a lot of unnecessary "and X, 1" in some applications that represent boolean values with int.
>From 5f0ad3232bf1ebab020284895b61c5b8dea6f4d1 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 26 Oct 2024 00:16:13 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
.../InstCombine/known-phi-recurse.ll | 118 ++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/known-phi-recurse.ll b/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
index c2007d16ae93be..7604f3f0c17849 100644
--- a/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
+++ b/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
@@ -142,3 +142,121 @@ end:
ret i32 %res
}
+define i32 @knownbits_phi_select_test1(ptr %p1, ptr %p2, i8 %x) {
+; CHECK-LABEL: @knownbits_phi_select_test1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[INDVAR1:%.*]] = phi i8 [ [[LOAD2:%.*]], [[BB2:%.*]] ], [ [[X:%.*]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[INDVAR3:%.*]] = phi ptr [ [[INDVAR3_NEXT:%.*]], [[BB2]] ], [ [[P1:%.*]], [[ENTRY]] ]
+; CHECK-NEXT: [[INDVAR4:%.*]] = phi i32 [ [[INDVAR4_NEXT:%.*]], [[BB2]] ], [ 0, [[ENTRY]] ]
+; CHECK-NEXT: [[INDVAR5:%.*]] = phi i32 [ [[INDVAR5_NEXT:%.*]], [[BB2]] ], [ 0, [[ENTRY]] ]
+; CHECK-NEXT: switch i8 [[INDVAR1]], label [[DEFAULT:%.*]] [
+; CHECK-NEXT: i8 0, label [[EXIT:%.*]]
+; CHECK-NEXT: i8 59, label [[BB1:%.*]]
+; CHECK-NEXT: i8 35, label [[BB1]]
+; CHECK-NEXT: ]
+; CHECK: default:
+; CHECK-NEXT: [[EXT:%.*]] = sext i8 [[INDVAR1]] to i64
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i16, ptr [[P2:%.*]], i64 [[EXT]]
+; CHECK-NEXT: [[LOAD1:%.*]] = load i16, ptr [[GEP1]], align 2
+; CHECK-NEXT: [[MASK:%.*]] = and i16 [[LOAD1]], 8192
+; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i16 [[MASK]], 0
+; CHECK-NEXT: br i1 [[CMP1]], label [[BB2]], label [[BB1]]
+; CHECK: bb1:
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[INDVAR4]], 0
+; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[INDVAR5]], 0
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP3]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[BB2]], label [[EXIT]]
+; CHECK: bb2:
+; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[INDVAR1]], 39
+; CHECK-NEXT: [[CMP5:%.*]] = icmp eq i32 [[INDVAR4]], 0
+; CHECK-NEXT: [[EXT2:%.*]] = zext i1 [[CMP5]] to i32
+; CHECK-NEXT: [[INDVAR4_NEXT]] = select i1 [[CMP4]], i32 [[EXT2]], i32 [[INDVAR4]]
+; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i8 [[INDVAR1]], 34
+; CHECK-NEXT: [[CMP7:%.*]] = icmp eq i32 [[INDVAR5]], 0
+; CHECK-NEXT: [[EXT3:%.*]] = zext i1 [[CMP7]] to i32
+; CHECK-NEXT: [[INDVAR5_NEXT]] = select i1 [[CMP6]], i32 [[EXT3]], i32 [[INDVAR5]]
+; CHECK-NEXT: [[INDVAR3_NEXT]] = getelementptr inbounds i8, ptr [[INDVAR3]], i64 1
+; CHECK-NEXT: [[LOAD2]] = load i8, ptr [[INDVAR3_NEXT]], align 1
+; CHECK-NEXT: br label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: ret i32 [[INDVAR5]]
+;
+entry:
+ br label %loop
+
+loop:
+ %indvar1 = phi i8 [ %load2, %bb2 ], [ %x, %entry ]
+ %indvar2 = phi i64 [ %indvar2.next, %bb2 ], [ 0, %entry ]
+ %indvar3 = phi ptr [ %indvar3.next, %bb2 ], [ %p1, %entry ]
+ %indvar4 = phi i32 [ %indvar4.next, %bb2 ], [ 0, %entry ]
+ %indvar5 = phi i32 [ %indvar5.next, %bb2 ], [ 0, %entry ]
+ switch i8 %indvar1, label %default [
+ i8 0, label %exit
+ i8 59, label %bb1
+ i8 35, label %bb1
+ ]
+
+default:
+ %ext = sext i8 %indvar1 to i64
+ %gep1 = getelementptr inbounds i16, ptr %p2, i64 %ext
+ %load1 = load i16, ptr %gep1, align 2
+ %mask = and i16 %load1, 8192
+ %cmp1 = icmp eq i16 %mask, 0
+ br i1 %cmp1, label %bb2, label %bb1
+
+bb1:
+ %cmp2 = icmp ne i32 %indvar4, 0
+ %cmp3 = icmp ne i32 %indvar5, 0
+ %or.cond = select i1 %cmp2, i1 true, i1 %cmp3
+ br i1 %or.cond, label %bb2, label %exit
+
+bb2:
+ %cmp4 = icmp eq i8 %indvar1, 39
+ %cmp5 = icmp eq i32 %indvar4, 0
+ %ext2 = zext i1 %cmp5 to i32
+ %indvar4.next = select i1 %cmp4, i32 %ext2, i32 %indvar4
+ %cmp6 = icmp eq i8 %indvar1, 34
+ %cmp7 = icmp eq i32 %indvar5, 0
+ %ext3 = zext i1 %cmp7 to i32
+ %indvar5.next = select i1 %cmp6, i32 %ext3, i32 %indvar5
+ %indvar3.next = getelementptr inbounds i8, ptr %indvar3, i64 1
+ %indvar2.next = add i64 %indvar2, 1
+ %load2 = load i8, ptr %indvar3.next, align 1
+ br label %loop
+
+exit:
+ ret i32 %indvar5
+}
+
+define i8 @knownbits_phi_select_test2() {
+; CHECK-LABEL: @knownbits_phi_select_test2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[INDVAR:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[CONTAIN:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[COND0:%.*]] = call i1 @cond()
+; CHECK-NEXT: [[CONTAIN]] = select i1 [[COND0]], i8 1, i8 [[INDVAR]]
+; CHECK-NEXT: [[COND1:%.*]] = call i1 @cond()
+; CHECK-NEXT: br i1 [[COND1]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[CONTAIN]], 1
+; CHECK-NEXT: ret i8 [[TMP0]]
+;
+entry:
+ br label %loop
+
+loop:
+ %indvar = phi i8 [ 0, %entry ], [ %contain, %loop ]
+ %cond0 = call i1 @cond()
+ %contain = select i1 %cond0, i8 1, i8 %indvar
+ %cond1 = call i1 @cond()
+ br i1 %cond1, label %exit, label %loop
+
+exit:
+ %bool = and i8 %contain, 1
+ ret i8 %bool
+}
+
+declare i1 @cond()
>From 015584b9b69e3f06e77f59f138cda5ba21b2bca3 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 26 Oct 2024 00:23:35 +0800
Subject: [PATCH 2/2] [ValueTracking] Compute known bits from recursive
select/phi
---
llvm/lib/Analysis/ValueTracking.cpp | 7 +++++++
.../Transforms/InstCombine/known-phi-recurse.ll | 13 +++++--------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index e9ed8b3c862b55..e443488a56b3cb 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1566,6 +1566,13 @@ static void computeKnownBitsFromOperator(const Operator *I,
// Skip direct self references.
if (IncValue == P) continue;
+ // If the Use is a select of this phi, use the knownbit of the other
+ // operand to break the recursion.
+ Value *V;
+ if (match(IncValue, m_Select(m_Value(), m_Specific(P), m_Value(V))) ||
+ match(IncValue, m_Select(m_Value(), m_Value(V), m_Specific(P))))
+ IncValue = V;
+
// Change the context instruction to the "edge" that flows into the
// phi. This is important because that is where the value is actually
// "evaluated" even though it is used later somewhere else. (see also
diff --git a/llvm/test/Transforms/InstCombine/known-phi-recurse.ll b/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
index 7604f3f0c17849..fd3728324b8ea8 100644
--- a/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
+++ b/llvm/test/Transforms/InstCombine/known-phi-recurse.ll
@@ -170,13 +170,11 @@ define i32 @knownbits_phi_select_test1(ptr %p1, ptr %p2, i8 %x) {
; CHECK-NEXT: br i1 [[OR_COND]], label [[BB2]], label [[EXIT]]
; CHECK: bb2:
; CHECK-NEXT: [[CMP4:%.*]] = icmp eq i8 [[INDVAR1]], 39
-; CHECK-NEXT: [[CMP5:%.*]] = icmp eq i32 [[INDVAR4]], 0
-; CHECK-NEXT: [[EXT2:%.*]] = zext i1 [[CMP5]] to i32
-; CHECK-NEXT: [[INDVAR4_NEXT]] = select i1 [[CMP4]], i32 [[EXT2]], i32 [[INDVAR4]]
+; CHECK-NEXT: [[EXT2:%.*]] = zext i1 [[CMP4]] to i32
+; CHECK-NEXT: [[INDVAR4_NEXT]] = xor i32 [[INDVAR4]], [[EXT2]]
; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i8 [[INDVAR1]], 34
-; CHECK-NEXT: [[CMP7:%.*]] = icmp eq i32 [[INDVAR5]], 0
-; CHECK-NEXT: [[EXT3:%.*]] = zext i1 [[CMP7]] to i32
-; CHECK-NEXT: [[INDVAR5_NEXT]] = select i1 [[CMP6]], i32 [[EXT3]], i32 [[INDVAR5]]
+; CHECK-NEXT: [[EXT3:%.*]] = zext i1 [[CMP6]] to i32
+; CHECK-NEXT: [[INDVAR5_NEXT]] = xor i32 [[INDVAR5]], [[EXT3]]
; CHECK-NEXT: [[INDVAR3_NEXT]] = getelementptr inbounds i8, ptr [[INDVAR3]], i64 1
; CHECK-NEXT: [[LOAD2]] = load i8, ptr [[INDVAR3_NEXT]], align 1
; CHECK-NEXT: br label [[LOOP]]
@@ -241,8 +239,7 @@ define i8 @knownbits_phi_select_test2() {
; CHECK-NEXT: [[COND1:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[COND1]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
-; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[CONTAIN]], 1
-; CHECK-NEXT: ret i8 [[TMP0]]
+; CHECK-NEXT: ret i8 [[CONTAIN]]
;
entry:
br label %loop
More information about the llvm-commits
mailing list