[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