41 changes: 41 additions & 0 deletions clang/unittests/AST/ASTImporterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7711,6 +7711,47 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {
CheckAST(ToTU, ToC);
}

TEST_P(ASTImporterOptionSpecificTestBase,
ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
Decl *From, *To;
std::tie(From, To) = getImportedDecl(
R"s(
struct A {
A() : m() {}
int m;
};
A foo() { A a; return a; }
A bar() { return {}; }
)s",
Lang_CXX17,
R"s(
struct A {
A() : m() {}
int m;
};
A baz() { return {}; }
)s",
Lang_CXX17, "A");

auto HasCtorInit =
hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
auto ImpMoveCtor =
cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);

auto *FromImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
From, ImpMoveCtor);
auto *ToImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
To, ImpMoveCtor);

EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());

EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
EXPECT_TRUE(*ToImpMoveCtor->init_begin());
}

AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,
InnerMatcher) {
return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
Expand Down
26 changes: 26 additions & 0 deletions clang/unittests/AST/DeclTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,32 @@ TEST(Decl, FriendFunctionWithinClassInHeaderUnit) {
EXPECT_TRUE(getFooValue->isInlined());
}

TEST(Decl, FunctionDeclBitsShouldNotOverlapWithCXXConstructorDeclBits) {
llvm::Annotations Code(R"(
struct A {
A() : m() {}
int m;
};
A f() { return A(); }
)");

auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), {"-std=c++14"});
ASTContext &Ctx = AST->getASTContext();

auto HasCtorInit =
hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
auto ImpMoveCtor =
cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit)
.bind("MoveCtor");

auto *ToImpMoveCtor =
selectFirst<CXXConstructorDecl>("MoveCtor", match(ImpMoveCtor, Ctx));

EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
}

