[llvm] [ValueTracking] Improve `and` and `or` recurrence handling (PR #225775)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 06:52:28 PDT 2026
=?utf-8?q?Ömer_Sinan_Ağacan?= <omer at osa1.net>,
=?utf-8?q?Ömer_Sinan_Ağacan?= <omer at osa1.net>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/225775 at github.com>
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Ömer Sinan Ağacan (osa1)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/225775.diff
2 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+24-2)
- (modified) llvm/test/Transforms/InstCombine/recurrence.ll (+110)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ed1e2f7467e19..2fdf3c4154dd1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1899,13 +1899,35 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
}
+ case Instruction::And: {
+ // Start's zeros will always stay zero, ones can change.
+ KnownBits KnownStep(BitWidth);
+ computeKnownBitsForRecurrenceOperands(P, Start, Step, DemandedElts,
+ KnownStart, KnownStep, Q, Depth);
+
+ Known.Zero = KnownStart.Zero;
+ Known.One = KnownStart.One & KnownStep.One;
+
+ break;
+ }
+
+ case Instruction::Or: {
+ // Start's ones will always stay one, zeros can change.
+ KnownBits KnownStep(BitWidth);
+ computeKnownBitsForRecurrenceOperands(P, Start, Step, DemandedElts,
+ KnownStart, KnownStep, Q, Depth);
+
+ Known.One = KnownStart.One;
+ Known.Zero = KnownStart.Zero & KnownStep.Zero;
+
+ break;
+ }
+
// Check for operations that have the property that if
// both their operands have low zero bits, the result
// will have low zero bits.
case Instruction::Add:
case Instruction::Sub:
- case Instruction::And:
- case Instruction::Or:
case Instruction::Mul: {
// Ok, we have a recurrence of the form {Start,op,Step}. Check for low
// zero bits.
diff --git a/llvm/test/Transforms/InstCombine/recurrence.ll b/llvm/test/Transforms/InstCombine/recurrence.ll
index 090e22c803b76..853e178a86a44 100644
--- a/llvm/test/Transforms/InstCombine/recurrence.ll
+++ b/llvm/test/Transforms/InstCombine/recurrence.ll
@@ -81,6 +81,58 @@ loop: ; preds = %loop, %entry
br label %loop
}
+; The mask should be removed based on Start's ones.
+define i64 @test_or_start_known_ones(i32 %s, ptr %p) {
+; CHECK-LABEL: @test_or_start_known_ones(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[S_EXT:%.*]] = zext i32 [[S:%.*]] to i64
+; CHECK-NEXT: [[START:%.*]] = or disjoint i64 [[S_EXT]], -4294967296
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP:%.*]] = load volatile i64, ptr [[P:%.*]], align 4
+; CHECK-NEXT: [[IV_NEXT]] = or i64 [[IV]], [[STEP]]
+; CHECK-NEXT: tail call void @use(i64 [[IV_NEXT]])
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %s.ext = zext i32 %s to i64
+ %start = or i64 %s.ext, u0xFFFFFFFF00000000
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
+ %step = load volatile i64, ptr %p
+ %iv.next = or i64 %iv, %step
+ %iv.next.masked = or i64 %iv.next, u0xFFFFFFFF00000000
+ tail call void @use(i64 %iv.next.masked)
+ br label %loop
+}
+
+; The mask should be removed based on the known zeros of Start and Step.
+define i64 @test_or_step_known_zeros(i32 %s, ptr %p) {
+; CHECK-LABEL: @test_or_step_known_zeros(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[STEP_I32:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
+; CHECK-NEXT: tail call void @use(i64 0)
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %start = zext i32 %s to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
+ %step.i32 = load volatile i32, ptr %p
+ %step = zext i32 %step.i32 to i64
+ %iv.next = or i64 %iv, %step
+ %iv.next.masked = and i64 %iv.next, u0xFFFFFFFF00000000
+ tail call void @use(i64 %iv.next.masked)
+ br label %loop
+}
+
define i64 @test_and(i64 %a) {
; CHECK-LABEL: @test_and(
; CHECK-NEXT: entry:
@@ -162,6 +214,64 @@ loop: ; preds = %loop, %entry
br label %loop
}
+; The mask should be removed based on Start's zeros.
+define i64 @test_and_start_known_zeros(i32 %s, ptr %p) {
+; CHECK-LABEL: @test_and_start_known_zeros(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[START:%.*]] = zext i32 [[S:%.*]] to i64
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP:%.*]] = load volatile i64, ptr [[P:%.*]], align 4
+; CHECK-NEXT: [[IV_NEXT]] = and i64 [[IV]], [[STEP]]
+; CHECK-NEXT: tail call void @use(i64 [[IV_NEXT]])
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %start = zext i32 %s to i64
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
+ %step = load volatile i64, ptr %p
+ %iv.next = and i64 %iv, %step
+ %iv.next.masked = and i64 %iv.next, u0x00000000FFFFFFFF
+ tail call void @use(i64 %iv.next.masked)
+ br label %loop
+}
+
+; The mask should be removed based on the known ones of Start and Step.
+define i64 @test_and_step_known_ones(i32 %s, ptr %p) {
+; CHECK-LABEL: @test_and_step_known_ones(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[START_ZEXT:%.*]] = zext i32 [[S:%.*]] to i64
+; CHECK-NEXT: [[START:%.*]] = or disjoint i64 [[START_ZEXT]], -4294967296
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_I32:%.*]] = load volatile i32, ptr [[P:%.*]], align 4
+; CHECK-NEXT: [[STEP_ZEXT:%.*]] = zext i32 [[STEP_I32]] to i64
+; CHECK-NEXT: [[STEP:%.*]] = or disjoint i64 [[STEP_ZEXT]], -4294967296
+; CHECK-NEXT: [[IV_NEXT]] = and i64 [[IV]], [[STEP]]
+; CHECK-NEXT: tail call void @use(i64 [[IV_NEXT]])
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %start.zext = zext i32 %s to i64
+ %start = or i64 %start.zext, u0xFFFFFFFF00000000
+ br label %loop
+
+loop:
+ %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ]
+ %step.i32 = load volatile i32, ptr %p
+ %step.zext = zext i32 %step.i32 to i64
+ %step = or i64 %step.zext, u0xFFFFFFFF00000000
+ %iv.next = and i64 %iv, %step
+ %iv.next.masked = or i64 %iv.next, u0xFFFFFFFF00000000
+ tail call void @use(i64 %iv.next.masked)
+ br label %loop
+}
+
declare i32 @get_step()
define i1 @test_loop_variant_step_with_condition() {
``````````
</details>
https://github.com/llvm/llvm-project/pull/225775
More information about the llvm-commits
mailing list