Skip to content

Commit

Permalink
[CIR] Add support for __int128 type (llvm#980)
Browse files Browse the repository at this point in the history
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 llvm#953 .
  • Loading branch information
Lancern authored and lanza committed Oct 19, 2024
1 parent 478deb6 commit 31fd4b7
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 15 deletions.
10 changes: 6 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ def CIR_IntType : CIR_Type<"Int", "int",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
let summary = "Integer type with arbitrary precision up to a fixed limit";
let description = [{
CIR type that represents C/C++ primitive integer types.
Said types are: `char`, `short`, `int`, `long`, `long long`, and their \
unsigned variations.
CIR type that represents integer types with arbitrary precision.

Those integer types that are directly available in C/C++ standard are called
primitive integer types. Said types are: `signed char`, `short`, `int`,
`long`, `long long`, and their unsigned variations.
}];
let parameters = (ins "unsigned":$width, "bool":$isSigned);
let hasCustomAssemblyFormat = 1;
Expand All @@ -62,7 +64,7 @@ def CIR_IntType : CIR_Type<"Int", "int",
/// Returns a minimum bitwidth of cir::IntType
static unsigned minBitwidth() { return 1; }
/// Returns a maximum bitwidth of cir::IntType
static unsigned maxBitwidth() { return 64; }
static unsigned maxBitwidth() { return 128; }

/// Returns true if cir::IntType that represents a primitive integer type
/// can be constructed from the provided bitwidth.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
::mlir::cir::IntType::get(builder.getContext(), 32, /*isSigned=*/true);
SInt64Ty =
::mlir::cir::IntType::get(builder.getContext(), 64, /*isSigned=*/true);
SInt128Ty =
::mlir::cir::IntType::get(builder.getContext(), 128, /*isSigned=*/true);

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

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

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenTypeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ struct CIRGenTypeCache {

/// void
mlir::cir::VoidType VoidTy;
// char, int, short, long
mlir::cir::IntType SInt8Ty, SInt16Ty, SInt32Ty, SInt64Ty;
// usigned char, unsigned, unsigned short, unsigned long
mlir::cir::IntType UInt8Ty, UInt16Ty, UInt32Ty, UInt64Ty;
// char, int, short, long, __int128
mlir::cir::IntType SInt8Ty, SInt16Ty, SInt32Ty, SInt64Ty, SInt128Ty;
// usigned char, unsigned, unsigned short, unsigned long, unsigned __int128
mlir::cir::IntType UInt8Ty, UInt16Ty, UInt32Ty, UInt64Ty, UInt128Ty;
/// half, bfloat, float, double, fp80
mlir::cir::FP16Type FP16Ty;
mlir::cir::BF16Type BFloat16Ty;
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,9 +503,10 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) {
break;

case BuiltinType::UInt128:
ResultType = CGM.UInt128Ty;
break;
case BuiltinType::Int128:
assert(0 && "not implemented");
// FIXME: ResultType = Builder.getIntegerType(128);
ResultType = CGM.SInt128Ty;
break;

#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
Expand Down
8 changes: 5 additions & 3 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,9 @@ Type IntType::parse(mlir::AsmParser &parser) {
// Fetch integer size.
if (parser.parseInteger(width))
return {};
if (width < 1 || width > 64) {
parser.emitError(loc, "expected integer width to be from 1 up to 64");
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
parser.emitError(loc, "expected integer width to be from ")
<< IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
return {};
}

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

if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
emitError() << "IntType only supports widths from "
<< IntType::minBitwidth() << "up to " << IntType::maxBitwidth();
<< IntType::minBitwidth() << " up to "
<< IntType::maxBitwidth();
return mlir::failure();
}

Expand Down
74 changes: 74 additions & 0 deletions clang/test/CIR/CodeGen/int128.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll --check-prefix=LLVM %s

// TODO: remove the -fno-clangir-call-conv-lowering flag when ABI lowering for
// int128 is supported.

// CHECK-LABEL: @_Z5test1n
// LLVM-LABEL: @_Z5test1n
__int128 test1(__int128 x) {
return x;
// CHECK: cir.return %{{.+}} : !s128i
// LLVM: ret i128 %{{.+}}
}

// CHECK-LABEL: @_Z5test2o
// LLVM-LABEL: @_Z5test2o
unsigned __int128 test2(unsigned __int128 x) {
return x;
// CHECK: cir.return %{{.+}} : !u128i
// LLVM: ret i128 %{{.+}}
}

// CHECK-LABEL: @_Z11unary_arithn
// LLVM-LABEL: @_Z11unary_arithn
__int128 unary_arith(__int128 x) {
return ++x;
// CHECK: %{{.+}} = cir.unary(inc, %{{.+}}) : !s128i, !s128i
// LLVM: %{{.+}} = add i128 %{{.+}}, 1
}

// CHECK-LABEL: @_Z12binary_arithnn
// LLVM-LABEL: @_Z12binary_arithnn
__int128 binary_arith(__int128 x, __int128 y) {
return x + y;
// CHECK: %{{.+}} = cir.binop(add, %{{.+}}, %{{.+}}) nsw : !s128i
// LLVM: %{{.+}} = add nsw i128 %{{.+}}, %{{.+}}
}

volatile int int_var;
volatile double double_var;

// CHECK-LABEL: @_Z19integral_conversionn
// LLVM-LABEL: @_Z19integral_conversionn
__int128 integral_conversion(__int128 x) {
int_var = x;
// CHECK: %[[#VAL:]] = cir.cast(integral, %{{.+}} : !s128i), !s32i
// LLVM: %{{.+}} = trunc i128 %{{.+}} to i32

return int_var;
// CHECK: %{{.+}} = cir.cast(integral, %{{.+}} : !s32i), !s128i
// LLVM: %{{.+}} = sext i32 %{{.+}} to i128
}

// CHECK-LABEL: @_Z16float_conversionn
// LLVM-LABEL: @_Z16float_conversionn
__int128 float_conversion(__int128 x) {
double_var = x;
// CHECK: %[[#VAL:]] = cir.cast(int_to_float, %{{.+}} : !s128i), !cir.double
// LLVM: %{{.+}} = sitofp i128 %{{.+}} to double

return double_var;
// CHECK: %{{.+}} = cir.cast(float_to_int, %{{.+}} : !cir.double), !s128i
// LLVM: %{{.+}} = fptosi double %{{.+}} to i128
}

// CHECK-LABEL: @_Z18boolean_conversionn
// LLVM-LABEL: @_Z18boolean_conversionn
bool boolean_conversion(__int128 x) {
return x;
// CHECK: %{{.+}} = cir.cast(int_to_bool, %{{.+}} : !s128i), !cir.bool
// LLVM: %{{.+}} = icmp ne i128 %{{.+}}, 0
}
4 changes: 2 additions & 2 deletions clang/test/CIR/IR/invalid.cir
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,8 @@ module {
// // -----

module {
// expected-error@below {{expected integer width to be from 1 up to 64}}
cir.func @l0(%arg0: !cir.int<s, 128>) -> () {
// expected-error@below {{expected integer width to be from 1 up to 128}}
cir.func @l0(%arg0: !cir.int<s, 256>) -> () {
cir.return
}
}
Expand Down

0 comments on commit 31fd4b7

Please sign in to comment.