TEST(Decl, NoProtoFunctionDeclAttributes) {
llvm::Annotations Code(R"(
void f();
Expand Down
3 changes: 3 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13458,6 +13458,8 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
verifyFormat(
"class A {\n"
" A() : a{} {}\n"
" A() : Base<int>{} {}\n"
" A() : Base<Foo<int>>{} {}\n"
" A(int b) : b(b) {}\n"
" A(int a, int b) : a(a), bs{{bs...}} { f(); }\n"
" int a, b;\n"
Expand Down Expand Up @@ -26266,6 +26268,7 @@ TEST_F(FormatTest, RemoveParentheses) {

Style.RemoveParentheses = FormatStyle::RPS_MultipleParentheses;
verifyFormat("int x __attribute__((aligned(16))) = 0;", Style);
verifyFormat("decltype((foo->bar)) baz;", Style);
verifyFormat("class __declspec(dllimport) X {};",
"class __declspec((dllimport)) X {};", Style);
verifyFormat("int x = (({ 0; }));", "int x = ((({ 0; })));", Style);
Expand Down
16 changes: 13 additions & 3 deletions clang/unittests/Interpreter/InterpreterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,20 @@ TEST(IncrementalProcessing, FindMangledNameSymbol) {
}

std::string MangledName = MangleName(FD);
auto Addr = cantFail(Interp->getSymbolAddress(MangledName));
EXPECT_NE(0U, Addr.getValue());
auto Addr = Interp->getSymbolAddress(MangledName);
EXPECT_FALSE(!Addr);
EXPECT_NE(0U, Addr->getValue());
GlobalDecl GD(FD);
EXPECT_EQ(Addr, cantFail(Interp->getSymbolAddress(GD)));
EXPECT_EQ(*Addr, cantFail(Interp->getSymbolAddress(GD)));
cantFail(
Interp->ParseAndExecute("extern \"C\" int printf(const char*,...);"));
Addr = Interp->getSymbolAddress("printf");
EXPECT_FALSE(!Addr);

// FIXME: Re-enable when we investigate the way we handle dllimports on Win.
#ifndef _WIN32
EXPECT_EQ((unsigned long long)&printf, Addr->getValue());
#endif // _WIN32
}

static void *AllocateObject(TypeDecl *TD, Interpreter &Interp) {
Expand Down
56 changes: 29 additions & 27 deletions compiler-rt/lib/asan/asan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,19 +588,34 @@ INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) {
return REAL(strncpy)(to, from, size);
}

INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtol);
ENSURE_ASAN_INITED();
if (!flags()->replace_str) {
return REAL(strtol)(nptr, endptr, base);
}
template <typename Fn>
static ALWAYS_INLINE auto StrtolImpl(void *ctx, Fn real, const char *nptr,
char **endptr, int base)
-> decltype(real(nullptr, nullptr, 0)) {
if (!flags()->replace_str)
return real(nptr, endptr, base);
char *real_endptr;
long result = REAL(strtol)(nptr, &real_endptr, base);
auto res = real(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result;
return res;
}

# define INTERCEPTOR_STRTO_BASE(ret_type, func) \
INTERCEPTOR(ret_type, func, const char *nptr, char **endptr, int base) { \
void *ctx; \
ASAN_INTERCEPTOR_ENTER(ctx, func); \
ENSURE_ASAN_INITED(); \
return StrtolImpl(ctx, REAL(func), nptr, endptr, base); \
}

INTERCEPTOR_STRTO_BASE(long, strtol)
INTERCEPTOR_STRTO_BASE(long long, strtoll)

# if SANITIZER_GLIBC
INTERCEPTOR_STRTO_BASE(long, __isoc23_strtol)
INTERCEPTOR_STRTO_BASE(long long, __isoc23_strtoll)
# endif

INTERCEPTOR(int, atoi, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atoi);
Expand Down Expand Up @@ -639,20 +654,6 @@ INTERCEPTOR(long, atol, const char *nptr) {
return result;
}

#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, strtoll);
ENSURE_ASAN_INITED();
if (!flags()->replace_str) {
return REAL(strtoll)(nptr, endptr, base);
}
char *real_endptr;
long long result = REAL(strtoll)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return result;
}

INTERCEPTOR(long long, atoll, const char *nptr) {
void *ctx;
ASAN_INTERCEPTOR_ENTER(ctx, atoll);
Expand All @@ -666,7 +667,6 @@ INTERCEPTOR(long long, atoll, const char *nptr) {
ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1);
return result;
}
#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL

#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT
static void AtCxaAtexit(void *unused) {
Expand Down Expand Up @@ -751,11 +751,13 @@ void InitializeAsanInterceptors() {

ASAN_INTERCEPT_FUNC(atoi);
ASAN_INTERCEPT_FUNC(atol);
ASAN_INTERCEPT_FUNC(strtol);
#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
ASAN_INTERCEPT_FUNC(atoll);
ASAN_INTERCEPT_FUNC(strtol);
ASAN_INTERCEPT_FUNC(strtoll);
#endif
# if SANITIZER_GLIBC
ASAN_INTERCEPT_FUNC(__isoc23_strtol);
ASAN_INTERCEPT_FUNC(__isoc23_strtoll);
# endif

// Intecept jump-related functions.
ASAN_INTERCEPT_FUNC(longjmp);
Expand Down
2 changes: 0 additions & 2 deletions compiler-rt/lib/asan/asan_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ void InitializePlatformInterceptors();
// Use macro to describe if specific function should be
// intercepted on a given platform.
#if !SANITIZER_WINDOWS
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
# define ASAN_INTERCEPT__LONGJMP 1
# define ASAN_INTERCEPT_INDEX 1
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
#else
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
# define ASAN_INTERCEPT__LONGJMP 0
# define ASAN_INTERCEPT_INDEX 0
# define ASAN_INTERCEPT_PTHREAD_CREATE 0
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/asan/asan_win_dll_thunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ INTERCEPT_WRAP_W_W(_expand_dbg)

INTERCEPT_LIBRARY_FUNCTION(atoi);
INTERCEPT_LIBRARY_FUNCTION(atol);
INTERCEPT_LIBRARY_FUNCTION(atoll);
INTERCEPT_LIBRARY_FUNCTION(frexp);
INTERCEPT_LIBRARY_FUNCTION(longjmp);
#if SANITIZER_INTERCEPT_MEMCHR
Expand All @@ -91,6 +92,7 @@ INTERCEPT_LIBRARY_FUNCTION(strspn);
INTERCEPT_LIBRARY_FUNCTION(strstr);
INTERCEPT_LIBRARY_FUNCTION(strtok);
INTERCEPT_LIBRARY_FUNCTION(strtol);
INTERCEPT_LIBRARY_FUNCTION(strtoll);
INTERCEPT_LIBRARY_FUNCTION(wcslen);
INTERCEPT_LIBRARY_FUNCTION(wcsnlen);

Expand Down
37 changes: 37 additions & 0 deletions compiler-rt/lib/msan/msan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,25 @@ INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)

#if SANITIZER_GLIBC
INTERCEPTORS_STRTO(double, __isoc23_strtod, char)
INTERCEPTORS_STRTO(float, __isoc23_strtof, char)
INTERCEPTORS_STRTO(long double, __isoc23_strtold, char)
INTERCEPTORS_STRTO_BASE(long, __isoc23_strtol, char)
INTERCEPTORS_STRTO_BASE(long long, __isoc23_strtoll, char)
INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_strtoul, char)
INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_strtoull, char)
INTERCEPTORS_STRTO_BASE(u64, __isoc23_strtouq, char)

INTERCEPTORS_STRTO(double, __isoc23_wcstod, wchar_t)
INTERCEPTORS_STRTO(float, __isoc23_wcstof, wchar_t)
INTERCEPTORS_STRTO(long double, __isoc23_wcstold, wchar_t)
INTERCEPTORS_STRTO_BASE(long, __isoc23_wcstol, wchar_t)
INTERCEPTORS_STRTO_BASE(long long, __isoc23_wcstoll, wchar_t)
INTERCEPTORS_STRTO_BASE(unsigned long, __isoc23_wcstoul, wchar_t)
INTERCEPTORS_STRTO_BASE(unsigned long long, __isoc23_wcstoull, wchar_t)
#endif

#if SANITIZER_NETBSD
#define INTERCEPT_STRTO(func) \
INTERCEPT_FUNCTION(func); \
Expand Down Expand Up @@ -1748,6 +1767,24 @@ void InitializeInterceptors() {
INTERCEPT_STRTO(wcstoul);
INTERCEPT_STRTO(wcstoll);
INTERCEPT_STRTO(wcstoull);
#if SANITIZER_GLIBC
INTERCEPT_STRTO(__isoc23_strtod);
INTERCEPT_STRTO(__isoc23_strtof);
INTERCEPT_STRTO(__isoc23_strtold);
INTERCEPT_STRTO(__isoc23_strtol);
INTERCEPT_STRTO(__isoc23_strtoul);
INTERCEPT_STRTO(__isoc23_strtoll);
INTERCEPT_STRTO(__isoc23_strtoull);
INTERCEPT_STRTO(__isoc23_strtouq);
INTERCEPT_STRTO(__isoc23_wcstod);
INTERCEPT_STRTO(__isoc23_wcstof);
INTERCEPT_STRTO(__isoc23_wcstold);
INTERCEPT_STRTO(__isoc23_wcstol);
INTERCEPT_STRTO(__isoc23_wcstoul);
INTERCEPT_STRTO(__isoc23_wcstoll);
INTERCEPT_STRTO(__isoc23_wcstoull);
#endif

#ifdef SANITIZER_NLDBL_VERSION
INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
Expand Down
73 changes: 57 additions & 16 deletions compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,16 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)

INTERCEPTOR(int, __isoc23_vscanf, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vscanf, false, format, ap)

INTERCEPTOR(int, __isoc23_vsscanf, const char *str, const char *format,
va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vsscanf, false, str, format, ap)

INTERCEPTOR(int, __isoc23_vfscanf, void *stream, const char *format, va_list ap)
VSCANF_INTERCEPTOR_IMPL(__isoc23_vfscanf, false, stream, format, ap)
#endif // SANITIZER_INTERCEPT_ISOC99_SCANF

INTERCEPTOR(int, scanf, const char *format, ...)
Expand All @@ -1511,6 +1521,15 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)

INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)

INTERCEPTOR(int, __isoc23_scanf, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_scanf, __isoc23_vscanf, format)

INTERCEPTOR(int, __isoc23_fscanf, void *stream, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_fscanf, __isoc23_vfscanf, stream, format)

INTERCEPTOR(int, __isoc23_sscanf, const char *str, const char *format, ...)
FORMAT_INTERCEPTOR_IMPL(__isoc23_sscanf, __isoc23_vsscanf, str, format)
#endif

#endif
Expand All @@ -1534,7 +1553,13 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_scanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_sscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_fscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_vscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_vsscanf); \
COMMON_INTERCEPT_FUNCTION(__isoc23_vfscanf);
#else
#define INIT_ISOC99_SCANF
#endif
Expand Down Expand Up @@ -3539,30 +3564,26 @@ UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
(real_endptr - nptr) + 1 : 0);
}


#if SANITIZER_INTERCEPT_STRTOIMAX
INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
template <typename Fn>
static ALWAYS_INLINE auto StrtoimaxImpl(void *ctx, Fn real, const char *nptr,
char **endptr, int base)
-> decltype(real(nullptr, nullptr, 0)) {
char *real_endptr;
INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
auto res = real(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return res;
}

INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
return StrtoimaxImpl(ctx, REAL(strtoimax), nptr, endptr, base);
}
INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
char *real_endptr;
UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
return res;
return StrtoimaxImpl(ctx, REAL(strtoumax), nptr, endptr, base);
}

#define INIT_STRTOIMAX \
Expand All @@ -3572,6 +3593,25 @@ INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
#define INIT_STRTOIMAX
#endif

#if SANITIZER_INTERCEPT_STRTOIMAX && SANITIZER_GLIBC
INTERCEPTOR(INTMAX_T, __isoc23_strtoimax, const char *nptr, char **endptr, int base) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoimax, nptr, endptr, base);
return StrtoimaxImpl(ctx, REAL(__isoc23_strtoimax), nptr, endptr, base);
}
INTERCEPTOR(UINTMAX_T, __isoc23_strtoumax, const char *nptr, char **endptr, int base) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoumax, nptr, endptr, base);
return StrtoimaxImpl(ctx, REAL(__isoc23_strtoumax), nptr, endptr, base);
}

# define INIT_STRTOIMAX_C23 \
COMMON_INTERCEPT_FUNCTION(__isoc23_strtoimax); \
COMMON_INTERCEPT_FUNCTION(__isoc23_strtoumax);
#else
# define INIT_STRTOIMAX_C23
#endif

