[clang] [CIR] Accept _BitInt up to 128 bits in x86_64 callconv lowering (PR #212668)
Adam Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 30 11:48:19 PDT 2026
================
@@ -0,0 +1,230 @@
+// RUN: cir-opt %s -cir-call-conv-lowering=target=x86_64 | FileCheck %s
+// RUN: cir-opt %s -cir-call-conv-lowering=target=x86_64 -cir-to-llvm -o - 2>/dev/null \
+// RUN: | mlir-translate -mlir-to-llvmir --allow-unregistered-dialect \
+// RUN: | FileCheck %s --check-prefix=LLVM
+
+!b17i = !cir.int<s, 17, bitint>
+!ub17i = !cir.int<u, 17, bitint>
+!b32i = !cir.int<s, 32, bitint>
+!b33i = !cir.int<s, 33, bitint>
+!ub33i = !cir.int<u, 33, bitint>
+!b40i = !cir.int<s, 40, bitint>
+!b63i = !cir.int<s, 63, bitint>
+!b64i = !cir.int<s, 64, bitint>
+!b65i = !cir.int<s, 65, bitint>
+!ub65i = !cir.int<u, 65, bitint>
+!b127i = !cir.int<s, 127, bitint>
+!b128i = !cir.int<s, 128, bitint>
+!s8i = !cir.int<s, 8>
+!rec_S = !cir.struct<"S" {!b17i}>
+!rec_P = !cir.struct<"P" {!b65i}>
+!rec_W = !cir.struct<"W" {!b128i}>
+!rec_O = !cir.struct<"O" {!b128i, !s8i}>
+!rec_Arr = !cir.struct<"Arr" {!cir.array<!b65i x 2>}>
+
+module attributes {
+ dlti.dl_spec = #dlti.dl_spec<
+ #dlti.dl_entry<i8, dense<8>: vector<2xi64>>,
+ #dlti.dl_entry<i16, dense<16>: vector<2xi64>>,
+ #dlti.dl_entry<i32, dense<32>: vector<2xi64>>,
+ #dlti.dl_entry<i64, dense<64>: vector<2xi64>>,
+ #dlti.dl_entry<i128, dense<128>: vector<2xi64>>>
+} {
+
+ // Sub-register signed _BitInt: Extend, one argument with signext.
+ cir.func @ret_b17(%arg0: !b17i) -> !b17i {
+ cir.return %arg0 : !b17i
+ }
+
+ // CHECK: cir.func{{.*}} @ret_b17(%arg0: !cir.int<s, 17, bitint> {llvm.signext}) -> (!cir.int<s, 17, bitint> {llvm.signext})
+
+ // Unsigned sub-register _BitInt: zeroext instead.
+ cir.func @ret_ub17(%arg0: !ub17i) -> !ub17i {
+ cir.return %arg0 : !ub17i
+ }
+
+ // CHECK: cir.func{{.*}} @ret_ub17(%arg0: !cir.int<u, 17, bitint> {llvm.zeroext}) -> (!cir.int<u, 17, bitint> {llvm.zeroext})
+
+ // Too wide to extend, and already the width the classifier names: unchanged.
+ cir.func @ret_b32(%arg0: !b32i) -> !b32i {
+ cir.return %arg0 : !b32i
+ }
+
+ // CHECK: cir.func{{.*}} @ret_b32(%arg0: !s32i_bitint) -> !s32i_bitint
+ // CHECK-NEXT: cir.return %arg0 : !s32i_bitint
+
+ // One bit wider is still one eightbyte, but the classifier names i64, so the
+ // value travels in that width and the narrower one is recovered from memory.
+ cir.func @ret_b33(%arg0: !b33i) -> !b33i {
+ cir.return %arg0 : !b33i
+ }
+
+ // CHECK: cir.func{{.*}} @ret_b33(%arg0: !u64i) -> !u64i
+ // CHECK: cir.cast bitcast %{{.*}} : !cir.ptr<!u64i> -> !cir.ptr<!cir.int<s, 33, bitint>>
+
+ // Signedness does not change the eightbyte it travels in.
+ cir.func @ret_ub33(%arg0: !ub33i) -> !ub33i {
+ cir.return %arg0 : !ub33i
+ }
+
+ // CHECK: cir.func{{.*}} @ret_ub33(%arg0: !u64i) -> !u64i
----------------
adams381 wrote:
Same rewrite. `ret_ub33` is only here to show signedness picking the extension, and the one check I had was on the signature, which apart from the name is identical to `ret_b33`'s. So the one thing the function exists to test was the one thing not being checked.
Both blocks walk the same sequence now, and after the rewrite `zext` is the only line where the lowered bodies differ:
```llvm
// LLVM-NEXT: %[[EXT:[0-9]+]] = zext i33 %[[NARROW]] to i64
```
https://github.com/llvm/llvm-project/pull/212668
More information about the cfe-commits
mailing list