This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGcc3affd8b020: [clang] [MSVC] Implement __mulh and __umulh builtins for aarch64 (authored by mstorsjo).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D106721/new/ https://reviews.llvm.org/D106721 Files: clang/include/clang/Basic/BuiltinsAArch64.def clang/lib/CodeGen/CGBuiltin.cpp clang/lib/Headers/intrin.h clang/test/CodeGen/arm64-microsoft-intrinsics.c Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c =================================================================== --- clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -81,6 +81,28 @@ // CHECK-MSVC: fence syncscope("singlethread") // CHECK-LINUX: error: implicit declaration of function '_ReadWriteBarrier' +long long check_mulh(long long a, long long b) { + return __mulh(a, b); +} + +// CHECK-MSVC: %[[ARG1:.*]] = sext i64 {{.*}} to i128 +// CHECK-MSVC: %[[ARG2:.*]] = sext i64 {{.*}} to i128 +// CHECK-MSVC: %[[PROD:.*]] = mul nsw i128 %[[ARG1]], %[[ARG2]] +// CHECK-MSVC: %[[HIGH:.*]] = ashr i128 %[[PROD]], 64 +// CHECK-MSVC: %[[RES:.*]] = trunc i128 %[[HIGH]] to i64 +// CHECK-LINUX: error: implicit declaration of function '__mulh' + +unsigned long long check_umulh(unsigned long long a, unsigned long long b) { + return __umulh(a, b); +} + +// CHECK-MSVC: %[[ARG1:.*]] = zext i64 {{.*}} to i128 +// CHECK-MSVC: %[[ARG2:.*]] = zext i64 {{.*}} to i128 +// CHECK-MSVC: %[[PROD:.*]] = mul nuw i128 %[[ARG1]], %[[ARG2]] +// CHECK-MSVC: %[[HIGH:.*]] = lshr i128 %[[PROD]], 64 +// CHECK-MSVC: %[[RES:.*]] = trunc i128 %[[HIGH]] to i64 +// CHECK-LINUX: error: implicit declaration of function '__umulh' + unsigned __int64 check__getReg() { unsigned volatile __int64 reg; reg = __getReg(18); Index: clang/lib/Headers/intrin.h =================================================================== --- clang/lib/Headers/intrin.h +++ clang/lib/Headers/intrin.h @@ -574,6 +574,9 @@ unsigned short __cdecl _byteswap_ushort(unsigned short val); unsigned long __cdecl _byteswap_ulong (unsigned long val); unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 val); + +__int64 __mulh(__int64 __a, __int64 __b); +unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b); #endif /*----------------------------------------------------------------------------*\ Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -9712,6 +9712,29 @@ return Builder.CreateCall(F); } + if (BuiltinID == AArch64::BI__mulh || BuiltinID == AArch64::BI__umulh) { + llvm::Type *ResType = ConvertType(E->getType()); + llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128); + + bool IsSigned = BuiltinID == AArch64::BI__mulh; + Value *LHS = + Builder.CreateIntCast(EmitScalarExpr(E->getArg(0)), Int128Ty, IsSigned); + Value *RHS = + Builder.CreateIntCast(EmitScalarExpr(E->getArg(1)), Int128Ty, IsSigned); + + Value *MulResult, *HigherBits; + if (IsSigned) { + MulResult = Builder.CreateNSWMul(LHS, RHS); + HigherBits = Builder.CreateAShr(MulResult, 64); + } else { + MulResult = Builder.CreateNUWMul(LHS, RHS); + HigherBits = Builder.CreateLShr(MulResult, 64); + } + HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned); + + return HigherBits; + } + // Handle MSVC intrinsics before argument evaluation to prevent double // evaluation. if (Optional<MSVCIntrin> MsvcIntId = translateAarch64ToMsvcIntrin(BuiltinID)) Index: clang/include/clang/Basic/BuiltinsAArch64.def =================================================================== --- clang/include/clang/Basic/BuiltinsAArch64.def +++ clang/include/clang/Basic/BuiltinsAArch64.def @@ -243,6 +243,9 @@ TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") + #undef BUILTIN #undef LANGBUILTIN #undef TARGET_HEADER_BUILTIN
Index: clang/test/CodeGen/arm64-microsoft-intrinsics.c =================================================================== --- clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -81,6 +81,28 @@ // CHECK-MSVC: fence syncscope("singlethread") // CHECK-LINUX: error: implicit declaration of function '_ReadWriteBarrier' +long long check_mulh(long long a, long long b) { + return __mulh(a, b); +} + +// CHECK-MSVC: %[[ARG1:.*]] = sext i64 {{.*}} to i128 +// CHECK-MSVC: %[[ARG2:.*]] = sext i64 {{.*}} to i128 +// CHECK-MSVC: %[[PROD:.*]] = mul nsw i128 %[[ARG1]], %[[ARG2]] +// CHECK-MSVC: %[[HIGH:.*]] = ashr i128 %[[PROD]], 64 +// CHECK-MSVC: %[[RES:.*]] = trunc i128 %[[HIGH]] to i64 +// CHECK-LINUX: error: implicit declaration of function '__mulh' + +unsigned long long check_umulh(unsigned long long a, unsigned long long b) { + return __umulh(a, b); +} + +// CHECK-MSVC: %[[ARG1:.*]] = zext i64 {{.*}} to i128 +// CHECK-MSVC: %[[ARG2:.*]] = zext i64 {{.*}} to i128 +// CHECK-MSVC: %[[PROD:.*]] = mul nuw i128 %[[ARG1]], %[[ARG2]] +// CHECK-MSVC: %[[HIGH:.*]] = lshr i128 %[[PROD]], 64 +// CHECK-MSVC: %[[RES:.*]] = trunc i128 %[[HIGH]] to i64 +// CHECK-LINUX: error: implicit declaration of function '__umulh' + unsigned __int64 check__getReg() { unsigned volatile __int64 reg; reg = __getReg(18); Index: clang/lib/Headers/intrin.h =================================================================== --- clang/lib/Headers/intrin.h +++ clang/lib/Headers/intrin.h @@ -574,6 +574,9 @@ unsigned short __cdecl _byteswap_ushort(unsigned short val); unsigned long __cdecl _byteswap_ulong (unsigned long val); unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 val); + +__int64 __mulh(__int64 __a, __int64 __b); +unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b); #endif /*----------------------------------------------------------------------------*\ Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -9712,6 +9712,29 @@ return Builder.CreateCall(F); } + if (BuiltinID == AArch64::BI__mulh || BuiltinID == AArch64::BI__umulh) { + llvm::Type *ResType = ConvertType(E->getType()); + llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128); + + bool IsSigned = BuiltinID == AArch64::BI__mulh; + Value *LHS = + Builder.CreateIntCast(EmitScalarExpr(E->getArg(0)), Int128Ty, IsSigned); + Value *RHS = + Builder.CreateIntCast(EmitScalarExpr(E->getArg(1)), Int128Ty, IsSigned); + + Value *MulResult, *HigherBits; + if (IsSigned) { + MulResult = Builder.CreateNSWMul(LHS, RHS); + HigherBits = Builder.CreateAShr(MulResult, 64); + } else { + MulResult = Builder.CreateNUWMul(LHS, RHS); + HigherBits = Builder.CreateLShr(MulResult, 64); + } + HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned); + + return HigherBits; + } + // Handle MSVC intrinsics before argument evaluation to prevent double // evaluation. if (Optional<MSVCIntrin> MsvcIntId = translateAarch64ToMsvcIntrin(BuiltinID)) Index: clang/include/clang/Basic/BuiltinsAArch64.def =================================================================== --- clang/include/clang/Basic/BuiltinsAArch64.def +++ clang/include/clang/Basic/BuiltinsAArch64.def @@ -243,6 +243,9 @@ TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") + #undef BUILTIN #undef LANGBUILTIN #undef TARGET_HEADER_BUILTIN
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits