Skip to content

Commit f70c0d1

Browse files
authored
[CIR] Add support for __int128 type (#980)
This PR adds initial support for the `__int128` type. The `!cir.int` type is extended to support 128-bit integer types. This PR comes with a simple test that verifies the CIRGen and LLVM lowering of `!s128i` and `!u128i` work. Resolve #953 .
1 parent e505aae commit f70c0d1

File tree

7 files changed

+98
-15
lines changed

7 files changed

+98
-15
lines changed

clang/include/clang/CIR/Dialect/IR/CIRTypes.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ def CIR_IntType : CIR_Type<"Int", "int",
3838
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
3939
let summary = "Integer type with arbitrary precision up to a fixed limit";
4040
let description = [{
41-
CIR type that represents C/C++ primitive integer types.
42-
Said types are: `char`, `short`, `int`, `long`, `long long`, and their \
43-
unsigned variations.
41+
CIR type that represents integer types with arbitrary precision.
42+
43+
Those integer types that are directly available in C/C++ standard are called
44+
primitive integer types. Said types are: `signed char`, `short`, `int`,
45+
`long`, `long long`, and their unsigned variations.
4446
}];
4547
let parameters = (ins "unsigned":$width, "bool":$isSigned);
4648
let hasCustomAssemblyFormat = 1;
@@ -62,7 +64,7 @@ def CIR_IntType : CIR_Type<"Int", "int",
6264
/// Returns a minimum bitwidth of cir::IntType
6365
static unsigned minBitwidth() { return 1; }
6466
/// Returns a maximum bitwidth of cir::IntType
65-
static unsigned maxBitwidth() { return 64; }
67+
static unsigned maxBitwidth() { return 128; }
6668

6769
/// Returns true if cir::IntType that represents a primitive integer type
6870
/// can be constructed from the provided bitwidth.

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
120120
::mlir::cir::IntType::get(builder.getContext(), 32, /*isSigned=*/true);
121121
SInt64Ty =
122122
::mlir::cir::IntType::get(builder.getContext(), 64, /*isSigned=*/true);
123+
SInt128Ty =
124+
::mlir::cir::IntType::get(builder.getContext(), 128, /*isSigned=*/true);
123125

124126
// Initialize CIR unsigned integer types cache.
125127
UInt8Ty =
@@ -130,6 +132,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
130132
::mlir::cir::IntType::get(builder.getContext(), 32, /*isSigned=*/false);
131133
UInt64Ty =
132134
::mlir::cir::IntType::get(builder.getContext(), 64, /*isSigned=*/false);
135+
UInt128Ty =
136+
::mlir::cir::IntType::get(builder.getContext(), 128, /*isSigned=*/false);
133137

134138
VoidTy = ::mlir::cir::VoidType::get(builder.getContext());
135139

clang/lib/CIR/CodeGen/CIRGenTypeCache.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ struct CIRGenTypeCache {
3131

3232
/// void
3333
mlir::cir::VoidType VoidTy;
34-
// char, int, short, long
35-
mlir::cir::IntType SInt8Ty, SInt16Ty, SInt32Ty, SInt64Ty;
36-
// usigned char, unsigned, unsigned short, unsigned long
37-
mlir::cir::IntType UInt8Ty, UInt16Ty, UInt32Ty, UInt64Ty;
34+
// char, int, short, long, __int128
35+
mlir::cir::IntType SInt8Ty, SInt16Ty, SInt32Ty, SInt64Ty, SInt128Ty;
36+
// usigned char, unsigned, unsigned short, unsigned long, unsigned __int128
37+
mlir::cir::IntType UInt8Ty, UInt16Ty, UInt32Ty, UInt64Ty, UInt128Ty;
3838
/// half, bfloat, float, double, fp80
3939
mlir::cir::FP16Type FP16Ty;
4040
mlir::cir::BF16Type BFloat16Ty;

clang/lib/CIR/CodeGen/CIRGenTypes.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,9 +503,10 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) {
503503
break;
504504

505505
case BuiltinType::UInt128:
506+
ResultType = CGM.UInt128Ty;
507+
break;
506508
case BuiltinType::Int128:
507-
assert(0 && "not implemented");
508-
// FIXME: ResultType = Builder.getIntegerType(128);
509+
ResultType = CGM.SInt128Ty;
509510
break;
510511

511512
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \

clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,8 +604,9 @@ Type IntType::parse(mlir::AsmParser &parser) {
604604
// Fetch integer size.
605605
if (parser.parseInteger(width))
606606
return {};
607-
if (width < 1 || width > 64) {
608-
parser.emitError(loc, "expected integer width to be from 1 up to 64");
607+
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
608+
parser.emitError(loc, "expected integer width to be from ")
609+
<< IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
609610
return {};
610611
}
611612

@@ -643,7 +644,8 @@ IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
643644

644645
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
645646
emitError() << "IntType only supports widths from "
646-
<< IntType::minBitwidth() << "up to " << IntType::maxBitwidth();
647+
<< IntType::minBitwidth() << " up to "
648+
<< IntType::maxBitwidth();
647649
return mlir::failure();
648650
}
649651

clang/test/CIR/CodeGen/int128.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll
4+
// RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s
5+
6+
// TODO: remove the -fno-clangir-call-conv-lowering flag when ABI lowering for
7+
// int128 is supported.
8+
9+
// CHECK-LABEL: @_Z5test1n
10+
// LLVM-LABEL: @_Z5test1n
11+
__int128 test1(__int128 x) {
12+
return x;
13+
// CHECK: cir.return %{{.+}} : !s128i
14+
// LLVM: ret i128 %{{.+}}
15+
}
16+
17+
// CHECK-LABEL: @_Z5test2o
18+
// LLVM-LABEL: @_Z5test2o
19+
unsigned __int128 test2(unsigned __int128 x) {
20+
return x;
21+
// CHECK: cir.return %{{.+}} : !u128i
22+
// LLVM: ret i128 %{{.+}}
23+
}
24+
25+
// CHECK-LABEL: @_Z11unary_arithn
26+
// LLVM-LABEL: @_Z11unary_arithn
27+
__int128 unary_arith(__int128 x) {
28+
return ++x;
29+
// CHECK: %{{.+}} = cir.unary(inc, %{{.+}}) : !s128i, !s128i
30+
// LLVM: %{{.+}} = add i128 %{{.+}}, 1
31+
}
32+
33+
// CHECK-LABEL: @_Z12binary_arithnn
34+
// LLVM-LABEL: @_Z12binary_arithnn
35+
__int128 binary_arith(__int128 x, __int128 y) {
36+
return x + y;
37+
// CHECK: %{{.+}} = cir.binop(add, %{{.+}}, %{{.+}}) nsw : !s128i
38+
// LLVM: %{{.+}} = add nsw i128 %{{.+}}, %{{.+}}
39+
}
40+
41+
volatile int int_var;
42+
volatile double double_var;
43+
44+
// CHECK-LABEL: @_Z19integral_conversionn
45+
// LLVM-LABEL: @_Z19integral_conversionn
46+
__int128 integral_conversion(__int128 x) {
47+
int_var = x;
48+
// CHECK: %[[#VAL:]] = cir.cast(integral, %{{.+}} : !s128i), !s32i
49+
// LLVM: %{{.+}} = trunc i128 %{{.+}} to i32
50+
51+
return int_var;
52+
// CHECK: %{{.+}} = cir.cast(integral, %{{.+}} : !s32i), !s128i
53+
// LLVM: %{{.+}} = sext i32 %{{.+}} to i128
54+
}
55+
56+
// CHECK-LABEL: @_Z16float_conversionn
57+
// LLVM-LABEL: @_Z16float_conversionn
58+
__int128 float_conversion(__int128 x) {
59+
double_var = x;
60+
// CHECK: %[[#VAL:]] = cir.cast(int_to_float, %{{.+}} : !s128i), !cir.double
61+
// LLVM: %{{.+}} = sitofp i128 %{{.+}} to double
62+
63+
return double_var;
64+
// CHECK: %{{.+}} = cir.cast(float_to_int, %{{.+}} : !cir.double), !s128i
65+
// LLVM: %{{.+}} = fptosi double %{{.+}} to i128
66+
}
67+
68+
// CHECK-LABEL: @_Z18boolean_conversionn
69+
// LLVM-LABEL: @_Z18boolean_conversionn
70+
bool boolean_conversion(__int128 x) {
71+
return x;
72+
// CHECK: %{{.+}} = cir.cast(int_to_bool, %{{.+}} : !s128i), !cir.bool
73+
// LLVM: %{{.+}} = icmp ne i128 %{{.+}}, 0
74+
}

clang/test/CIR/IR/invalid.cir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ module {
593593
// // -----
594594

595595
module {
596-
// expected-error@below {{expected integer width to be from 1 up to 64}}
597-
cir.func @l0(%arg0: !cir.int<s, 128>) -> () {
596+
// expected-error@below {{expected integer width to be from 1 up to 128}}
597+
cir.func @l0(%arg0: !cir.int<s, 256>) -> () {
598598
cir.return
599599
}
600600
}

0 commit comments

Comments
 (0)