#if SANITIZER_INTERCEPT_MBSTOWCS
INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
void *ctx;
Expand Down Expand Up @@ -10304,6 +10344,7 @@ static void InitializeCommonInterceptors() {
INIT_GETCWD;
INIT_GET_CURRENT_DIR_NAME;
INIT_STRTOIMAX;
INIT_STRTOIMAX_C23;
INIT_MBSTOWCS;
INIT_MBSNRTOWCS;
INIT_WCSTOMBS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ __interceptor_pthread_setspecific w
__interceptor_read w
__interceptor_realpath w
__isinf U
__isoc23_sscanf U
__isoc23_strtol U
__isoc23_strtoll U
__isoc23_strtoll_l U
__isoc23_strtoull U
__isoc23_strtoull_l U
__isoc23_vsscanf U
__isoc99_sscanf U
__isoc99_vsscanf U
__moddi3 U
Expand Down
3 changes: 0 additions & 3 deletions compiler-rt/test/asan/TestCases/atoll_strict.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
// RUN: %env_asan_opts=strict_string_checks=false %run %t test3 2>&1
// RUN: %env_asan_opts=strict_string_checks=true not %run %t test3 2>&1 | FileCheck %s --check-prefix=CHECK3

// FIXME: Needs Windows interceptor.
// XFAIL: target={{.*windows-(msvc.*|gnu)}}

#include <assert.h>
#include <stdlib.h>
#include <string.h>
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/test/asan/TestCases/strtoll_strict.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

// FIXME: Enable strtoll interceptor.
// REQUIRES: shadow-scale-3
// XFAIL: target={{.*windows-(msvc.*|gnu)}}
// XFAIL: target={{.*windows-msvc.*}}

#include <assert.h>
#include <stdlib.h>
Expand Down
24 changes: 24 additions & 0 deletions compiler-rt/test/sanitizer_common/TestCases/scanf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %clang -std=c17 %s -o %t && %run %t
/// Test __isoc23_* for glibc 2.38+.
// RUN: %clang -std=c23 %s -o %t && %run %t

#include <assert.h>
#include <stdarg.h>
#include <stdio.h>

int test_vsscanf(const char *buf, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = vsscanf(buf, fmt, ap);
va_end(ap);
return ret;
}

int main(int argc, char **argv) {
int x, y;
assert(sscanf("42", "%d", &x) == 1);
assert(x == 42);
assert(test_vsscanf("42", "%d", &y) == 1);
assert(y == 42);
return 0;
}
61 changes: 61 additions & 0 deletions compiler-rt/test/sanitizer_common/TestCases/strtol.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// RUN: %clang -std=c17 %s -o %t && %run %t
/// Test __isoc23_* for glibc 2.38+.
// RUN: %clang -std=c23 %s -o %t && %run %t

#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

#define TESTL(func) \
{ \
char *end; \
long l = (long)func("42", &end, 0); \
assert(l == 42); \
assert(*end == '\0'); \
}

#define TESTF(func) \
{ \
char *end; \
long l = (long)func("42", &end); \
assert(l == 42); \
assert(*end == '\0'); \
}

#define WTESTL(func) \
{ \
wchar_t *end; \
long l = (long)func(L"42", &end, 0); \
assert(l == 42); \
assert(*end == L'\0'); \
}

#define WTESTF(func) \
{ \
wchar_t *end; \
long l = (long)func(L"42", &end); \
assert(l == 42); \
assert(*end == '\0'); \
}

int main() {
TESTL(strtol);
TESTL(strtoll);
TESTL(strtoimax);
TESTL(strtoul);
TESTL(strtoull);
TESTL(strtoumax);
TESTF(strtof);
TESTF(strtod);
TESTF(strtold);

WTESTL(wcstol);
WTESTL(wcstoll);
WTESTL(wcstoul);
WTESTL(wcstoull);
WTESTF(wcstof);
WTESTF(wcstod);
WTESTF(wcstold);
}
13 changes: 12 additions & 1 deletion llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3414,6 +3414,7 @@ bool RISCVDAGToDAGISel::performCombineVMergeAndVOps(SDNode *N) {

// Because N and True must have the same merge operand (or True's operand is
// implicit_def), the "effective" body is the minimum of their VLs.
SDValue OrigVL = VL;
VL = GetMinVL(TrueVL, VL);
if (!VL)
return false;
Expand Down Expand Up @@ -3461,7 +3462,17 @@ bool RISCVDAGToDAGISel::performCombineVMergeAndVOps(SDNode *N) {
"Expected instructions with mask have a tied dest.");
#endif

uint64_t Policy = isImplicitDef(Merge) ? RISCVII::TAIL_AGNOSTIC : /*TUMU*/ 0;
// Use a tumu policy, relaxing it to tail agnostic provided that the merge
// operand is undefined.
//
// However, if the VL became smaller than what the vmerge had originally, then
// elements past VL that were previously in the vmerge's body will have moved
// to the tail. In that case we always need to use tail undisturbed to
// preserve them.
bool MergeVLShrunk = VL != OrigVL;
uint64_t Policy = (isImplicitDef(Merge) && !MergeVLShrunk)
? RISCVII::TAIL_AGNOSTIC
: /*TUMU*/ 0;
SDValue PolicyOp =
CurDAG->getTargetConstant(Policy, DL, Subtarget->getXLenVT());

Expand Down
79 changes: 47 additions & 32 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1648,17 +1648,14 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::FP_ROUND, VT, Custom);
setOperationAction(ISD::STRICT_FP_ROUND, VT, Custom);
}
for (MVT VT : { MVT::f32, MVT::v2f32, MVT::v4f32 }) {
for (MVT VT : { MVT::f32, MVT::v2f32, MVT::v4f32, MVT::v8f32 }) {
setOperationAction(ISD::FP_EXTEND, VT, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, VT, Custom);
}
for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) {
setOperationPromotedToType(Opc, MVT::v8f16, MVT::v8f32);
setOperationPromotedToType(Opc, MVT::v16f16, MVT::v16f32);
}

