llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: None (adams381)

<details>
<summary>Changes</summary>

Add an optional `bitint` parameter to `cir::IntType` so CIR can distinguish 
`_BitInt(N)` from builtin integer types like `__int128`.  Both lower to the 
same LLVM integer type, but they have different ABI rules (alignment, passing 
convention) on x86_64.

The flag is set during CIRGen for `Type::BitInt`, printed/parsed as 
`!cir.int&lt;s, 128, bitint&gt;`, and excluded from `isFundamental()`.  
Existing 2-arg `IntType::get()` calls continue to work via a default parameter.


---
Full diff: https://github.com/llvm/llvm-project/pull/188113.diff


7 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/IR/CIRTypes.td (+16-3) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+2-1) 
- (modified) clang/lib/CIR/Dialect/IR/CIRTypes.cpp (+16-3) 
- (added) clang/test/CIR/CodeGen/bitint.c (+32) 
- (modified) clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp (+15-15) 
- (added) clang/test/CIR/IR/bitint.cir (+20) 
- (modified) clang/test/CIR/global-var-simple.cpp (+2-2) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 450c02135e033..f14d6099304ce 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -50,21 +50,34 @@ def CIR_IntType : CIR_Type<"Int", "int", [
     fundamental integer types. Said types are: `signed char`, `short`, `int`,
     `long`, `long long`, and their unsigned variations.
   }];
-  let parameters = (ins "unsigned":$width, "bool":$isSigned);
+  let parameters = (ins "unsigned":$width, "bool":$isSigned,
+                        DefaultValuedParameter<"bool", "false">:$bitInt);
+  let builders = [
+    TypeBuilder<(ins "unsigned":$width, "bool":$isSigned), [{
+      return $_get($_ctxt, width, isSigned, /*bitInt=*/false);
+    }]>,
+  ];
   let hasCustomAssemblyFormat = 1;
   let extraClassDeclaration = [{
     /// Return true if this is a signed integer type.
     bool isSigned() const { return getIsSigned(); }
     /// Return true if this is an unsigned integer type.
     bool isUnsigned() const { return !getIsSigned(); }
+    /// Return true if this is a _BitInt type.
+    bool isBitInt() const { return getBitInt(); }
     /// Return type alias.
     std::string getAlias() const {
-      return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i';
+      std::string alias =
+          (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i';
+      if (isBitInt())
+        alias += "_bitint";
+      return alias;
     }
     /// Return true if this is a fundamental integer type (i.e. signed or
     /// unsigned integer types whose bit width is 8, 16, 32, or 64).
+    /// _BitInt types are never fundamental even if their width matches.
     bool isFundamental() const {
-      return isFundamentalIntType(*this);
+      return !isBitInt() && isFundamentalIntType(*this);
     }
     bool isSignedFundamental() const {
       return isFundamentalSIntType(*this);
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 2092964bac065..c86ddbb44a501 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -564,7 +564,8 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
       resultType = cgm.sInt32Ty;
     } else {
       resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
-                                     bitIntTy->isSigned());
+                                     bitIntTy->isSigned(),
+                                     /*bitInt=*/true);
     }
     break;
   }
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index d96975b3e6aa7..1da59b7815ab5 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -499,15 +499,28 @@ Type IntType::parse(mlir::AsmParser &parser) {
     return {};
   }
 
+  bool bitInt = false;
+  if (succeeded(parser.parseOptionalComma())) {
+    llvm::StringRef kw;
+    if (parser.parseKeyword(&kw) || kw != "bitint") {
+      parser.emitError(loc, "expected 'bitint'");
+      return {};
+    }
+    bitInt = true;
+  }
+
   if (parser.parseGreater())
     return {};
 
-  return IntType::get(context, width, isSigned);
+  return IntType::get(context, width, isSigned, bitInt);
 }
 
 void IntType::print(mlir::AsmPrinter &printer) const {
   char sign = isSigned() ? 's' : 'u';
-  printer << '<' << sign << ", " << getWidth() << '>';
+  printer << '<' << sign << ", " << getWidth();
+  if (isBitInt())
+    printer << ", bitint";
+  printer << '>';
 }
 
 llvm::TypeSize
