https://github.com/iamaayushrivastava updated 
https://github.com/llvm/llvm-project/pull/202502

>From 35e9c8c39ef48f68d4d72340a3a7a10e0618a905 Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Tue, 9 Jun 2026 09:37:34 +0530
Subject: [PATCH 1/2] [CIR] Fix constant folding of vector comparisons for
 unsigned types and result values

---
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 48 +++++++++----
 clang/test/CIR/Transforms/vector-cmp-fold.cir | 67 +++++++++++++++----
 2 files changed, 89 insertions(+), 26 deletions(-)

diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index cf07fc4f0833a..987b605193296 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3436,15 +3436,21 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
 
   SmallVector<mlir::Attribute, 16> elements(vecSize);
   bool isIntAttr = vecSize && mlir::isa<cir::IntAttr>(lhsVecElhs[0]);
+  bool isUnsignedInt =
+      isIntAttr && mlir::cast<cir::IntType>(inputElemTy).isUnsigned();
   for (uint64_t i = 0; i < vecSize; i++) {
     mlir::Attribute lhsAttr = lhsVecElhs[i];
     mlir::Attribute rhsAttr = rhsVecElhs[i];
-    int cmpResult = 0;
+    bool cmpResult = false;
     switch (opKind) {
     case cir::CmpOpKind::lt: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        if (isUnsignedInt)
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <
+                      mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
+        else
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <
+                      mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3453,8 +3459,12 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::le: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        if (isUnsignedInt)
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() <=
+                      mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
+        else
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() <=
+                      mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() <=
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3463,8 +3473,12 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::gt: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        if (isUnsignedInt)
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >
+                      mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
+        else
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >
+                      mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3473,8 +3487,12 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::ge: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        if (isUnsignedInt)
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getUInt() >=
+                      mlir::cast<cir::IntAttr>(rhsAttr).getUInt();
+        else
+          cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() >=
+                      mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() >=
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3483,8 +3501,8 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::eq: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getValue() ==
+                    mlir::cast<cir::IntAttr>(rhsAttr).getValue();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3493,8 +3511,8 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::ne: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
-                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
+        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getValue() !=
+                    mlir::cast<cir::IntAttr>(rhsAttr).getValue();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3517,7 +3535,9 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     }
 
-    elements[i] = cir::IntAttr::get(getType().getElementType(), cmpResult);
+    // Vector comparison results are 0 (false) or -1 / all-ones (true).
+    elements[i] =
+        cir::IntAttr::get(getType().getElementType(), cmpResult ? -1LL : 0LL);
   }
 
   return cir::ConstVectorAttr::get(
diff --git a/clang/test/CIR/Transforms/vector-cmp-fold.cir 
b/clang/test/CIR/Transforms/vector-cmp-fold.cir
index f3486bd26fe1b..4d7c81f81cccb 100644
--- a/clang/test/CIR/Transforms/vector-cmp-fold.cir
+++ b/clang/test/CIR/Transforms/vector-cmp-fold.cir
@@ -29,8 +29,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -47,8 +47,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -65,8 +65,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -141,8 +141,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -161,8 +161,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -181,8 +181,8 @@ module  {
   }
 
   // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test() -> !cir.vector<4 x 
!s32i> {
-  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<1> : 
!s32i, #cir.int<1> : !s32i,
-  // CHECK-SAME: #cir.int<1> : !s32i, #cir.int<1> : !s32i]> : !cir.vector<4 x 
!s32i>
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s32i, #cir.int<-1> : !s32i,
+  // CHECK-SAME: #cir.int<-1> : !s32i, #cir.int<-1> : !s32i]> : !cir.vector<4 
x !s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
 
@@ -225,3 +225,46 @@ module  {
   // CHECK-SAME: #cir.int<0> : !s32i, #cir.int<0> : !s32i]> : !cir.vector<4 x 
!s32i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s32i>
 }
+
+// -----
+
+// Test unsigned integer comparisons: result must use unsigned ordering and
+// produce 0 or -1 (all-ones) per the SIMD convention.
+
+!u8i = !cir.int<u, 8>
+!s8i = !cir.int<s, 8>
+
+module  {
+  cir.func @fold_cmp_vector_unsigned_gt() -> !cir.vector<4 x !s8i> {
+    %vec_1 = cir.const #cir.const_vector<[#cir.int<255> : !u8i, #cir.int<0> : 
!u8i, #cir.int<1> : !u8i, #cir.int<254> : !u8i]> : !cir.vector<4 x !u8i>
+    %vec_2 = cir.const #cir.const_vector<[#cir.int<254> : !u8i, #cir.int<255> 
: !u8i, #cir.int<255> : !u8i, #cir.int<255> : !u8i]> : !cir.vector<4 x !u8i>
+    %new_vec = cir.vec.cmp(gt, %vec_1, %vec_2) : !cir.vector<4 x !u8i>, 
!cir.vector<4 x !s8i>
+    cir.return %new_vec : !cir.vector<4 x !s8i>
+  }
+
+  // 255>254 (T), 0>255 (F), 1>255 (F), 254>255 (F) -> [-1, 0, 0, 0]
+  // CHECK:  cir.func{{.*}} @fold_cmp_vector_unsigned_gt() -> !cir.vector<4 x 
!s8i> {
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s8i, #cir.int<0> : !s8i,
+  // CHECK-SAME: #cir.int<0> : !s8i, #cir.int<0> : !s8i]> : !cir.vector<4 x 
!s8i>
+  // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s8i>
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!s8i = !cir.int<s, 8>
+
+module  {
+  cir.func @fold_cmp_vector_unsigned_lt() -> !cir.vector<4 x !s8i> {
+    %vec_1 = cir.const #cir.const_vector<[#cir.int<0> : !u8i, #cir.int<255> : 
!u8i, #cir.int<128> : !u8i, #cir.int<127> : !u8i]> : !cir.vector<4 x !u8i>
+    %vec_2 = cir.const #cir.const_vector<[#cir.int<255> : !u8i, #cir.int<0> : 
!u8i, #cir.int<129> : !u8i, #cir.int<128> : !u8i]> : !cir.vector<4 x !u8i>
+    %new_vec = cir.vec.cmp(lt, %vec_1, %vec_2) : !cir.vector<4 x !u8i>, 
!cir.vector<4 x !s8i>
+    cir.return %new_vec : !cir.vector<4 x !s8i>
+  }
+
+  // 0<255 (T), 255<0 (F), 128<129 (T), 127<128 (T) -> [-1, 0, -1, -1]
+  // CHECK:  cir.func{{.*}} @fold_cmp_vector_unsigned_lt() -> !cir.vector<4 x 
!s8i> {
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!s8i, #cir.int<0> : !s8i,
+  // CHECK-SAME: #cir.int<-1> : !s8i, #cir.int<-1> : !s8i]> : !cir.vector<4 x 
!s8i>
+  // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s8i>
+}

>From 27196909cf36eaf1fa9bc6436da71a866b6e1712 Mon Sep 17 00:00:00 2001
From: iamaayushrivastava <[email protected]>
Date: Wed, 10 Jun 2026 15:42:36 +0530
Subject: [PATCH 2/2] Address review comments on vector comparisons for
 unsigned types

---
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 12 ++++++----
 clang/test/CIR/Transforms/vector-cmp-fold.cir | 24 +++++++++++++++++++
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 987b605193296..d6fee0da92ad1 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -3501,8 +3501,8 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::eq: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getValue() ==
-                    mlir::cast<cir::IntAttr>(rhsAttr).getValue();
+        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() ==
+                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() ==
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3511,8 +3511,8 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     case cir::CmpOpKind::ne: {
       if (isIntAttr) {
-        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getValue() !=
-                    mlir::cast<cir::IntAttr>(rhsAttr).getValue();
+        cmpResult = mlir::cast<cir::IntAttr>(lhsAttr).getSInt() !=
+                    mlir::cast<cir::IntAttr>(rhsAttr).getSInt();
       } else {
         cmpResult = mlir::cast<cir::FPAttr>(lhsAttr).getValue() !=
                     mlir::cast<cir::FPAttr>(rhsAttr).getValue();
@@ -3535,7 +3535,9 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
     }
     }
 
-    // Vector comparison results are 0 (false) or -1 / all-ones (true).
+    // A true result is all bits set (-1 in two's complement), and a false
+    // result is all bits clear. For a 1-bit element type these are the same
+    // bit pattern as 1 and 0, respectively.
     elements[i] =
         cir::IntAttr::get(getType().getElementType(), cmpResult ? -1LL : 0LL);
   }
diff --git a/clang/test/CIR/Transforms/vector-cmp-fold.cir 
b/clang/test/CIR/Transforms/vector-cmp-fold.cir
index 4d7c81f81cccb..9198db396c1e8 100644
--- a/clang/test/CIR/Transforms/vector-cmp-fold.cir
+++ b/clang/test/CIR/Transforms/vector-cmp-fold.cir
@@ -268,3 +268,27 @@ module  {
   // CHECK-SAME: #cir.int<-1> : !s8i, #cir.int<-1> : !s8i]> : !cir.vector<4 x 
!s8i>
   // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !s8i>
 }
+
+// -----
+
+// Test folding when the result element type is a 1-bit signed integer. The
+// all-ones (true) bit pattern is printed as -1 and all-zeros (false) as 0,
+// since -1 and 1 share the same bit pattern at width 1.
+
+!s32i = !cir.int<s, 32>
+!s1i = !cir.int<s, 1>
+
+module  {
+  cir.func @fold_cmp_vector_op_test_i1_result() -> !cir.vector<4 x !s1i> {
+    %vec_1 = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<3> : 
!s32i, #cir.int<5> : !s32i, #cir.int<7> : !s32i]> : !cir.vector<4 x !s32i>
+    %vec_2 = cir.const #cir.const_vector<[#cir.int<2> : !s32i, #cir.int<4> : 
!s32i, #cir.int<6> : !s32i, #cir.int<8> : !s32i]> : !cir.vector<4 x !s32i>
+    %new_vec = cir.vec.cmp(lt, %vec_1, %vec_2) : !cir.vector<4 x !s32i>, 
!cir.vector<4 x !s1i>
+    cir.return %new_vec : !cir.vector<4 x !s1i>
+  }
+
+  // 1<2, 3<4, 5<6, 7<8 are all true -> [-1, -1, -1, -1]
+  // CHECK:  cir.func{{.*}} @fold_cmp_vector_op_test_i1_result() -> 
!cir.vector<4 x !cir.int<s, 1>> {
+  // CHECK-NEXT: %[[RES:.*]] = cir.const #cir.const_vector<[#cir.int<-1> : 
!cir.int<s, 1>, #cir.int<-1> : !cir.int<s, 1>,
+  // CHECK-SAME: #cir.int<-1> : !cir.int<s, 1>, #cir.int<-1> : !cir.int<s, 
1>]> : !cir.vector<4 x !cir.int<s, 1>>
+  // CHECK-NEXT: cir.return %[[RES]] : !cir.vector<4 x !cir.int<s, 1>>
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to