[llvm] [ConstraintElim] Add facts for sdiv with a positive divisor. (PR #225535)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 05:59:04 PDT 2026


================
@@ -0,0 +1,492 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+declare void @llvm.assume(i1)
+
+define i1 @sdiv_sge_zero(i32 noundef %x) {
+; CHECK-LABEL: define i1 @sdiv_sge_zero(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[NNEG:%.*]] = icmp sge i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[NNEG]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 4
+; CHECK-NEXT:    ret i1 true
+;
+  %nneg = icmp sge i32 %x, 0
+  call void @llvm.assume(i1 %nneg)
+  %q = sdiv i32 %x, 4
+  %c = icmp sge i32 %q, 0
+  ret i1 %c
+}
+
+define i1 @sdiv_sle_dividend(i32 noundef %x) {
+; CHECK-LABEL: define i1 @sdiv_sle_dividend(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[NNEG:%.*]] = icmp sge i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[NNEG]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 2
+; CHECK-NEXT:    ret i1 true
+;
+  %nneg = icmp sge i32 %x, 0
+  call void @llvm.assume(i1 %nneg)
+  %q = sdiv i32 %x, 2
+  %c = icmp sle i32 %q, %x
+  ret i1 %c
+}
+
+define i1 @sdiv_slt_dividend(i32 noundef %x) {
+; CHECK-LABEL: define i1 @sdiv_slt_dividend(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 2
+; CHECK-NEXT:    ret i1 true
+;
+  %pos = icmp sgt i32 %x, 0
+  call void @llvm.assume(i1 %pos)
+  %q = sdiv i32 %x, 2
+  %c = icmp slt i32 %q, %x
+  ret i1 %c
+}
+
+define i1 @sdiv_slt_dividend_bound(i32 noundef %x, i32 noundef %limit) {
+; CHECK-LABEL: define i1 @sdiv_slt_dividend_bound(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[LIMIT:%.*]]) {
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[LE:%.*]] = icmp sle i32 [[X]], [[LIMIT]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[LE]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 3
+; CHECK-NEXT:    ret i1 true
+;
+  %pos = icmp sgt i32 %x, 0
+  call void @llvm.assume(i1 %pos)
+  %le = icmp sle i32 %x, %limit
+  call void @llvm.assume(i1 %le)
+  %q = sdiv i32 %x, 3
+  %c = icmp slt i32 %q, %limit
+  ret i1 %c
+}
+
+define i1 @sdiv_positive_divisor(i32 noundef %x, i32 noundef %n) {
+; CHECK-LABEL: define i1 @sdiv_positive_divisor(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[N:%.*]]) {
+; CHECK-NEXT:    [[NNEG:%.*]] = icmp sge i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[NNEG]])
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i32 [[N]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], [[N]]
+; CHECK-NEXT:    ret i1 true
+;
+  %nneg = icmp sge i32 %x, 0
+  call void @llvm.assume(i1 %nneg)
+  %pos = icmp sgt i32 %n, 0
+  call void @llvm.assume(i1 %pos)
+  %q = sdiv i32 %x, %n
+  %c = icmp sle i32 %q, %x
+  ret i1 %c
+}
+
+define i1 @sdiv_slt_dividend_divisor_gt_one(i32 noundef %x, i32 noundef %n) {
+; CHECK-LABEL: define i1 @sdiv_slt_dividend_divisor_gt_one(
+; CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[N:%.*]]) {
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[GT1:%.*]] = icmp sgt i32 [[N]], 1
+; CHECK-NEXT:    call void @llvm.assume(i1 [[GT1]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], [[N]]
+; CHECK-NEXT:    ret i1 true
+;
+  %pos = icmp sgt i32 %x, 0
+  call void @llvm.assume(i1 %pos)
+  %gt1 = icmp sgt i32 %n, 1
+  call void @llvm.assume(i1 %gt1)
+  %q = sdiv i32 %x, %n
+  %c = icmp slt i32 %q, %x
+  ret i1 %c
+}
+
+define i1 @sdiv_ult_dividend_via_transfer(i32 noundef %x) {
+; CHECK-LABEL: define i1 @sdiv_ult_dividend_via_transfer(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i32 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 4
+; CHECK-NEXT:    ret i1 true
+;
+  %pos = icmp sgt i32 %x, 0
+  call void @llvm.assume(i1 %pos)
+  %q = sdiv i32 %x, 4
+  %c = icmp ult i32 %q, %x
+  ret i1 %c
+}
+
+define i1 @sdiv_nneg_dividend_from_valuetracking(i32 noundef %y) {
+; CHECK-LABEL: define i1 @sdiv_nneg_dividend_from_valuetracking(
+; CHECK-SAME: i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:    [[X:%.*]] = and i32 [[Y]], 255
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 [[X]], 2
+; CHECK-NEXT:    ret i1 true
+;
+  %x = and i32 %y, 255
+  %q = sdiv i32 %x, 2
+  %c = icmp sge i32 %q, 0
+  ret i1 %c
+}
+
+define i1 @sdiv_const_dividend() {
+; CHECK-LABEL: define i1 @sdiv_const_dividend() {
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i32 42, 4
+; CHECK-NEXT:    ret i1 true
+;
+  %q = sdiv i32 42, 4
+  %c = icmp slt i32 %q, 42
+  ret i1 %c
+}
+
+define i1 @sdiv_smax_divisor(i64 noundef %x, i64 noundef %limit) {
+; CHECK-LABEL: define i1 @sdiv_smax_divisor(
+; CHECK-SAME: i64 noundef [[X:%.*]], i64 noundef [[LIMIT:%.*]]) {
+; CHECK-NEXT:    [[POS:%.*]] = icmp sgt i64 [[X]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[POS]])
+; CHECK-NEXT:    [[LE:%.*]] = icmp sle i64 [[X]], [[LIMIT]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[LE]])
+; CHECK-NEXT:    [[Q:%.*]] = sdiv i64 [[X]], 9223372036854775807
+; CHECK-NEXT:    [[C:%.*]] = icmp slt i64 [[Q]], [[LIMIT]]
+; CHECK-NEXT:    ret i1 [[C]]
----------------
antoniofrighetto wrote:

Nit: this could be folded too, right? (Would perhaps suggest adding the to-be-folded tests in the same PR that adds the code for it.)

https://github.com/llvm/llvm-project/pull/225535


More information about the llvm-commits mailing list