@@ -523,7 +536,7 @@ uint64_t IntType::getABIAlignment(const mlir::DataLayout 
&dataLayout,
 
 mlir::LogicalResult
 IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
-                unsigned width, bool isSigned) {
+                unsigned width, bool isSigned, bool bitInt) {
   if (width < IntType::minBitwidth() || width > IntType::maxBitwidth())
     return emitError() << "IntType only supports widths from "
                        << IntType::minBitwidth() << " up to "
diff --git a/clang/test/CIR/CodeGen/bitint.c b/clang/test/CIR/CodeGen/bitint.c
new file mode 100644
index 0000000000000..1f02c6f3eaaba
--- /dev/null
+++ b/clang/test/CIR/CodeGen/bitint.c
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+// _BitInt types are distinguished from regular integer types via the
+// "bitint" keyword in CIR.  Verify that the type alias includes "_bitint"
+// and that regular __int128 does not.
+
+// CIR-DAG: !s32i_bitint = !cir.int<s, 32, bitint>
+// CIR-DAG: !s128i_bitint = !cir.int<s, 128, bitint>
+// CIR-DAG: !u64i_bitint = !cir.int<u, 64, bitint>
+// CIR-DAG: !s128i = !cir.int<s, 128>
+
+void take_bitint_32(_BitInt(32) x) {}
+// LLVM: define {{.*}} void @take_bitint_32(i32 {{.*}})
+// OGCG: define {{.*}} void @take_bitint_32(i32 {{.*}})
+
+void take_bitint_128(signed _BitInt(128) x) {}
+// LLVM: define {{.*}} void @take_bitint_128(i128 {{.*}})
+// OGCG: define {{.*}} void @take_bitint_128(i128 {{.*}})
+
+void take_unsigned_bitint(unsigned _BitInt(64) x) {}
+// LLVM: define {{.*}} void @take_unsigned_bitint(i64 {{.*}})
+// OGCG: define {{.*}} void @take_unsigned_bitint(i64 {{.*}})
+
+// Regular __int128 should NOT have the bitint flag.
+void take_int128(__int128 x) {}
+// LLVM: define {{.*}} void @take_int128(i128 {{.*}})
+// OGCG: define {{.*}} void @take_int128(i128 {{.*}})
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp
index 1c674ff5a297a..8089a538d733b 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-overflow.cpp
@@ -40,11 +40,11 @@ bool test_add_overflow_xint31_xint31_xint31(_BitInt(31) x, 
_BitInt(31) y, _BitIn
 }
 
 //      CIR: cir.func {{.*}} 
@_Z38test_add_overflow_xint31_xint31_xint31DB31_S_PS_
-//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>>
-// CIR-NEXT:   %[[RES:.+]], %{{.+}} = cir.add.overflow %[[#LHS]], %[[#RHS]] : 
!cir.int<s, 31> -> !cir.int<s, 31>
-// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, 
!cir.ptr<!cir.int<s, 31>>
+//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>>
+//      CIR:   %[[RES:.+]], %{{.+}} = cir.add.overflow %{{.+}}, %{{.+}} : 
!cir.int<s, 31> -> !cir.int<s, 31, bitint>
+// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, 
bitint>, !cir.ptr<!cir.int<s, 31, bitint>>
 //      CIR: }
 
 bool test_sub_overflow_uint_uint_uint(unsigned x, unsigned y, unsigned *res) {
@@ -76,11 +76,11 @@ bool test_sub_overflow_xint31_xint31_xint31(_BitInt(31) x, 
_BitInt(31) y, _BitIn
 }
 
 //      CIR: cir.func {{.*}} 
@_Z38test_sub_overflow_xint31_xint31_xint31DB31_S_PS_
-//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>>
-// CIR-NEXT:   %[[RES:.+]], %{{.+}} = cir.sub.overflow %[[#LHS]], %[[#RHS]] : 
!cir.int<s, 31> -> !cir.int<s, 31>
-// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, 
!cir.ptr<!cir.int<s, 31>>
+//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>>
+//      CIR:   %[[RES:.+]], %{{.+}} = cir.sub.overflow %{{.+}}, %{{.+}} : 
!cir.int<s, 31> -> !cir.int<s, 31, bitint>
+// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, 
bitint>, !cir.ptr<!cir.int<s, 31, bitint>>
 //      CIR: }
 
 bool test_mul_overflow_uint_uint_uint(unsigned x, unsigned y, unsigned *res) {
@@ -112,11 +112,11 @@ bool test_mul_overflow_xint31_xint31_xint31(_BitInt(31) 
x, _BitInt(31) y, _BitIn
 }
 
 //      CIR: cir.func {{.*}} 
@_Z38test_mul_overflow_xint31_xint31_xint31DB31_S_PS_
-//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 
31>>, !cir.int<s, 31>
-// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31>>>, !cir.ptr<!cir.int<s, 31>>
-// CIR-NEXT:   %[[RES:.+]], %{{.+}} = cir.mul.overflow %[[#LHS]], %[[#RHS]] : 
!cir.int<s, 31> -> !cir.int<s, 31>
-// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31>, 
!cir.ptr<!cir.int<s, 31>>
+//      CIR:   %[[#LHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RHS:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.int<s, 31, 
bitint>>, !cir.int<s, 31, bitint>
+// CIR-NEXT:   %[[#RES_PTR:]] = cir.load{{.*}} %{{.+}} : 
!cir.ptr<!cir.ptr<!cir.int<s, 31, bitint>>>, !cir.ptr<!cir.int<s, 31, bitint>>
+//      CIR:   %[[RES:.+]], %{{.+}} = cir.mul.overflow %{{.+}}, %{{.+}} : 
!cir.int<s, 31> -> !cir.int<s, 31, bitint>
+// CIR-NEXT:   cir.store{{.*}} %[[RES]], %[[#RES_PTR]] : !cir.int<s, 31, 
bitint>, !cir.ptr<!cir.int<s, 31, bitint>>
 //      CIR: }
 
 bool test_mul_overflow_ulong_ulong_long(unsigned long x, unsigned long y, 
unsigned long *res) {
diff --git a/clang/test/CIR/IR/bitint.cir b/clang/test/CIR/IR/bitint.cir
new file mode 100644
index 0000000000000..5dddddc833777
--- /dev/null
+++ b/clang/test/CIR/IR/bitint.cir
@@ -0,0 +1,20 @@
+// RUN: cir-opt %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+!s32i = !cir.int<s, 32>
+!s32i_bitint = !cir.int<s, 32, bitint>
+!u64i_bitint = !cir.int<u, 64, bitint>
+!s128i_bitint = !cir.int<s, 128, bitint>
+
+module {
+  // CHECK: cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: 
!u64i_bitint, %arg2: !s128i_bitint)
+  cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: 
!s128i_bitint) {
+    cir.return
+  }
+
+  // Regular int should NOT print bitint.
+  // CHECK: cir.func @round_trip_regular(%arg0: !s32i)
+  cir.func @round_trip_regular(%arg0: !s32i) {
+    cir.return
+  }
+}
diff --git a/clang/test/CIR/global-var-simple.cpp 
b/clang/test/CIR/global-var-simple.cpp
index 4608089058fb4..68e44c926110c 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -53,10 +53,10 @@ char32_t c32;
 // CHECK: cir.global external @c32 = #cir.int<0> : !u32i
 
 _BitInt(20) sb20;
-// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20>
+// CHECK: cir.global external @sb20 = #cir.int<0> : !cir.int<s, 20, bitint>
 
 unsigned _BitInt(48) ub48;
-// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48>
+// CHECK: cir.global external @ub48 = #cir.int<0> : !cir.int<u, 48, bitint>
 
 bool boolfalse = false;
 // CHECK: cir.global external @boolfalse = #false

``````````

</details>


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

Reply via email to