From 72446746e0867e63b4e12f675ff1d6dbf570a28f Mon Sep 17 00:00:00 2001 From: Sirui Mu Date: Tue, 15 Oct 2024 23:44:42 +0800 Subject: [PATCH] [CIR] Add support for __int128 type This patch adds initial support for the __int128 type. The `!cir.int` type is extended to support 128-bit integer types. --- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 10 ++- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 4 + clang/lib/CIR/CodeGen/CIRGenTypeCache.h | 8 +- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 5 +- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 8 +- clang/test/CIR/CodeGen/int128.cpp | 74 +++++++++++++++++++ clang/test/CIR/IR/invalid.cir | 4 +- 7 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 clang/test/CIR/CodeGen/int128.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index 1c63fcd84c67..de4bf213dc87 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -38,9 +38,11 @@ def CIR_IntType : CIR_Type<"Int", "int", [DeclareTypeInterfaceMethods]> { 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; @@ -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. diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 7da61a261e21..955d6e4708d1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -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 = @@ -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()); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h index e07e46be68e5..1ba8095522bd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h +++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h @@ -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; diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 89793e6ea428..e4ab73c9b99f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -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) \ diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index c37fe2788020..e64c139f1844 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -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 {}; } @@ -643,7 +644,8 @@ IntType::verify(llvm::function_ref 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(); } diff --git a/clang/test/CIR/CodeGen/int128.cpp b/clang/test/CIR/CodeGen/int128.cpp new file mode 100644 index 000000000000..97539e4317c9 --- /dev/null +++ b/clang/test/CIR/CodeGen/int128.cpp @@ -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 +} diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index a28569ac0b46..3283b60726c4 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -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) -> () { + // expected-error@below {{expected integer width to be from 1 up to 128}} + cir.func @l0(%arg0: !cir.int) -> () { cir.return } }