setOperationAction(ISD::FP_EXTEND, MVT::v8f32, Legal);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v8f32, Legal);
}

// This block controls legalization of the mask vector sizes that are
Expand Down Expand Up @@ -1975,8 +1972,8 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setF16Action(MVT::v32f16, Expand);
setOperationAction(ISD::FP_ROUND, MVT::v16f16, Custom);
setOperationAction(ISD::STRICT_FP_ROUND, MVT::v16f16, Custom);
setOperationAction(ISD::FP_EXTEND, MVT::v16f32, Legal);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v16f32, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v16f32, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v16f32, Custom);
for (unsigned Opc : {ISD::FADD, ISD::FSUB, ISD::FMUL, ISD::FDIV}) {
setOperationPromotedToType(Opc, MVT::v16f16, MVT::v16f32);
setOperationPromotedToType(Opc, MVT::v32f16, MVT::v32f32);
Expand Down Expand Up @@ -2197,9 +2194,9 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::v32i16, Legal);
setOperationAction(ISD::FP_ROUND, MVT::v16f16, Legal);
setOperationAction(ISD::STRICT_FP_ROUND, MVT::v16f16, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v16f32, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v16f32, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v16f32, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v8f64, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v8f64, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v8f64, Legal);
setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v32f16, Custom);

Expand Down Expand Up @@ -2249,9 +2246,9 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::v8i16, Custom);
setOperationAction(ISD::FP_ROUND, MVT::v8f16, Legal);
setOperationAction(ISD::STRICT_FP_ROUND, MVT::v8f16, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v8f32, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v8f32, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v8f32, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v4f64, Legal);
setOperationAction(ISD::FP_EXTEND, MVT::v4f64, Custom);
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::v4f64, Legal);

// INSERT_VECTOR_ELT v8f16 extended to VECTOR_SHUFFLE
Expand Down Expand Up @@ -14795,13 +14792,9 @@ static bool isShuffleFoldableLoad(SDValue V) {
}

template<typename T>
static bool isSoftFP16(T VT, const X86Subtarget &Subtarget) {
return VT.getScalarType() == MVT::f16 && !Subtarget.hasFP16();
}

template<typename T>
bool X86TargetLowering::isSoftFP16(T VT) const {
return ::isSoftFP16(VT, Subtarget);
static bool isSoftF16(T VT, const X86Subtarget &Subtarget) {
T EltVT = VT.getScalarType();
return EltVT == MVT::bf16 || (EltVT == MVT::f16 && !Subtarget.hasFP16());
}

/// Try to lower insertion of a single element into a zero vector.
Expand All @@ -14817,7 +14810,7 @@ static SDValue lowerShuffleAsElementInsertion(
unsigned NumElts = VT.getVectorNumElements();
unsigned EltBits = VT.getScalarSizeInBits();

if (isSoftFP16(EltVT, Subtarget))
if (isSoftF16(EltVT, Subtarget))
return SDValue();

int V2Index =
Expand Down Expand Up @@ -20374,7 +20367,7 @@ SDValue X86TargetLowering::LowerVSELECT(SDValue Op, SelectionDAG &DAG) const {

SDLoc dl(Op);
MVT VT = Op.getSimpleValueType();
if (isSoftFP16(VT)) {
if (isSoftF16(VT, Subtarget)) {
MVT NVT = VT.changeVectorElementTypeToInteger();
return DAG.getBitcast(VT, DAG.getNode(ISD::VSELECT, dl, NVT, Cond,
DAG.getBitcast(NVT, LHS),
Expand Down Expand Up @@ -21852,7 +21845,7 @@ SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op,
MVT VT = Op.getSimpleValueType();
SDLoc dl(Op);

if (isSoftFP16(VT))
if (isSoftF16(VT, Subtarget))
return promoteXINT_TO_FP(Op, DAG);
else if (isLegalConversion(SrcVT, true, Subtarget))
return Op;
Expand Down Expand Up @@ -22357,7 +22350,7 @@ SDValue X86TargetLowering::LowerUINT_TO_FP(SDValue Op,
if (DstVT == MVT::f128)
return SDValue();

if (isSoftFP16(DstVT))
if (isSoftF16(DstVT, Subtarget))
return promoteXINT_TO_FP(Op, DAG);
else if (isLegalConversion(SrcVT, false, Subtarget))
return Op;
Expand Down Expand Up @@ -23314,7 +23307,7 @@ SDValue X86TargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const {
SDLoc dl(Op);

SDValue Res;
if (isSoftFP16(SrcVT)) {
if (isSoftF16(SrcVT, Subtarget)) {
MVT NVT = VT.isVector() ? VT.changeVectorElementType(MVT::f32) : MVT::f32;
if (IsStrict)
return DAG.getNode(Op.getOpcode(), dl, {VT, MVT::Other},
Expand Down Expand Up @@ -23743,7 +23736,7 @@ X86TargetLowering::LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const {

// This code is only for floats and doubles. Fall back to generic code for
// anything else.
if (!isScalarFPTypeInSSEReg(SrcVT) || isSoftFP16(SrcVT))
if (!isScalarFPTypeInSSEReg(SrcVT) || isSoftF16(SrcVT, Subtarget))
return SDValue();

EVT SatVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
Expand Down Expand Up @@ -23888,6 +23881,10 @@ SDValue X86TargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
!Subtarget.getTargetTriple().isOSDarwin()))
return SDValue();

if ((SVT == MVT::v8f16 && Subtarget.hasF16C()) ||
(SVT == MVT::v16f16 && Subtarget.useAVX512Regs()))
return Op;

if (SVT == MVT::f16) {
if (Subtarget.hasFP16())
return Op;
Expand Down Expand Up @@ -23960,7 +23957,25 @@ SDValue X86TargetLowering::LowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const {
if (!SVT.isVector())
return Op;

if (SVT.getVectorElementType() == MVT::bf16) {
// FIXME: Do we need to support strict FP?
assert(!IsStrict && "Strict FP doesn't support BF16");
if (VT.getVectorElementType() == MVT::f64) {
MVT TmpVT = VT.changeVectorElementType(MVT::f32);
return DAG.getNode(ISD::FP_EXTEND, DL, VT,
DAG.getNode(ISD::FP_EXTEND, DL, TmpVT, In));
}
assert(VT.getVectorElementType() == MVT::f32 && "Unexpected fpext");
MVT NVT = SVT.changeVectorElementType(MVT::i32);
In = DAG.getBitcast(SVT.changeTypeToInteger(), In);
In = DAG.getNode(ISD::ZERO_EXTEND, DL, NVT, In);
In = DAG.getNode(ISD::SHL, DL, NVT, In, DAG.getConstant(16, DL, NVT));
return DAG.getBitcast(VT, In);
}

if (SVT.getVectorElementType() == MVT::f16) {
if (Subtarget.hasFP16() && isTypeLegal(SVT))
return Op;
assert(Subtarget.hasF16C() && "Unexpected features!");
if (SVT == MVT::v2f16)
In = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v4f16, In,
Expand Down Expand Up @@ -25676,7 +25691,7 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget &Subtarget,
if (isFP) {
MVT EltVT = Op0.getSimpleValueType().getVectorElementType();
assert(EltVT == MVT::f16 || EltVT == MVT::f32 || EltVT == MVT::f64);
if (isSoftFP16(EltVT, Subtarget))
if (isSoftF16(EltVT, Subtarget))
return SDValue();

bool IsSignaling = Op.getOpcode() == ISD::STRICT_FSETCCS;
Expand Down Expand Up @@ -26241,7 +26256,7 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
ISD::CondCode CC =
cast<CondCodeSDNode>(Op.getOperand(IsStrict ? 3 : 2))->get();

if (isSoftFP16(Op0.getValueType()))
if (isSoftF16(Op0.getValueType(), Subtarget))
return SDValue();

// Handle f128 first, since one possible outcome is a normal integer
Expand Down Expand Up @@ -26434,7 +26449,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
MVT VT = Op1.getSimpleValueType();
SDValue CC;

if (isSoftFP16(VT)) {
if (isSoftF16(VT, Subtarget)) {
MVT NVT = VT.changeTypeToInteger();
return DAG.getBitcast(VT, DAG.getNode(ISD::SELECT, DL, NVT, Cond,
DAG.getBitcast(NVT, Op1),
Expand Down Expand Up @@ -26506,7 +26521,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
}

if (Cond.getOpcode() == ISD::SETCC &&
!isSoftFP16(Cond.getOperand(0).getSimpleValueType())) {
!isSoftF16(Cond.getOperand(0).getSimpleValueType(), Subtarget)) {
if (SDValue NewCond = LowerSETCC(Cond, DAG)) {
Cond = NewCond;
// If the condition was updated, it's possible that the operands of the
Expand Down Expand Up @@ -27196,7 +27211,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
// Bail out when we don't have native compare instructions.
if (Cond.getOpcode() == ISD::SETCC &&
Cond.getOperand(0).getValueType() != MVT::f128 &&
!isSoftFP16(Cond.getOperand(0).getValueType())) {
!isSoftF16(Cond.getOperand(0).getValueType(), Subtarget)) {
SDValue LHS = Cond.getOperand(0);
SDValue RHS = Cond.getOperand(1);
ISD::CondCode CC = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
Expand Down Expand Up @@ -34983,7 +34998,7 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N,
EVT SrcVT = Src.getValueType();

SDValue Res;
if (isSoftFP16(SrcVT)) {
if (isSoftF16(SrcVT, Subtarget)) {
EVT NVT = VT.isVector() ? VT.changeVectorElementType(MVT::f32) : MVT::f32;
if (IsStrict) {
Res =
Expand Down Expand Up @@ -47383,7 +47398,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
// ignored in unsafe-math mode).
// We also try to create v2f32 min/max nodes, which we later widen to v4f32.
if (Cond.getOpcode() == ISD::SETCC && VT.isFloatingPoint() &&
VT != MVT::f80 && VT != MVT::f128 && !isSoftFP16(VT, Subtarget) &&
VT != MVT::f80 && VT != MVT::f128 && !isSoftF16(VT, Subtarget) &&
(TLI.isTypeLegal(VT) || VT == MVT::v2f32) &&
(Subtarget.hasSSE2() ||
(Subtarget.hasSSE1() && VT.getScalarType() == MVT::f32))) {
Expand Down Expand Up @@ -47700,7 +47715,7 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
}

// Early exit check
if (!TLI.isTypeLegal(VT) || isSoftFP16(VT, Subtarget))
if (!TLI.isTypeLegal(VT) || isSoftF16(VT, Subtarget))
return SDValue();

if (SDValue V = combineVSelectWithAllOnesOrZeros(N, DAG, DCI, Subtarget))
Expand Down Expand Up @@ -54550,7 +54565,7 @@ static SDValue combineFMinFMax(SDNode *N, SelectionDAG &DAG) {
static SDValue combineFMinNumFMaxNum(SDNode *N, SelectionDAG &DAG,
const X86Subtarget &Subtarget) {
EVT VT = N->getValueType(0);
if (Subtarget.useSoftFloat() || isSoftFP16(VT, Subtarget))
if (Subtarget.useSoftFloat() || isSoftF16(VT, Subtarget))
return SDValue();

const TargetLowering &TLI = DAG.getTargetLoweringInfo();
Expand Down
2 changes: 0 additions & 2 deletions llvm/lib/Target/X86/X86ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -1749,8 +1749,6 @@ namespace llvm {

bool needsCmpXchgNb(Type *MemType) const;

template<typename T> bool isSoftFP16(T VT) const;

void SetupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB,
MachineBasicBlock *DispatchBB, int FI) const;

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ static Decomposition decompose(Value *V,
return MergeResults(Op0, Op1, IsSigned);

ConstantInt *CI;
if (match(V, m_NSWMul(m_Value(Op0), m_ConstantInt(CI)))) {
if (match(V, m_NSWMul(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI)) {
auto Result = decompose(Op0, Preconditions, IsSigned, DL);
Result.mul(CI->getSExtValue());
return Result;
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vselect.ll
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) {
; RV32-NEXT: vslidedown.vi v10, v10, 2
; RV32-NEXT: vand.vi v10, v10, 1
; RV32-NEXT: vmsne.vi v0, v10, 0
; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, mu
; RV32-NEXT: vsetivli zero, 6, e32, m2, tu, mu
; RV32-NEXT: vle32.v v8, (a0), v0.t
; RV32-NEXT: vse32.v v8, (a3)
; RV32-NEXT: ret
Expand Down Expand Up @@ -58,7 +58,7 @@ define void @vselect_vv_v6i32(ptr %a, ptr %b, ptr %cc, ptr %z) {
; RV64-NEXT: vslidedown.vi v10, v10, 2
; RV64-NEXT: vand.vi v10, v10, 1
; RV64-NEXT: vmsne.vi v0, v10, 0
; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, mu
; RV64-NEXT: vsetivli zero, 6, e32, m2, tu, mu
; RV64-NEXT: vle32.v v8, (a0), v0.t
; RV64-NEXT: vse32.v v8, (a3)
; RV64-NEXT: ret
Expand Down Expand Up @@ -239,7 +239,7 @@ define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) {
; RV32-NEXT: vslidedown.vi v10, v10, 2
; RV32-NEXT: vand.vi v10, v10, 1
; RV32-NEXT: vmsne.vi v0, v10, 0
; RV32-NEXT: vsetivli zero, 6, e32, m2, ta, mu
; RV32-NEXT: vsetivli zero, 6, e32, m2, tu, mu
; RV32-NEXT: vle32.v v8, (a0), v0.t
; RV32-NEXT: vse32.v v8, (a3)
; RV32-NEXT: ret
Expand Down Expand Up @@ -269,7 +269,7 @@ define void @vselect_vv_v6f32(ptr %a, ptr %b, ptr %cc, ptr %z) {
; RV64-NEXT: vslidedown.vi v10, v10, 2
; RV64-NEXT: vand.vi v10, v10, 1
; RV64-NEXT: vmsne.vi v0, v10, 0
; RV64-NEXT: vsetivli zero, 6, e32, m2, ta, mu
; RV64-NEXT: vsetivli zero, 6, e32, m2, tu, mu
; RV64-NEXT: vle32.v v8, (a0), v0.t
; RV64-NEXT: vse32.v v8, (a3)
; RV64-NEXT: ret
Expand Down
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1065,3 +1065,15 @@ define <vscale x 2 x i32> @vmerge_larger_vl_poison_passthru(<vscale x 2 x i32> %
ret <vscale x 2 x i32> %b
}

; The vadd's new policy should be tail undisturbed since the false op of the
; vmerge moves from the the body to the tail, and we need to preserve it.
define <vscale x 2 x i32> @vmerge_larger_vl_false_becomes_tail(<vscale x 2 x i32> %false, <vscale x 2 x i32> %x, <vscale x 2 x i32> %y, <vscale x 2 x i1> %m) {
; CHECK-LABEL: vmerge_larger_vl_false_becomes_tail:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 2, e32, m1, tu, mu
; CHECK-NEXT: vadd.vv v8, v9, v10, v0.t
; CHECK-NEXT: ret
%a = call <vscale x 2 x i32> @llvm.riscv.vadd.nxv2i32.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %x, <vscale x 2 x i32> %y, i64 2)
%b = call <vscale x 2 x i32> @llvm.riscv.vmerge.nxv2i32.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %false, <vscale x 2 x i32> %a, <vscale x 2 x i1> %m, i64 3)
ret <vscale x 2 x i32> %b
}
590 changes: 463 additions & 127 deletions llvm/test/CodeGen/X86/bfloat.ll

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,29 @@ else:
ret i1 false
}

define i1 @mul_nsw_decomp(i128 %x) {
; CHECK-LABEL: @mul_nsw_decomp(
; CHECK-NEXT: [[VAL:%.*]] = mul nsw i128 [[X:%.*]], 9223372036854775808
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i128 [[X]], [[VAL]]
; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
; CHECK: then:
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i128 [[X]], 0
; CHECK-NEXT: ret i1 [[CMP2]]
; CHECK: else:
; CHECK-NEXT: ret i1 false
;
%val = mul nsw i128 %x, 9223372036854775808
%cmp = icmp sgt i128 %x, %val
br i1 %cmp, label %then, label %else

then:
%cmp2 = icmp sgt i128 %x, 0
ret i1 %cmp2

else:
ret i1 false
}

define i1 @add_nuw_decomp_recursive() {
; CHECK-LABEL: @add_nuw_decomp_recursive(
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 -9223372036854775808, 10
Expand Down
10 changes: 5 additions & 5 deletions llvm/tools/llvm-exegesis/lib/X86/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,11 +1083,11 @@ ExegesisX86Target::generateExitSyscall(unsigned ExitCode) const {
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif

// 32 bit ARM doesn't have mmap and uses mmap2 instead. The only difference
// between the two syscalls is that mmap2's offset parameter is in terms 4096
// byte offsets rather than individual bytes, so for our purposes they are
// effectively the same as all ofsets here are set to 0.
#ifdef __arm__
// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
// difference between the two syscalls is that mmap2's offset parameter is in
// terms 4096 byte offsets rather than individual bytes, so for our purposes
// they are effectively the same as all ofsets here are set to 0.
#if defined(SYS_mmap2) && !defined(SYS_mmap)
#define SYS_mmap SYS_mmap2
#endif

Expand Down
10 changes: 5 additions & 5 deletions llvm/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,11 +635,11 @@ TEST_F(X86Core2TargetTest, GenerateExitSyscallTest) {
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif

// 32 bit ARM doesn't have mmap and uses mmap2 instead. The only difference
// between the two syscalls is that mmap2's offset parameter is in terms 4096
// byte offsets rather than individual bytes, so for our purposes they are
// effectively the same as all ofsets here are set to 0.
#ifdef __arm__
// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
// difference between the two syscalls is that mmap2's offset parameter is in
// terms 4096 byte offsets rather than individual bytes, so for our purposes
// they are effectively the same as all ofsets here are set to 0.
#if defined(SYS_mmap2) && !defined(SYS_mmap)
#define SYS_mmap SYS_mmap2
#endif

Expand Down