From 5c91b98c5d45243352bf10262454bcac77cd3fed Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 27 Aug 2021 15:06:08 -0700 Subject: [PATCH] [ARMISelLowering] avoid emitting libcalls to __mulodi4() __has_builtin(__builtin_mul_overflow) returns true for 32b ARM targets, but Clang is deferring to compiler RT when encountering `long long` types. This breaks sanitizer builds of the Linux kernel that are using __builtin_mul_overflow with these types for these targets. If the semantics of __has_builtin mean "the compiler resolves these, always" then we shouldn't conditionally emit a libcall. This will still need to be worked around in the Linux kernel in order to continue to support allmodconfig builds of the Linux kernel for this target with older releases of clang. Link: https://bugs.llvm.org/show_bug.cgi?id=28629 Link: https://github.com/ClangBuiltLinux/linux/issues/1438 Reviewed By: rengolin Differential Revision: https://reviews.llvm.org/D108842 --- llvm/lib/Target/ARM/ARMISelLowering.cpp | 2 ++ .../CodeGen/ARM/overflow-intrinsic-optimizations.ll | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 5366a64..fb150b3 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -545,6 +545,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, setLibcallName(RTLIB::SRL_I128, nullptr); setLibcallName(RTLIB::SRA_I128, nullptr); setLibcallName(RTLIB::MUL_I128, nullptr); + setLibcallName(RTLIB::MULO_I64, nullptr); + setLibcallName(RTLIB::MULO_I128, nullptr); // RTLIB if (Subtarget->isAAPCS_ABI() && diff --git a/llvm/test/CodeGen/ARM/overflow-intrinsic-optimizations.ll b/llvm/test/CodeGen/ARM/overflow-intrinsic-optimizations.ll index 048a120..1a7809e 100644 --- a/llvm/test/CodeGen/ARM/overflow-intrinsic-optimizations.ll +++ b/llvm/test/CodeGen/ARM/overflow-intrinsic-optimizations.ll @@ -234,6 +234,22 @@ while.end: ret i32 %conv } +define i1 @no__mulodi4(i32 %a, i64 %b, i32* %c) { +; CHECK-LABEL: no__mulodi4 +; CHECK-NOT: bl __mulodi4 +entry: + %0 = sext i32 %a to i64 + %1 = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %0, i64 %b) + %2 = extractvalue { i64, i1 } %1, 1 + %3 = extractvalue { i64, i1 } %1, 0 + %4 = trunc i64 %3 to i32 + %5 = sext i32 %4 to i64 + %6 = icmp ne i64 %3, %5 + %7 = or i1 %2, %6 + store i32 %4, i32* %c, align 4 + ret i1 %7 +} + declare void @llvm.trap() #2 declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1 declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) #1 @@ -241,3 +257,4 @@ declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) #1 declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) #1 declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) #1 declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) #1 +declare { i64, i1 } @llvm.smul.with.overflow.i64(i64, i64) -- 2.7.4