r283785 - Implement __emul, __emulu, _mul128 and _umul128 MS intrinsics

Albert Gutowski via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 10 11:09:28 PDT 2016


Author: agutowski
Date: Mon Oct 10 13:09:27 2016
New Revision: 283785

URL: http://llvm.org/viewvc/llvm-project?rev=283785&view=rev
Log:
Implement __emul, __emulu, _mul128 and _umul128 MS intrinsics

Reviewers: rnk, thakis, majnemer, hans

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D25353

Added:
    cfe/trunk/test/CodeGen/ms-x86-intrinsics.c
Modified:
    cfe/trunk/include/clang/Basic/BuiltinsX86.def
    cfe/trunk/include/clang/Basic/BuiltinsX86_64.def
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/lib/Headers/intrin.h
    cfe/trunk/test/CodeGen/ms-intrinsics.c

Modified: cfe/trunk/include/clang/Basic/BuiltinsX86.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsX86.def?rev=283785&r1=283784&r2=283785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/BuiltinsX86.def (original)
+++ cfe/trunk/include/clang/Basic/BuiltinsX86.def Mon Oct 10 13:09:27 2016
@@ -2071,6 +2071,9 @@ TARGET_BUILTIN(__builtin_ia32_selectpd_5
 TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx")
 TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx")
 
+TARGET_HEADER_BUILTIN(__emul,  "LLiii",    "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
+
 #undef BUILTIN
 #undef TARGET_BUILTIN
 #undef TARGET_HEADER_BUILTIN

Modified: cfe/trunk/include/clang/Basic/BuiltinsX86_64.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/BuiltinsX86_64.def?rev=283785&r1=283784&r2=283785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/BuiltinsX86_64.def (original)
+++ cfe/trunk/include/clang/Basic/BuiltinsX86_64.def Mon Oct 10 13:09:27 2016
@@ -20,6 +20,8 @@
 
 TARGET_HEADER_BUILTIN(__mulh,  "LLiLLiLLi",    "nch", "intrin.h", ALL_MS_LANGUAGES, "")
 TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*",      "nh",   "intrin.h", ALL_MS_LANGUAGES, "")
+TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nh",   "intrin.h", ALL_MS_LANGUAGES, "")
 
 #undef BUILTIN
 #undef TARGET_HEADER_BUILTIN

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=283785&r1=283784&r2=283785&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Oct 10 13:09:27 2016
@@ -7576,16 +7576,24 @@ Value *CodeGenFunction::EmitX86BuiltinEx
   case X86::BI__builtin_ia32_cmpordsd:
     return getCmpIntrinsicCall(Intrinsic::x86_sse2_cmp_sd, 7);
 
+  case X86::BI__emul:
+  case X86::BI__emulu: {
+    llvm::Type *Int64Ty = llvm::IntegerType::get(getLLVMContext(), 64);
+    bool isSigned = (BuiltinID == X86::BI__emul);
+    Value *LHS = Builder.CreateIntCast(Ops[0], Int64Ty, isSigned);
+    Value *RHS = Builder.CreateIntCast(Ops[1], Int64Ty, isSigned);
+    return Builder.CreateMul(LHS, RHS, "", !isSigned, isSigned);
+  }
   case X86::BI__mulh:
-  case X86::BI__umulh: {
-    Value *LHS = EmitScalarExpr(E->getArg(0));
-    Value *RHS = EmitScalarExpr(E->getArg(1));
+  case X86::BI__umulh:
+  case X86::BI_mul128:
+  case X86::BI_umul128: {
     llvm::Type *ResType = ConvertType(E->getType());
     llvm::Type *Int128Ty = llvm::IntegerType::get(getLLVMContext(), 128);
 
-    bool IsSigned = (BuiltinID == X86::BI__mulh);
-    LHS = Builder.CreateIntCast(LHS, Int128Ty, IsSigned);
-    RHS = Builder.CreateIntCast(RHS, Int128Ty, IsSigned);
+    bool IsSigned = (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI_mul128);
+    Value *LHS = Builder.CreateIntCast(Ops[0], Int128Ty, IsSigned);
+    Value *RHS = Builder.CreateIntCast(Ops[1], Int128Ty, IsSigned);
 
     Value *MulResult, *HigherBits;
     if (IsSigned) {
@@ -7595,9 +7603,14 @@ Value *CodeGenFunction::EmitX86BuiltinEx
       MulResult = Builder.CreateNUWMul(LHS, RHS);
       HigherBits = Builder.CreateLShr(MulResult, 64);
     }
-
     HigherBits = Builder.CreateIntCast(HigherBits, ResType, IsSigned);
-    return HigherBits;
+
+    if (BuiltinID == X86::BI__mulh || BuiltinID == X86::BI__umulh)
+      return HigherBits;
+
+    Address HighBitsAddress = EmitPointerWithAlignment(E->getArg(2));
+    Builder.CreateStore(HigherBits, HighBitsAddress);
+    return Builder.CreateIntCast(MulResult, ResType, IsSigned);
   }
   }
 }

Modified: cfe/trunk/lib/Headers/intrin.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/intrin.h?rev=283785&r1=283784&r2=283785&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/intrin.h (original)
+++ cfe/trunk/lib/Headers/intrin.h Mon Oct 10 13:09:27 2016
@@ -66,7 +66,9 @@ void __cpuid(int[4], int);
 static __inline__
 void __cpuidex(int[4], int, int);
 void __debugbreak(void);
+static __inline__
 __int64 __emul(int, int);
+static __inline__
 unsigned __int64 __emulu(unsigned int, unsigned int);
 void __cdecl __fastfail(unsigned int);
 unsigned int __getcallerseflags(void);
@@ -313,8 +315,6 @@ unsigned __int64 __lzcnt64(unsigned __in
 static __inline__
 void __movsq(unsigned long long *, unsigned long long const *, size_t);
 static __inline__
-__int64 __mulh(__int64, __int64);
-static __inline__
 unsigned __int64 __popcnt64(unsigned __int64);
 static __inline__
 unsigned char __readgsbyte(unsigned long);
@@ -405,9 +405,6 @@ static __inline__
 __int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask);
 __int64 _InterlockedXor64_np(__int64 volatile *_Value, __int64 _Mask);
 char _InterlockedXor8_np(char volatile *_Value, char _Mask);
-static __inline__
-__int64 _mul128(__int64 _Multiplier, __int64 _Multiplicand,
-                __int64 *_HighProduct);
 unsigned __int64 _rorx_u64(unsigned __int64, const unsigned int);
 __int64 _sarx_i64(__int64, unsigned int);
 #if __STDC_HOSTED__
@@ -415,35 +412,20 @@ int __cdecl _setjmpex(jmp_buf);
 #endif
 unsigned __int64 _shlx_u64(unsigned __int64, unsigned int);
 unsigned __int64 _shrx_u64(unsigned __int64, unsigned int);
-/*
- * Multiply two 64-bit integers and obtain a 64-bit result.
- * The low-half is returned directly and the high half is in an out parameter.
- */
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-_umul128(unsigned __int64 _Multiplier, unsigned __int64 _Multiplicand,
-         unsigned __int64 *_HighProduct) {
-  unsigned __int128 _FullProduct =
-      (unsigned __int128)_Multiplier * (unsigned __int128)_Multiplicand;
-  *_HighProduct = _FullProduct >> 64;
-  return _FullProduct;
-}
+static __inline__
+__int64 __mulh(__int64, __int64);
 static __inline__
 unsigned __int64 __umulh(unsigned __int64, unsigned __int64);
+static __inline__
+__int64 _mul128(__int64, __int64, __int64*);
+static __inline__
+unsigned __int64 _umul128(unsigned __int64,
+                          unsigned __int64,
+                          unsigned __int64*);
 
 #endif /* __x86_64__ */
 
 /*----------------------------------------------------------------------------*\
-|* Multiplication
-\*----------------------------------------------------------------------------*/
-static __inline__ __int64 __DEFAULT_FN_ATTRS
-__emul(int __in1, int __in2) {
-  return (__int64)__in1 * (__int64)__in2;
-}
-static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
-__emulu(unsigned int __in1, unsigned int __in2) {
-  return (unsigned __int64)__in1 * (unsigned __int64)__in2;
-}
-/*----------------------------------------------------------------------------*\
 |* Bit Counting and Testing
 \*----------------------------------------------------------------------------*/
 static __inline__ unsigned char __DEFAULT_FN_ATTRS

Modified: cfe/trunk/test/CodeGen/ms-intrinsics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-intrinsics.c?rev=283785&r1=283784&r2=283785&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms-intrinsics.c (original)
+++ cfe/trunk/test/CodeGen/ms-intrinsics.c Mon Oct 10 13:09:27 2016
@@ -41,32 +41,6 @@ void *test_InterlockedCompareExchangePoi
 // CHECK:   ret i8* %[[RESULT:[0-9]+]]
 // CHECK: }
 
-#if defined(__i386__)
-long test__readfsdword(unsigned long Offset) {
-  return __readfsdword(Offset);
-}
-
-// CHECK-I386: define i32 @test__readfsdword(i32 %Offset){{.*}}{
-// CHECK-I386:   [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)*
-// CHECK-I386:   [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(257)* [[PTR]], align 4
-// CHECK-I386:   ret i32 [[VALUE:%[0-9]+]]
-// CHECK-I386: }
-#endif
-
-#if defined(__x86_64__)
-__int64 test__mulh(__int64 a, __int64 b) {
-  return __mulh(a, b);
-}
-// CHECK-X64-LABEL: define i64 @test__mulh(i64 %a, i64 %b)
-// CHECK-X64: = mul nsw i128 %
-
-unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) {
-  return __umulh(a, b);
-}
-// CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b)
-// CHECK-X64: = mul nuw i128 %
-#endif
-
 char test_InterlockedExchange8(char volatile *value, char mask) {
   return _InterlockedExchange8(value, mask);
 }

