[llvm] [ConstraintElimination] Extend unsigned-to-signed fact transfer (PR #66173)

Antonio Frighetto via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 22 11:27:12 PDT 2023


https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/66173

>From 9335491aed96ff8a3fb32a6855fecacb2b54357d Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 22 Sep 2023 18:10:50 +0000
Subject: [PATCH 1/2] [ConstraintElimination] Introduce tests for PR66173

Introduce test cases for extending
unsigned-to-signed transfer logic.
---
 .../transfer-unsigned-facts-to-signed.ll      | 105 ++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll b/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
index 34b27dd42e338aa..45dc73a9cc11bbb 100644
--- a/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
+++ b/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
@@ -228,3 +228,108 @@ then:
 else:
   ret i1 0
 }
+
+define i1 @ule_signed_pos_constant_1(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_signed_pos_constant_1(
+; CHECK-NEXT:    [[B_NON_NEG:%.*]] = icmp sge i8 [[B:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NON_NEG]])
+; CHECK-NEXT:    [[A_ULE_B:%.*]] = icmp ule i8 [[A:%.*]], [[B]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[A_ULE_B]])
+; CHECK-NEXT:    [[SLE_TEST:%.*]] = icmp sle i8 [[A]], [[B]]
+; CHECK-NEXT:    [[SLT_TEST:%.*]] = icmp slt i8 [[A]], [[B]]
+; CHECK-NEXT:    [[RESULT_XOR:%.*]] = xor i1 [[SLE_TEST]], [[SLT_TEST]]
+; CHECK-NEXT:    ret i1 [[RESULT_XOR]]
+;
+  %b_non_neg = icmp sge i8 %b, 0
+  call void @llvm.assume(i1 %b_non_neg)
+  %a_ule_b = icmp ule i8 %a, %b
+  call void @llvm.assume(i1 %a_ule_b)
+
+  %sle_test = icmp sle i8 %a, %b
+  %slt_test = icmp slt i8 %a, %b
+  %result_xor = xor i1 %sle_test, %slt_test
+
+  ret i1 %result_xor
+}
+
+define i1 @ule_signed_pos_constant_2(i8 %a) {
+; CHECK-LABEL: @ule_signed_pos_constant_2(
+; CHECK-NEXT:    [[A_ULT_4:%.*]] = icmp ule i8 [[A:%.*]], 4
+; CHECK-NEXT:    br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK:       then:
+; CHECK-NEXT:    [[T_0:%.*]] = icmp sge i8 [[A]], 0
+; CHECK-NEXT:    [[T_1:%.*]] = icmp sle i8 [[A]], 4
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_0]], [[T_1]]
+; CHECK-NEXT:    [[C_0:%.*]] = icmp sle i8 [[A]], 5
+; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_0]]
+; CHECK-NEXT:    ret i1 [[RES_2]]
+; CHECK:       else:
+; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
+; CHECK-NEXT:    [[C_3:%.*]] = icmp sle i8 [[A]], 4
+; CHECK-NEXT:    [[RES_3:%.*]] = xor i1 [[C_2]], [[C_3]]
+; CHECK-NEXT:    [[C_4:%.*]] = icmp sle i8 [[A]], 5
+; CHECK-NEXT:    [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_4]]
+; CHECK-NEXT:    ret i1 [[RES_4]]
+;
+  %a.ult.4 = icmp ule i8 %a, 4
+  br i1 %a.ult.4, label %then, label %else
+
+then:
+  %t.0 = icmp sge i8 %a, 0
+  %t.1 = icmp sle i8 %a, 4
+  %res.1 = xor i1 %t.0, %t.1
+
+  %c.0 = icmp sle i8 %a, 5
+  %res.2 = xor i1 %res.1, %c.0
+  ret i1 %res.2
+
+else:
+  %c.2 = icmp sge i8 %a, 0
+  %c.3 = icmp sle i8 %a, 4
+  %res.3 = xor i1 %c.2, %c.3
+
+  %c.4 = icmp sle i8 %a, 5
+  %res.4 = xor i1 %res.3, %c.4
+
+  ret i1 %res.4
+}
+
+define i1 @uge_assumed_positive_values(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_assumed_positive_values(
+; CHECK-NEXT:    [[A_NON_NEG:%.*]] = icmp sge i8 [[A:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NON_NEG]])
+; CHECK-NEXT:    [[A_UGT_B:%.*]] = icmp uge i8 [[A]], [[B:%.*]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[A_UGT_B]])
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp sge i8 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+  %a_non_neg = icmp sge i8 %a, 0
+  call void @llvm.assume(i1 %a_non_neg)
+  %a_ugt_b = icmp uge i8 %a, %b
+  call void @llvm.assume(i1 %a_ugt_b)
+
+  %result = icmp sge i8 %a, %b
+
+  ret i1 %result
+}
+
+define i1 @ugt_assumed_positive_values(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_assumed_positive_values(
+; CHECK-NEXT:    [[A_NON_NEG:%.*]] = icmp sge i8 [[A:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NON_NEG]])
+; CHECK-NEXT:    [[A_UGT_B:%.*]] = icmp ugt i8 [[A]], [[B:%.*]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[A_UGT_B]])
+; CHECK-NEXT:    [[RESULT:%.*]] = icmp sgt i8 [[A]], [[B]]
+; CHECK-NEXT:    ret i1 [[RESULT]]
+;
+  %a_non_neg = icmp sge i8 %a, 0
+  call void @llvm.assume(i1 %a_non_neg)
+  %a_ugt_b = icmp ugt i8 %a, %b
+  call void @llvm.assume(i1 %a_ugt_b)
+
+  %result = icmp sgt i8 %a, %b
+
+  ret i1 %result
+}
+
+declare void @llvm.assume(i1)

>From d5bf12f0d0dfdee71a4012f2f63e6cdfb5b66726 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Fri, 22 Sep 2023 18:25:40 +0000
Subject: [PATCH 2/2] [ConstraintElimination] Extend unsigned-to-signed fact
 transfer

Minor addition of transferring unsigned facts to signed comparisons.
---
 .../Transforms/Scalar/ConstraintElimination.cpp | 17 +++++++++++++++--
 .../signed-query-unsigned-system.ll             |  3 +--
 .../transfer-unsigned-facts-to-signed.ll        | 16 +++++-----------
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index fd6b6b553348511..368b800964deb9a 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -25,6 +25,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/Verifier.h"
@@ -748,11 +749,23 @@ void ConstraintInfo::transferToOtherSystem(
   default:
     break;
   case CmpInst::ICMP_ULT:
-    //  If B is a signed positive constant, A >=s 0 and A <s B.
+  case CmpInst::ICMP_ULE:
+    //  If B is a signed positive constant, then A >=s 0 and A <s (or <=s) B.
     if (doesHold(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0))) {
       addFact(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0), NumIn,
               NumOut, DFSInStack);
-      addFact(CmpInst::ICMP_SLT, A, B, NumIn, NumOut, DFSInStack);
+      addFact(CmpInst::getSignedPredicate(Pred), A, B, NumIn, NumOut,
+              DFSInStack);
+    }
+    break;
+  case CmpInst::ICMP_UGE:
+  case CmpInst::ICMP_UGT:
+    //  If A is a signed positive constant, then B >=s 0 and A >s (or >=s) B.
+    if (doesHold(CmpInst::ICMP_SGE, A, ConstantInt::get(B->getType(), 0))) {
+      addFact(CmpInst::ICMP_SGE, B, ConstantInt::get(B->getType(), 0), NumIn,
+              NumOut, DFSInStack);
+      addFact(CmpInst::getSignedPredicate(Pred), A, B, NumIn, NumOut,
+              DFSInStack);
     }
     break;
   case CmpInst::ICMP_SLT:
diff --git a/llvm/test/Transforms/ConstraintElimination/signed-query-unsigned-system.ll b/llvm/test/Transforms/ConstraintElimination/signed-query-unsigned-system.ll
index f5f7cc222f5a827..63d0c3ea3609c7e 100644
--- a/llvm/test/Transforms/ConstraintElimination/signed-query-unsigned-system.ll
+++ b/llvm/test/Transforms/ConstraintElimination/signed-query-unsigned-system.ll
@@ -109,8 +109,7 @@ define i1 @sge_no_const_unsigned_uge(i8 %a, i16 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_UGE_B]])
 ; CHECK-NEXT:    [[B_POS:%.*]] = icmp sge i16 [[B]], 0
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[B_POS]])
-; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i16 [[EXT]], [[B]]
-; CHECK-NEXT:    ret i1 [[CMP]]
+; CHECK-NEXT:    ret i1 true
 ;
   %ext = zext i8 %a to i16
   %a.uge.b = icmp uge i16 %ext, %b
diff --git a/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll b/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
index 45dc73a9cc11bbb..60e915fcebc3eae 100644
--- a/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
+++ b/llvm/test/Transforms/ConstraintElimination/transfer-unsigned-facts-to-signed.ll
@@ -235,9 +235,8 @@ define i1 @ule_signed_pos_constant_1(i8 %a, i8 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NON_NEG]])
 ; CHECK-NEXT:    [[A_ULE_B:%.*]] = icmp ule i8 [[A:%.*]], [[B]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_ULE_B]])
-; CHECK-NEXT:    [[SLE_TEST:%.*]] = icmp sle i8 [[A]], [[B]]
 ; CHECK-NEXT:    [[SLT_TEST:%.*]] = icmp slt i8 [[A]], [[B]]
-; CHECK-NEXT:    [[RESULT_XOR:%.*]] = xor i1 [[SLE_TEST]], [[SLT_TEST]]
+; CHECK-NEXT:    [[RESULT_XOR:%.*]] = xor i1 true, [[SLT_TEST]]
 ; CHECK-NEXT:    ret i1 [[RESULT_XOR]]
 ;
   %b_non_neg = icmp sge i8 %b, 0
@@ -257,11 +256,8 @@ define i1 @ule_signed_pos_constant_2(i8 %a) {
 ; CHECK-NEXT:    [[A_ULT_4:%.*]] = icmp ule i8 [[A:%.*]], 4
 ; CHECK-NEXT:    br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]]
 ; CHECK:       then:
-; CHECK-NEXT:    [[T_0:%.*]] = icmp sge i8 [[A]], 0
-; CHECK-NEXT:    [[T_1:%.*]] = icmp sle i8 [[A]], 4
-; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 [[T_0]], [[T_1]]
-; CHECK-NEXT:    [[C_0:%.*]] = icmp sle i8 [[A]], 5
-; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_0]]
+; CHECK-NEXT:    [[RES_1:%.*]] = xor i1 true, true
+; CHECK-NEXT:    [[RES_2:%.*]] = xor i1 [[RES_1]], true
 ; CHECK-NEXT:    ret i1 [[RES_2]]
 ; CHECK:       else:
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sge i8 [[A]], 0
@@ -300,8 +296,7 @@ define i1 @uge_assumed_positive_values(i8 %a, i8 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NON_NEG]])
 ; CHECK-NEXT:    [[A_UGT_B:%.*]] = icmp uge i8 [[A]], [[B:%.*]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_UGT_B]])
-; CHECK-NEXT:    [[RESULT:%.*]] = icmp sge i8 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a_non_neg = icmp sge i8 %a, 0
   call void @llvm.assume(i1 %a_non_neg)
@@ -319,8 +314,7 @@ define i1 @ugt_assumed_positive_values(i8 %a, i8 %b) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NON_NEG]])
 ; CHECK-NEXT:    [[A_UGT_B:%.*]] = icmp ugt i8 [[A]], [[B:%.*]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[A_UGT_B]])
-; CHECK-NEXT:    [[RESULT:%.*]] = icmp sgt i8 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RESULT]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a_non_neg = icmp sge i8 %a, 0
   call void @llvm.assume(i1 %a_non_neg)



More information about the llvm-commits mailing list