[PATCH] D38861: [CodeGen] Error on unsupported checked multiplies early

Vedant Kumar via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 12 15:26:17 PDT 2017


vsk created this revision.

LLVM's smul.with.overflow intrinsic isn't supported on X86 for bit
widths larger than 64, or on X86-64 for bit widths larger than 128.

The failure mode is either a linker error ("the __muloti4 builtin isn't
available for this target") or an assertion failure ("SelectionDAG
doesn't know what builtin to call").

Until we actually add builtin support for 128-bit multiply-with-overflow
on X86, we should error-out on unsupported calls as early as possible.

https://bugs.llvm.org/show_bug.cgi?id=34920


https://reviews.llvm.org/D38861

Files:
  lib/CodeGen/CGBuiltin.cpp
  test/CodeGen/builtins-overflow-unsupported.c
  test/CodeGen/builtins-overflow.c


Index: test/CodeGen/builtins-overflow.c
===================================================================
--- test/CodeGen/builtins-overflow.c
+++ test/CodeGen/builtins-overflow.c
@@ -2,7 +2,7 @@
 // rdar://13421498
 
 // RUN: %clang_cc1 -triple "i686-unknown-unknown"   -emit-llvm -x c %s -o - | FileCheck %s
-// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - | FileCheck %s --check-prefixes=CHECK,M64
 // RUN: %clang_cc1 -triple "x86_64-mingw32"         -emit-llvm -x c %s -o - | FileCheck %s
 
 extern unsigned UnsignedErrorCode;
@@ -338,3 +338,20 @@
     return LongLongErrorCode;
   return result;
 }
+
+#if defined(__LP64__)
+signed long long test_mixed_sign_mul_i64(signed long long a, unsigned long long b) {
+  // M64-LABEL: define i64 @test_mixed_sign_mul_i64
+  // M64: sext i64 {{.*}} to i65
+  // M64-NEXT: zext i64 {{.*}} to i65
+  // M64-NEXT: call { i65, i1 } @llvm.smul.with.overflow.i65
+  // M64-NEXT: [[OFLOW_1:%.*]] = extractvalue { i65, i1 } {{.*}}, 1
+  // M64-NEXT: [[RES:%.*]] = extractvalue { i65, i1 } {{.*}}, 0
+  // M64-NEXT: [[RES_TRUNC:%.*]] = trunc i65 {{.*}} to i64
+  // M64-NEXT: [[RES_EXT:%.*]] = zext i64 {{.*}} to i65
+  // M64-NEXT: [[OFLOW_2:%.*]] = icmp ne i65 [[RES]], [[RES_EXT]]
+  // M64-NEXT: or i1 [[OFLOW_1]], [[OFLOW_2]]
+  // M64-NEXT: store i64 [[RES_TRUNC]]
+  return __builtin_mul_overflow(a, b, &b);
+}
+#endif
Index: test/CodeGen/builtins-overflow-unsupported.c
===================================================================
--- /dev/null
+++ test/CodeGen/builtins-overflow-unsupported.c
@@ -0,0 +1,14 @@
+// RUN: not %clang_cc1 -triple "i686-unknown-unknown"   -emit-llvm -x c %s -o - 2>&1 | FileCheck %s --check-prefix=M32
+// RUN: not %clang_cc1 -triple "x86_64-unknown-unknown" -emit-llvm -x c %s -o - 2>&1 | FileCheck %s --check-prefix=M64
+
+signed long long try_smul_i65(signed long long a, unsigned long long b) {
+  // M32: [[@LINE+1]]:10: error: cannot compile this __builtin_mul_overflow with mixed-sign operands yet
+  return __builtin_mul_overflow(a, b, &b);
+}
+
+#if defined(__LP64__)
+__int128_t try_smul_i29(__int128_t a, __uint128_t b) {
+  // M64: [[@LINE+1]]:10: error: cannot compile this __builtin_mul_overflow with mixed-sign operands yet
+  return __builtin_mul_overflow(a, b, &b);
+}
+#endif
Index: lib/CodeGen/CGBuiltin.cpp
===================================================================
--- lib/CodeGen/CGBuiltin.cpp
+++ lib/CodeGen/CGBuiltin.cpp
@@ -2248,11 +2248,23 @@
     WidthAndSignedness EncompassingInfo =
         EncompassingIntegerType({LeftInfo, RightInfo, ResultInfo});
 
+    llvm::Type *ResultLLVMTy = CGM.getTypes().ConvertType(ResultQTy);
+
+    const auto &Triple = getTarget().getTriple();
+    if (BuiltinID == Builtin::BI__builtin_mul_overflow) {
+      if ((EncompassingInfo.Width > 64 &&
+           Triple.getArch() == llvm::Triple::ArchType::x86) ||
+          (EncompassingInfo.Width > 128 &&
+           Triple.getArch() == llvm::Triple::ArchType::x86_64)) {
+        CGM.ErrorUnsupported(E,
+                             "__builtin_mul_overflow with mixed-sign operands");
+        return RValue::get(llvm::UndefValue::get(ResultLLVMTy));
+      }
+    }
+
     llvm::Type *EncompassingLLVMTy =
         llvm::IntegerType::get(CGM.getLLVMContext(), EncompassingInfo.Width);
 
-    llvm::Type *ResultLLVMTy = CGM.getTypes().ConvertType(ResultQTy);
-
     llvm::Intrinsic::ID IntrinsicId;
     switch (BuiltinID) {
     default:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D38861.118850.patch
Type: text/x-patch
Size: 3566 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171012/d529706b/attachment.bin>


More information about the cfe-commits mailing list