Added: cfe/trunk/test/CodeGen/ms-x86-intrinsics.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-x86-intrinsics.c?rev=283785&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/ms-x86-intrinsics.c (added)
+++ cfe/trunk/test/CodeGen/ms-x86-intrinsics.c Mon Oct 10 13:09:27 2016
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN:         -triple i686--windows -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-I386
+// RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN:         -triple x86_64--windows -Oz -emit-llvm %s -o - \
+// RUN:         | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64
+
+#if defined(__i386__)
+long test__readfsdword(unsigned long Offset) {
+  return __readfsdword(Offset);
+}
+
+// CHECK-I386-LABEL: define i32 @test__readfsdword(i32 %Offset){{.*}}{
+// CHECK-I386:   [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)*
+// CHECK-I386:   [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(257)* [[PTR]], align 4
+// CHECK-I386:   ret i32 [[VALUE:%[0-9]+]]
+// CHECK-I386: }
+#endif
+
+__int64 test__emul(int a, int b) {
+  return __emul(a, b);
+}
+// CHECK-LABEL: define i64 @test__emul(i32 %a, i32 %b)
+// CHECK: [[X:%[0-9]+]] = sext i32 %a to i64
+// CHECK: [[Y:%[0-9]+]] = sext i32 %b to i64
+// CHECK: [[RES:%[0-9]+]] = mul nsw i64 [[Y]], [[X]]
+// CHECK: ret i64 [[RES]]
+
+unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
+  return __emulu(a, b);
+}
+// CHECK-LABEL: define i64 @test__emulu(i32 %a, i32 %b)
+// CHECK: [[X:%[0-9]+]] = zext i32 %a to i64
+// CHECK: [[Y:%[0-9]+]] = zext i32 %b to i64
+// CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
+// CHECK: ret i64 [[RES]]
+
+#if defined(__x86_64__)
+__int64 test__mulh(__int64 a, __int64 b) {
+  return __mulh(a, b);
+}
+// CHECK-X64-LABEL: define i64 @test__mulh(i64 %a, i64 %b)
+// CHECK-X64: = mul nsw i128 %
+
+unsigned __int64 test__umulh(unsigned __int64 a, unsigned __int64 b) {
+  return __umulh(a, b);
+}
+// CHECK-X64-LABEL: define i64 @test__umulh(i64 %a, i64 %b)
+// CHECK-X64: = mul nuw i128 %
+
+__int64 test_mul128(__int64 Multiplier,
+                    __int64 Multiplicand,
+                    __int64 *HighProduct) {
+  return _mul128(Multiplier, Multiplicand, HighProduct);
+}
+// CHECK-X64-LABEL: define i64 @test_mul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
+// CHECK-X64: = sext i64 %Multiplier to i128
+// CHECK-X64: = sext i64 %Multiplicand to i128
+// CHECK-X64: = mul nsw i128 %
+// CHECK-X64: store i64 %
+// CHECK-X64: ret i64 %
+
+unsigned __int64 test_umul128(unsigned __int64 Multiplier,
+                              unsigned __int64 Multiplicand,
+                              unsigned __int64 *HighProduct) {
+  return _umul128(Multiplier, Multiplicand, HighProduct);
+}
+// CHECK-X64-LABEL: define i64 @test_umul128(i64 %Multiplier, i64 %Multiplicand, i64*{{[a-z_ ]*}}%HighProduct)
+// CHECK-X64: = zext i64 %Multiplier to i128
+// CHECK-X64: = zext i64 %Multiplicand to i128
+// CHECK-X64: = mul nuw i128 %
+// CHECK-X64: store i64 %
+// CHECK-X64: ret i64 %
+#endif




More information about the cfe-commits mailing list