Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ class MinMaxlocElementalConversion : public mlir::OpRewritePattern<Op> {
const llvm::fltSemantics &sem = ty.getFloatSemantics();
return builder.createRealConstant(
loc, elementType,
llvm::APFloat::getLargest(sem, /*Negative=*/!isMax));
llvm::APFloat::getLargest(sem, /*Negative=*/isMax));
}
unsigned bits = elementType.getIntOrFloatBitWidth();
int64_t limitInt =
Expand Down
1 change: 1 addition & 0 deletions flang/test/HLFIR/maxloc-elemental.fir
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
return
}
// CHECK-LABEL: _QPtest_float
// CHECK: %cst = arith.constant -3.40282347E+38 : f32
// CHECK: %[[V11:.*]] = fir.do_loop %arg3 = %c0 to %[[V10:.*]] step %c1 iter_args(%arg4 = %cst) -> (f32) {
// CHECK-NEXT: %[[V14:.*]] = arith.addi %arg3, %c1 : index
// CHECK-NEXT: %[[V15:.*]] = hlfir.designate %[[V1:.*]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
Expand Down
1 change: 1 addition & 0 deletions flang/test/HLFIR/minloc-elemental.fir
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ func.func @_QPtest_float(%arg0: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a
return
}
// CHECK-LABEL: _QPtest_float
// CHECK: %cst = arith.constant 3.40282347E+38 : f32
// CHECK: %[[V11:.*]] = fir.do_loop %arg3 = %c0 to %[[V10:.*]] step %c1 iter_args(%arg4 = %cst) -> (f32) {
// CHECK-NEXT: %[[V14:.*]] = arith.addi %arg3, %c1 : index
// CHECK-NEXT: %[[V15:.*]] = hlfir.designate %[[V1:.*]]#0 (%[[V14]]) : (!fir.box<!fir.array<?xf32>>, index) -> !fir.ref<f32>
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
"`1203 <https://wg21.link/LWG1203>`__","More useful rvalue stream insertion","Prague","|Complete|","12.0"
"`2859 <https://wg21.link/LWG2859>`__","Definition of *reachable* in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object","Prague","",""
"`3018 <https://wg21.link/LWG3018>`__","``shared_ptr``\ of function type","Prague","",""
"`3050 <https://wg21.link/LWG3050>`__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","","","|chrono|"
"`3050 <https://wg21.link/LWG3050>`__","Conversion specification problem in ``chrono::duration``\ constructor","Prague","|Complete|","19.0","|chrono|"
"`3141 <https://wg21.link/LWG3141>`__","``CopyConstructible``\ doesn't preserve source values","Prague","|Nothing to do|",""
"`3150 <https://wg21.link/LWG3150>`__","``UniformRandomBitGenerator``\ should validate ``min``\ and ``max``\ ","Prague","|Complete|","13.0","|ranges|"
"`3175 <https://wg21.link/LWG3175>`__","The ``CommonReference``\ requirement of concept ``SwappableWith``\ is not satisfied in the example","Prague","|Complete|","13.0"
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/__chrono/duration.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
__enable_if_t<is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
typedef typename common_type<_Rep1, _Rep2>::type _Cr;
Expand All @@ -423,7 +423,7 @@ operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<is_convertible<_Rep1, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
__enable_if_t<is_convertible<const _Rep1&, typename common_type<_Rep1, _Rep2>::type>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) {
return __d * __s;
Expand All @@ -435,7 +435,7 @@ template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<!__is_duration<_Rep2>::value &&
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
Expand All @@ -457,7 +457,7 @@ template <class _Rep1,
class _Period,
class _Rep2,
__enable_if_t<!__is_duration<_Rep2>::value &&
is_convertible<_Rep2, typename common_type<_Rep1, _Rep2>::type>::value,
is_convertible<const _Rep2&, typename common_type<_Rep1, _Rep2>::type>::value,
int> = 0>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration<typename common_type<_Rep1, _Rep2>::type, _Period>
operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/chrono
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public:
constexpr explicit duration(const Rep2& r,
typename enable_if
<
is_convertible<Rep2, rep>::value &&
is_convertible<const Rep2&, rep>::value &&
(treat_as_floating_point<rep>::value ||
!treat_as_floating_point<rep>::value && !treat_as_floating_point<Rep2>::value)
>::type* = 0);
Expand Down
14 changes: 7 additions & 7 deletions libcxx/include/print
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace std {
*/

#include <__assert> // all public C++ headers provide the assertion handler
#include <__availability>
#include <__concepts/same_as.h>
#include <__config>
#include <__system_error/system_error.h>
Expand All @@ -43,10 +44,6 @@ namespace std {
#include <string_view>
#include <version>

#if __has_include(<unistd.h>)
# include <unistd.h>
#endif

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
Expand All @@ -68,7 +65,8 @@ _LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream);
// Note the function is only implemented on the Windows platform.
_LIBCPP_EXPORTED_FROM_ABI void __write_to_windows_console(FILE* __stream, wstring_view __view);
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS

#elif __has_include(<unistd.h>)
_LIBCPP_EXPORTED_FROM_ABI bool __is_posix_terminal(FILE* __stream);
#endif // _LIBCPP_WIN32API

#if _LIBCPP_STD_VER >= 23
Expand Down Expand Up @@ -195,15 +193,17 @@ inline constexpr bool __use_unicode_execution_charset = _MSVC_EXECUTION_CHARACTE
inline constexpr bool __use_unicode_execution_charset = true;
# endif

_LIBCPP_HIDE_FROM_ABI inline bool __is_terminal(FILE* __stream) {
_LIBCPP_HIDE_FROM_ABI inline bool __is_terminal([[maybe_unused]] FILE* __stream) {
// The macro _LIBCPP_TESTING_PRINT_IS_TERMINAL is used to change
// the behavior in the test. This is not part of the public API.
# ifdef _LIBCPP_TESTING_PRINT_IS_TERMINAL
return _LIBCPP_TESTING_PRINT_IS_TERMINAL(__stream);
# elif _LIBCPP_AVAILABILITY_HAS_PRINT == 0
return false;
# elif defined(_LIBCPP_WIN32API)
return std::__is_windows_terminal(__stream);
# elif __has_include(<unistd.h>)
return isatty(fileno(__stream));
return std::__is_posix_terminal(__stream);
# else
# error "Provide a way to determine whether a FILE* is a terminal"
# endif
Expand Down
8 changes: 8 additions & 0 deletions libcxx/lib/abi/CHANGELOG.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ New entries should be added directly below the "Version" header.
Version 18.0
------------

* [libc++] Moves is_terminal to the dylib

The patch moves the POSIX implementation of is_terminal to the dylib. This is
needed to avoid using <unistd.h> in public headers.

All platforms
Symbol added: _ZNSt6__ndk119__is_posix_terminalEP7__sFILE

* [libc++abi] Implement __cxa_init_primary_exception and use it to optimize std::make_exception_ptr (#65534)

This patch implements __cxa_init_primary_exception, an extension to the Itanium C++ ABI.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,7 @@
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__is_posix_terminalEP7__sFILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__is_posix_terminalEP7__sFILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex8try_lockEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__is_posix_terminalEP4FILE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base11lock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex8try_lockEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__is_posix_terminalEP4FILE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base11lock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1495,6 +1495,7 @@
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__is_posix_terminalEP7__sFILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__is_posix_terminalEP7__sFILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,7 @@
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__is_posix_terminalEP7__sFILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,7 @@
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__is_posix_terminalEP8_IO_FILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,7 @@
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex8try_lockEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutexC2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__is_posix_terminalEP8_IO_FILE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__119__shared_mutex_base15try_lock_sharedEv', 'type': 'FUNC'}
Expand Down
10 changes: 5 additions & 5 deletions libcxx/modules/std.compat.cppm.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ module;

// *** Headers not yet available ***
//
// This validation is mainly to aid libc++ developers to add modules for new
// headers. On Windows the Windows SDK can be in the include path. This SDK
// contains the MSVC STL headers. This may give false positives when MSVC STL
// provides a header libc++ has not implemented yet. Therefore this validation
// is not done on Windows.
// This validation is mainly to catch when a new header is added but adding the
// corresponding .inc file is forgotten. However, the check based on __has_include
// alone doesn't work on Windows because the Windows SDK is on the include path,
// and that means the MSVC STL headers can be found as well, tricking __has_include
// into thinking that libc++ provides the header.
//
#ifndef _WIN32
# if __has_include(<debugging>)
Expand Down
10 changes: 5 additions & 5 deletions libcxx/modules/std.cppm.in
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ module;

// *** Headers not yet available ***
//
// This validation is mainly to aid libc++ developers to add modules for new
// headers. On Windows the Windows SDK can be in the include path. This SDK
// contains the MSVC STL headers. This may give false positives when MSVC STL
// provides a header libc++ has not implemented yet. Therefore this validation
// is not done on Windows.
// This validation is mainly to catch when a new header is added but adding the
// corresponding .inc file is forgotten. However, the check based on __has_include
// alone doesn't work on Windows because the Windows SDK is on the include path,
// and that means the MSVC STL headers can be found as well, tricking __has_include
// into thinking that libc++ provides the header.
//
#ifndef _WIN32
# if __has_include(<debugging>)
Expand Down
4 changes: 3 additions & 1 deletion libcxx/modules/std/ostream.inc
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ export namespace std {
using std::println;

using std::vprint_nonunicode;
# ifndef _LIBCPP_HAS_NO_UNICODE
using std::vprint_unicode;
# endif // _LIBCPP_STD_VER >= 23
# endif // _LIBCPP_HAS_NO_UNICODE
# endif // _LIBCPP_STD_VER >= 23

#endif // _LIBCPP_HAS_NO_LOCALIZATION
} // namespace std
25 changes: 16 additions & 9 deletions libcxx/src/print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,26 @@

#include <__config>

#if defined(_LIBCPP_WIN32API)
#include <cstdlib>
#include <print>

#include <__system_error/system_error.h>

# include <cstdlib>
# include <print>
#include "filesystem/error.h"

#if defined(_LIBCPP_WIN32API)
# define WIN32_LEAN_AND_MEAN
# define NOMINMAX
# include <io.h>
# include <windows.h>

# include <__system_error/system_error.h>

# include "filesystem/error.h"
#elif __has_include(<unistd.h>)
# include <unistd.h>
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if defined(_LIBCPP_WIN32API)

_LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream) {
// Note the Standard does this in one call, but it's unclear whether
// an invalid handle is allowed when calling GetConsoleMode.
Expand Down Expand Up @@ -52,6 +56,9 @@ __write_to_windows_console([[maybe_unused]] FILE* __stream, [[maybe_unused]] wst
}
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS

_LIBCPP_END_NAMESPACE_STD
#elif __has_include(<unistd.h>) // !_LIBCPP_WIN32API

#endif // !_LIBCPP_WIN32API
_LIBCPP_EXPORTED_FROM_ABI bool __is_posix_terminal(FILE* __stream) { return isatty(fileno(__stream)); }
#endif

_LIBCPP_END_NAMESPACE_STD
23 changes: 23 additions & 0 deletions libcxx/test/std/time/rep.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define REP_H

#include "test_macros.h"
#include <type_traits>

class Rep
{
Expand All @@ -29,6 +30,28 @@ class Rep

struct NotARep {};

#if TEST_STD_VER >= 11
// Several duration operators take a Rep parameter. Before LWG3050 this
// parameter was constrained to be convertible from a non-const object,
// but the code always uses a const object. So the function was SFINAE'd
// away for this type. LWG3050 fixes the constraint to use a const
// object.
struct RepConstConvertibleLWG3050 {
operator long() = delete;
operator long() const { return 2; }
};
namespace std {
template <>
struct common_type<RepConstConvertibleLWG3050, int> {
using type = long;
};
template <>
struct common_type<int, RepConstConvertibleLWG3050> {
using type = long;
};
} // namespace std
#endif // TEST_STD_VER >= 11

// std::chrono:::duration has only '*', '/' and '%' taking a "Rep" parameter

// Multiplication is commutative, division is not.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "test_macros.h"
#include "truncate_fp.h"
#include "../../rep.h"

int main(int, char**)
{
Expand Down Expand Up @@ -65,7 +66,17 @@ int main(int, char**)
constexpr std::chrono::duration<double, std::ratio<3, 5> > s2(5);
static_assert(s1 / s2 == 20./3, "");
}
#endif
{
std::chrono::duration<int> d(5);
RepConstConvertibleLWG3050 x;

{
auto r = d / x;
assert(r.count() == 2);
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
}
}
#endif // TEST_STD_VER >= 11

return 0;
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <chrono>
#include <cassert>
#include <ratio>
#include "../../rep.h"

#include "test_macros.h"

Expand Down Expand Up @@ -60,7 +61,17 @@ int main(int, char**)
constexpr std::chrono::duration<int, std::ratio<1, 15> > r = s1 % s2;
static_assert(r.count() == 24, "");
}
#endif
{
std::chrono::duration<int> d(5);
RepConstConvertibleLWG3050 x;

{
auto r = d % x;
assert(r.count() == 1);
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
}
}
#endif // TEST_STD_VER >= 11

return 0;
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,27 @@
#include "test_macros.h"
#include "../../rep.h"

int main(int, char**)
{
{
int main(int, char**) {
{
std::chrono::nanoseconds ns(3);
ns = ns * 5;
assert(ns.count() == 15);
ns = 6 * ns;
assert(ns.count() == 90);
}
}

#if TEST_STD_VER >= 11
{
{
constexpr std::chrono::nanoseconds ns(3);
constexpr std::chrono::nanoseconds ns2 = ns * 5;
static_assert(ns2.count() == 15, "");
constexpr std::chrono::nanoseconds ns3 = 6 * ns;
static_assert(ns3.count() == 18, "");
}
}
#endif

#if TEST_STD_VER >= 11
{ // This is related to PR#41130
{ // This is related to PR#41130
typedef std::chrono::nanoseconds Duration;
Duration d(5);
NotARep n;
Expand All @@ -57,8 +56,23 @@ int main(int, char**)
assert(d.count() == 5);
d = n * d;
assert(d.count() == 5);
}
{
std::chrono::duration<int> d(8);
RepConstConvertibleLWG3050 x;

{
auto r = d * x;
assert(r.count() == 16);
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
}
#endif
{
auto r = x * d;
assert(r.count() == 16);
ASSERT_SAME_TYPE(std::chrono::duration<long>, decltype(r));
}
}
#endif // TEST_STD_VER >= 11

return 0;
}
2 changes: 1 addition & 1 deletion libcxx/utils/generate_libcxx_cppm_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def write_file(module):
"""
// *** Headers not yet available ***
//
// This validation is mainly to catch when a new header is added but adding the
// This validation is mainly to catch when a new header is added but adding the
// corresponding .inc file is forgotten. However, the check based on __has_include
// alone doesn't work on Windows because the Windows SDK is on the include path,
// and that means the MSVC STL headers can be found as well, tricking __has_include
Expand Down
2 changes: 1 addition & 1 deletion lld/test/COFF/lto-cache-errors.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user
;; Not supported on windows since we use permissions to deny the creation
; UNSUPPORTED: system-windows

Expand Down
2 changes: 1 addition & 1 deletion lld/test/COFF/thinlto-emit-imports.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user

; Generate summary sections and test lld handling.
; RUN: opt -module-summary %s -o %t1.obj
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/resolution-err.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
; UNSUPPORTED: system-windows
; REQUIRES: shell
; REQUIRES: shell, non-root-user
; RUN: llvm-as %s -o %t.bc
; RUN: touch %t.resolution.txt
; RUN: chmod u-w %t.resolution.txt
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/thinlto-cant-write-index.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user

; Basic ThinLTO tests.
; RUN: opt -module-summary %s -o %t1.o
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/lto/thinlto-emit-imports.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user
;; Test a few properties not tested by thinlto-index-only.ll

; RUN: opt -module-summary %s -o %t1.o
Expand Down
2 changes: 1 addition & 1 deletion lld/test/MachO/invalid/invalid-lto-object-path.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user

;; Creating read-only directories with `chmod 400` isn't supported on Windows
; UNSUPPORTED: system-windows
Expand Down
2 changes: 1 addition & 1 deletion lld/test/MachO/thinlto-emit-imports.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86
; REQUIRES: x86, non-root-user
; RUN: rm -rf %t; split-file %s %t

; Generate summary sections and test lld handling.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class ProcessFreeBSDKernelFVC : public ProcessFreeBSDKernel {
class ProcessFreeBSDKernelKVM : public ProcessFreeBSDKernel {
public:
ProcessFreeBSDKernelKVM(lldb::TargetSP target_sp, lldb::ListenerSP listener,
kvm_t *fvc);
kvm_t *fvc, const FileSpec &core_file);

~ProcessFreeBSDKernelKVM();

Expand Down
41 changes: 41 additions & 0 deletions llvm/include/llvm/Object/COFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,47 @@ class SectionStrippedError
SectionStrippedError() { setErrorCode(object_error::section_stripped); }
};

inline std::optional<std::string>
getArm64ECMangledFunctionName(StringRef Name) {
bool IsCppFn = Name[0] == '?';
if (IsCppFn && Name.find("$$h") != std::string::npos)
return std::nullopt;
if (!IsCppFn && Name[0] == '#')
return std::nullopt;

StringRef Prefix = "$$h";
size_t InsertIdx = 0;
if (IsCppFn) {
InsertIdx = Name.find("@@");
size_t ThreeAtSignsIdx = Name.find("@@@");
if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) {
InsertIdx += 2;
} else {
InsertIdx = Name.find("@");
if (InsertIdx != std::string::npos)
InsertIdx++;
}
} else {
Prefix = "#";
}

return std::optional<std::string>(
(Name.substr(0, InsertIdx) + Prefix + Name.substr(InsertIdx)).str());
}

inline std::optional<std::string>
getArm64ECDemangledFunctionName(StringRef Name) {
if (Name[0] == '#')
return std::string(Name.substr(1));
if (Name[0] != '?')
return std::nullopt;

std::pair<StringRef, StringRef> Pair = Name.split("$$h");
if (Pair.second.empty())
return std::nullopt;
return (Pair.first + Pair.second).str();
}

} // end namespace object

} // end namespace llvm
Expand Down
28 changes: 25 additions & 3 deletions llvm/include/llvm/Object/COFFImportFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ namespace llvm {
namespace object {

class COFFImportFile : public SymbolicFile {
private:
enum SymbolIndex { ImpSymbol, ThunkSymbol, ECAuxSymbol, ECThunkSymbol };

public:
COFFImportFile(MemoryBufferRef Source)
: SymbolicFile(ID_COFFImportFile, Source) {}
Expand All @@ -36,9 +39,23 @@ class COFFImportFile : public SymbolicFile {
void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; }

Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override {
if (Symb.p == 0)
switch (Symb.p) {
case ImpSymbol:
OS << "__imp_";
OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header));
break;
case ECAuxSymbol:
OS << "__imp_aux_";
break;
}
const char *Name = Data.getBufferStart() + sizeof(coff_import_header);
if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) {
if (std::optional<std::string> DemangledName =
getArm64ECDemangledFunctionName(Name)) {
OS << StringRef(*DemangledName);
return Error::success();
}
}
OS << StringRef(Name);
return Error::success();
}

Expand All @@ -52,7 +69,12 @@ class COFFImportFile : public SymbolicFile {

basic_symbol_iterator symbol_end() const override {
DataRefImpl Symb;
Symb.p = isData() ? 1 : 2;
if (isData())
Symb.p = ImpSymbol + 1;
else if (COFF::isArm64EC(getMachine()))
Symb.p = ECThunkSymbol + 1;
else
Symb.p = ThunkSymbol + 1;
return BasicSymbolRef(Symb, this);
}

Expand Down
24 changes: 24 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/JumpTableToSwitch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===- JumpTableToSwitch.h - ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_SCALAR_JUMP_TABLE_TO_SWITCH_H
#define LLVM_TRANSFORMS_SCALAR_JUMP_TABLE_TO_SWITCH_H

#include "llvm/IR/PassManager.h"

namespace llvm {

class Function;

struct JumpTableToSwitchPass : PassInfoMixin<JumpTableToSwitchPass> {
/// Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
} // end namespace llvm

#endif // LLVM_TRANSFORMS_SCALAR_JUMP_TABLE_TO_SWITCH_H
15 changes: 15 additions & 0 deletions llvm/lib/Object/COFFImportFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,21 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
}

// On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
if (ImportType == IMPORT_CODE && isArm64EC(Machine)) {
if (std::optional<std::string> MangledName =
getArm64ECMangledFunctionName(Name)) {
if (ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName.swap(Name);
}
Name = std::move(*MangledName);
} else if (ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
}
}

Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
NameType, ExportName, Machine));
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
#include "llvm/Transforms/Scalar/InferAddressSpaces.h"
#include "llvm/Transforms/Scalar/InferAlignment.h"
#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
#include "llvm/Transforms/Scalar/JumpTableToSwitch.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Scalar/LICM.h"
#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#include "llvm/Transforms/Scalar/IndVarSimplify.h"
#include "llvm/Transforms/Scalar/InferAlignment.h"
#include "llvm/Transforms/Scalar/InstSimplifyPass.h"
#include "llvm/Transforms/Scalar/JumpTableToSwitch.h"
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Scalar/LICM.h"
#include "llvm/Transforms/Scalar/LoopDeletion.h"
Expand Down Expand Up @@ -237,6 +238,10 @@ static cl::opt<bool>
EnableGVNSink("enable-gvn-sink",
cl::desc("Enable the GVN sinking pass (default = off)"));

static cl::opt<bool> EnableJumpTableToSwitch(
"enable-jump-table-to-switch",
cl::desc("Enable JumpTableToSwitch pass (default = off)"));

// This option is used in simplifying testing SampleFDO optimizations for
// profile loading.
static cl::opt<bool>
Expand Down Expand Up @@ -559,6 +564,10 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
FPM.addPass(JumpThreadingPass());
FPM.addPass(CorrelatedValuePropagationPass());

// Jump table to switch conversion.
if (EnableJumpTableToSwitch)
FPM.addPass(JumpTableToSwitchPass());

FPM.addPass(
SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true)));
FPM.addPass(InstCombinePass());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ FUNCTION_PASS("interleaved-load-combine", InterleavedLoadCombinePass(TM))
FUNCTION_PASS("invalidate<all>", InvalidateAllAnalysesPass())
FUNCTION_PASS("irce", IRCEPass())
FUNCTION_PASS("jump-threading", JumpThreadingPass())
FUNCTION_PASS("jump-table-to-switch", JumpTableToSwitchPass());
FUNCTION_PASS("kcfi", KCFIPass())
FUNCTION_PASS("lcssa", LCSSAPass())
FUNCTION_PASS("libcalls-shrinkwrap", LibCallsShrinkWrapPass())
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/InitializePasses.h"
#include "llvm/Object/COFF.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/TargetParser/Triple.h"

using namespace llvm;
using namespace llvm::object;

using OperandBundleDef = OperandBundleDefT<Value *>;

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64MCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
using namespace llvm::object;

extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration;

Expand Down
28 changes: 0 additions & 28 deletions llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,34 +248,6 @@ static inline bool atomicBarrierDroppedOnZero(unsigned Opcode) {
return false;
}

static inline std::optional<std::string>
getArm64ECMangledFunctionName(std::string Name) {
bool IsCppFn = Name[0] == '?';
if (IsCppFn && Name.find("$$h") != std::string::npos)
return std::nullopt;
if (!IsCppFn && Name[0] == '#')
return std::nullopt;

StringRef Prefix = "$$h";
size_t InsertIdx = 0;
if (IsCppFn) {
InsertIdx = Name.find("@@");
size_t ThreeAtSignsIdx = Name.find("@@@");
if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) {
InsertIdx += 2;
} else {
InsertIdx = Name.find("@");
if (InsertIdx != std::string::npos)
InsertIdx++;
}
} else {
Prefix = "#";
}

Name.insert(Name.begin() + InsertIdx, Prefix.begin(), Prefix.end());
return std::optional<std::string>(Name);
}

namespace AArch64CC {

// The CondCodes constants map directly to the 4-bit encoding of the condition
Expand Down
88 changes: 87 additions & 1 deletion llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
//===----------------------------------------------------------------------===//

#include "RISCVLegalizerInfo.h"
#include "MCTargetDesc/RISCVMatInt.h"
#include "RISCVMachineFunctionInfo.h"
#include "RISCVSubtarget.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/ValueTypes.h"
Expand Down Expand Up @@ -182,7 +185,13 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
CTPOPActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
}

getActionDefinitionsBuilder({G_CONSTANT, G_IMPLICIT_DEF})
auto &ConstantActions = getActionDefinitionsBuilder(G_CONSTANT);
ConstantActions.legalFor({s32, p0});
if (ST.is64Bit())
ConstantActions.customFor({s64});
ConstantActions.widenScalarToNextPow2(0).clampScalar(0, s32, sXLen);

getActionDefinitionsBuilder(G_IMPLICIT_DEF)
.legalFor({s32, sXLen, p0})
.widenScalarToNextPow2(0)
.clampScalar(0, s32, sXLen);
Expand Down Expand Up @@ -451,17 +460,94 @@ bool RISCVLegalizerInfo::legalizeVAStart(MachineInstr &MI,
return true;
}

bool RISCVLegalizerInfo::shouldBeInConstantPool(APInt APImm,
bool ShouldOptForSize) const {
assert(APImm.getBitWidth() == 32 || APImm.getBitWidth() == 64);
int64_t Imm = APImm.getSExtValue();
// All simm32 constants should be handled by isel.
// NOTE: The getMaxBuildIntsCost call below should return a value >= 2 making
// this check redundant, but small immediates are common so this check
// should have better compile time.
if (isInt<32>(Imm))
return false;

// We only need to cost the immediate, if constant pool lowering is enabled.
if (!STI.useConstantPoolForLargeInts())
return false;

RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Imm, STI);
if (Seq.size() <= STI.getMaxBuildIntsCost())
return false;

// Optimizations below are disabled for opt size. If we're optimizing for
// size, use a constant pool.
if (ShouldOptForSize)
return true;
//
// Special case. See if we can build the constant as (ADD (SLLI X, C), X) do
// that if it will avoid a constant pool.
// It will require an extra temporary register though.
// If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
// low and high 32 bits are the same and bit 31 and 63 are set.
unsigned ShiftAmt, AddOpc;
RISCVMatInt::InstSeq SeqLo =
RISCVMatInt::generateTwoRegInstSeq(Imm, STI, ShiftAmt, AddOpc);
return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost());
}

// TODO: This is almost the same as LegalizerHelper::lowerFConstant and is
// target-independent. Should we move this to LegalizeHelper?
bool RISCVLegalizerInfo::emitLoadFromConstantPool(
Register DstReg, const Constant *ConstVal,
MachineIRBuilder &MIRBuilder) const {
MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
MachineFunction &MF = MIRBuilder.getMF();
const DataLayout &DL = MIRBuilder.getDataLayout();
LLVMContext &Ctx = MF.getFunction().getContext();
unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
LLT AddrPtrTy = LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
LLT DstLLT = MRI.getType(DstReg);

Align Alignment(DL.getABITypeAlign(getTypeForLLT(DstLLT, Ctx)));

auto Addr = MIRBuilder.buildConstantPool(
AddrPtrTy,
MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment));

MachineMemOperand *MMO =
MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
MachineMemOperand::MOLoad, DstLLT, Alignment);

MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
return true;
}

bool RISCVLegalizerInfo::legalizeCustom(
LegalizerHelper &Helper, MachineInstr &MI,
LostDebugLocObserver &LocObserver) const {
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
GISelChangeObserver &Observer = Helper.Observer;
MachineFunction &MF = *MI.getParent()->getParent();
switch (MI.getOpcode()) {
default:
// No idea what to do.
return false;
case TargetOpcode::G_ABS:
return Helper.lowerAbsToMaxNeg(MI);
// TODO: G_FCONSTANT
case TargetOpcode::G_CONSTANT: {
const Function &F = MF.getFunction();
// TODO: if PSI and BFI are present, add " ||
// llvm::shouldOptForSize(*CurMBB, PSI, BFI)".
bool ShouldOptForSize = F.hasOptSize() || F.hasMinSize();
const ConstantInt *ConstVal = MI.getOperand(1).getCImm();
if (!shouldBeInConstantPool(ConstVal->getValue(), ShouldOptForSize))
return true;
emitLoadFromConstantPool(MI.getOperand(0).getReg(),
MI.getOperand(1).getCImm(), MIRBuilder);
MI.eraseFromParent();
return true;
}
case TargetOpcode::G_SHL:
case TargetOpcode::G_ASHR:
case TargetOpcode::G_LSHR:
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define LLVM_LIB_TARGET_RISCV_RISCVMACHINELEGALIZER_H

#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/Register.h"

namespace llvm {

Expand All @@ -36,6 +37,9 @@ class RISCVLegalizerInfo : public LegalizerInfo {
MachineInstr &MI) const override;

private:
bool shouldBeInConstantPool(APInt APImm, bool ShouldOptForSize) const;
bool emitLoadFromConstantPool(Register DstReg, const Constant *CPVal,
MachineIRBuilder &MIRBuilder) const;
bool legalizeShlAshrLshr(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
GISelChangeObserver &Observer) const;

Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1227,3 +1227,8 @@ def FeatureTaggedGlobals : SubtargetFeature<"tagged-globals",
"AllowTaggedGlobals",
"true", "Use an instruction sequence for taking the address of a global "
"that allows a memory tag in the upper address bits">;

def FeatureForcedSWShadowStack : SubtargetFeature<
"forced-sw-shadow-stack", "HasForcedSWShadowStack", "true",
"Implement shadow stack with software.">;
def HasForcedSWShadowStack : Predicate<"Subtarget->hasForcedSWShadowStack()">;
22 changes: 16 additions & 6 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ static Align getABIStackAlignment(RISCVABI::ABI ABI) {
}

RISCVFrameLowering::RISCVFrameLowering(const RISCVSubtarget &STI)
: TargetFrameLowering(StackGrowsDown,
getABIStackAlignment(STI.getTargetABI()),
/*LocalAreaOffset=*/0,
/*TransientStackAlignment=*/Align(16)),
: TargetFrameLowering(
StackGrowsDown, getABIStackAlignment(STI.getTargetABI()),
/*LocalAreaOffset=*/0,
/*TransientStackAlignment=*/getABIStackAlignment(STI.getTargetABI())),
STI(STI) {}

static const MCPhysReg AllPopRegs[] = {
Expand All @@ -66,9 +66,14 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
CSI, [&](CalleeSavedInfo &CSR) { return CSR.getReg() == RAReg; }))
return;

const RISCVInstrInfo *TII = STI.getInstrInfo();
if (!STI.hasForcedSWShadowStack() && STI.hasStdExtZicfiss()) {
BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH)).addReg(RAReg);
return;
}

Register SCSPReg = RISCVABI::getSCSPReg();

const RISCVInstrInfo *TII = STI.getInstrInfo();
bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
int64_t SlotSize = STI.getXLen() / 8;
// Store return address to shadow call stack
Expand Down Expand Up @@ -121,9 +126,14 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
CSI, [&](CalleeSavedInfo &CSR) { return CSR.getReg() == RAReg; }))
return;

const RISCVInstrInfo *TII = STI.getInstrInfo();
if (!STI.hasForcedSWShadowStack() && STI.hasStdExtZicfiss()) {
BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK)).addReg(RAReg);
return;
}

Register SCSPReg = RISCVABI::getSCSPReg();

const RISCVInstrInfo *TII = STI.getInstrInfo();
bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit);
int64_t SlotSize = STI.getXLen() / 8;
// Load return address from shadow call stack
Expand Down
30 changes: 0 additions & 30 deletions llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,33 +1709,6 @@ static Instruction *foldFDivPowDivisor(BinaryOperator &I,
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
}

/// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv
/// instruction.
static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
InstCombiner::BuilderTy &Builder) {
// X / sqrt(Y / Z) --> X * sqrt(Z / Y)
if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
return nullptr;
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
auto *II = dyn_cast<IntrinsicInst>(Op1);
if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
!II->hasAllowReassoc() || !II->hasAllowReciprocal())
return nullptr;

Value *Y, *Z;
auto *DivOp = dyn_cast<Instruction>(II->getOperand(0));
if (!DivOp || !DivOp->hasAllowReassoc() || !I.hasAllowReciprocal() ||
!DivOp->hasOneUse())
return nullptr;
if (match(DivOp, m_FDiv(m_Value(Y), m_Value(Z)))) {
Value *SwapDiv = Builder.CreateFDivFMF(Z, Y, DivOp);
Value *NewSqrt =
Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), SwapDiv, II);
return BinaryOperator::CreateFMulFMF(Op0, NewSqrt, &I);
}
return nullptr;
}

Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
Module *M = I.getModule();

Expand Down Expand Up @@ -1843,9 +1816,6 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
return Mul;

if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder))
return Mul;

// pow(X, Y) / X --> pow(X, Y-1)
if (I.hasAllowReassoc() &&
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Scalar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_llvm_component_library(LLVMScalarOpts
InferAlignment.cpp
InstSimplifyPass.cpp
JumpThreading.cpp
JumpTableToSwitch.cpp
LICM.cpp
LoopAccessAnalysisPrinter.cpp
LoopBoundSplit.cpp
Expand Down
190 changes: 190 additions & 0 deletions llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
//===- JumpTableToSwitch.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/JumpTableToSwitch.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

using namespace llvm;

static cl::opt<unsigned>
JumpTableSizeThreshold("jump-table-to-switch-size-threshold", cl::Hidden,
cl::desc("Only split jump tables with size less or "
"equal than JumpTableSizeThreshold."),
cl::init(10));

// TODO: Consider adding a cost model for profitability analysis of this
// transformation. Currently we replace a jump table with a switch if all the
// functions in the jump table are smaller than the provided threshold.
static cl::opt<unsigned> FunctionSizeThreshold(
"jump-table-to-switch-function-size-threshold", cl::Hidden,
cl::desc("Only split jump tables containing functions whose sizes are less "
"or equal than this threshold."),
cl::init(50));

#define DEBUG_TYPE "jump-table-to-switch"

namespace {
struct JumpTableTy {
Value *Index;
SmallVector<Function *, 10> Funcs;
};
} // anonymous namespace

static std::optional<JumpTableTy> parseJumpTable(GetElementPtrInst *GEP,
PointerType *PtrTy) {
Constant *Ptr = dyn_cast<Constant>(GEP->getPointerOperand());
if (!Ptr)
return std::nullopt;

GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr);
if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer())
return std::nullopt;

Function &F = *GEP->getParent()->getParent();
const DataLayout &DL = F.getParent()->getDataLayout();
const unsigned BitWidth =
DL.getIndexSizeInBits(GEP->getPointerAddressSpace());
MapVector<Value *, APInt> VariableOffsets;
APInt ConstantOffset(BitWidth, 0);
if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))
return std::nullopt;
if (VariableOffsets.size() != 1)
return std::nullopt;
// TODO: consider supporting more general patterns
if (!ConstantOffset.isZero())
return std::nullopt;
APInt StrideBytes = VariableOffsets.front().second;
const uint64_t JumpTableSizeBytes = DL.getTypeAllocSize(GV->getValueType());
if (JumpTableSizeBytes % StrideBytes.getZExtValue() != 0)
return std::nullopt;
const uint64_t N = JumpTableSizeBytes / StrideBytes.getZExtValue();
if (N > JumpTableSizeThreshold)
return std::nullopt;

JumpTableTy JumpTable;
JumpTable.Index = VariableOffsets.front().first;
JumpTable.Funcs.reserve(N);
for (uint64_t Index = 0; Index < N; ++Index) {
// ConstantOffset is zero.
APInt Offset = Index * StrideBytes;
Constant *C =
ConstantFoldLoadFromConst(GV->getInitializer(), PtrTy, Offset, DL);
auto *Func = dyn_cast_or_null<Function>(C);
if (!Func || Func->isDeclaration() ||
Func->getInstructionCount() > FunctionSizeThreshold)
return std::nullopt;
JumpTable.Funcs.push_back(Func);
}
return JumpTable;
}

static BasicBlock *expandToSwitch(CallBase *CB, const JumpTableTy &JT,
DomTreeUpdater &DTU,
OptimizationRemarkEmitter &ORE) {
const bool IsVoid = CB->getType() == Type::getVoidTy(CB->getContext());

SmallVector<DominatorTree::UpdateType, 8> DTUpdates;
BasicBlock *BB = CB->getParent();
BasicBlock *Tail = SplitBlock(BB, CB, &DTU, nullptr, nullptr,
BB->getName() + Twine(".tail"));
DTUpdates.push_back({DominatorTree::Delete, BB, Tail});
BB->getTerminator()->eraseFromParent();

Function &F = *BB->getParent();
BasicBlock *BBUnreachable = BasicBlock::Create(
F.getContext(), "default.switch.case.unreachable", &F, Tail);
IRBuilder<> BuilderUnreachable(BBUnreachable);
BuilderUnreachable.CreateUnreachable();

IRBuilder<> Builder(BB);
SwitchInst *Switch = Builder.CreateSwitch(JT.Index, BBUnreachable);
DTUpdates.push_back({DominatorTree::Insert, BB, BBUnreachable});

IRBuilder<> BuilderTail(CB);
PHINode *PHI =
IsVoid ? nullptr : BuilderTail.CreatePHI(CB->getType(), JT.Funcs.size());

for (auto [Index, Func] : llvm::enumerate(JT.Funcs)) {
BasicBlock *B = BasicBlock::Create(Func->getContext(),
"call." + Twine(Index), &F, Tail);
DTUpdates.push_back({DominatorTree::Insert, BB, B});
DTUpdates.push_back({DominatorTree::Insert, B, Tail});

CallBase *Call = cast<CallBase>(CB->clone());
Call->setCalledFunction(Func);
Call->insertInto(B, B->end());
Switch->addCase(
cast<ConstantInt>(ConstantInt::get(JT.Index->getType(), Index)), B);
BranchInst::Create(Tail, B);
if (PHI)
PHI->addIncoming(Call, B);
}
DTU.applyUpdates(DTUpdates);
ORE.emit([&]() {
return OptimizationRemark(DEBUG_TYPE, "ReplacedJumpTableWithSwitch", CB)
<< "expanded indirect call into switch";
});
if (PHI)
CB->replaceAllUsesWith(PHI);
CB->eraseFromParent();
return Tail;
}

PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
FunctionAnalysisManager &AM) {
OptimizationRemarkEmitter &ORE =
AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
DominatorTree *DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
PostDominatorTree *PDT = AM.getCachedResult<PostDominatorTreeAnalysis>(F);
DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
bool Changed = false;
for (BasicBlock &BB : make_early_inc_range(F)) {
BasicBlock *CurrentBB = &BB;
while (CurrentBB) {
BasicBlock *SplittedOutTail = nullptr;
for (Instruction &I : make_early_inc_range(*CurrentBB)) {
auto *Call = dyn_cast<CallInst>(&I);
if (!Call || Call->getCalledFunction() || Call->isMustTailCall())
continue;
auto *L = dyn_cast<LoadInst>(Call->getCalledOperand());
// Skip atomic or volatile loads.
if (!L || !L->isSimple())
continue;
auto *GEP = dyn_cast<GetElementPtrInst>(L->getPointerOperand());
if (!GEP)
continue;
auto *PtrTy = dyn_cast<PointerType>(L->getType());
assert(PtrTy && "call operand must be a pointer");
std::optional<JumpTableTy> JumpTable = parseJumpTable(GEP, PtrTy);
if (!JumpTable)
continue;
SplittedOutTail = expandToSwitch(Call, *JumpTable, DTU, ORE);
Changed = true;
break;
}
CurrentBB = SplittedOutTail ? SplittedOutTail : nullptr;
}
}

if (!Changed)
return PreservedAnalyses::all();

PreservedAnalyses PA;
if (DT)
PA.preserve<DominatorTreeAnalysis>();
if (PDT)
PA.preserve<PostDominatorTreeAnalysis>();
return PA;
}
21 changes: 21 additions & 0 deletions llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1985,7 +1985,28 @@ PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter) {
// increment to the new (widened) increment.
auto *OrigInc =
cast<Instruction>(OrigPhi->getIncomingValueForBlock(LatchBlock));

WideInc->setDebugLoc(OrigInc->getDebugLoc());
// We are replacing a narrow IV increment with a wider IV increment. If
// the original (narrow) increment did not wrap, the wider increment one
// should not wrap either. Set the flags to be the union of both wide
// increment and original increment; this ensures we preserve flags SCEV
// could infer for the wider increment. Limit this only to cases where
// both increments directly increment the corresponding PHI nodes and have
// the same opcode. It is not safe to re-use the flags from the original
// increment, if it is more complex and SCEV expansion may have yielded a
// more simplified wider increment.
bool MatchingOps =
match(OrigInc, m_c_BinOp(m_Specific(OrigPhi), m_Value())) &&
match(WideInc, m_c_BinOp(m_Specific(WidePhi), m_Value())) &&
OrigInc->getOpcode() == WideInc->getOpcode();
if (MatchingOps && isa<OverflowingBinaryOperator>(OrigInc) &&
isa<OverflowingBinaryOperator>(WideInc)) {
WideInc->setHasNoUnsignedWrap(WideInc->hasNoUnsignedWrap() ||
OrigInc->hasNoUnsignedWrap());
WideInc->setHasNoSignedWrap(WideInc->hasNoSignedWrap() ||
OrigInc->hasNoSignedWrap());
}
}
}

Expand Down
20 changes: 19 additions & 1 deletion llvm/test/Analysis/BasicAA/vscale.ll
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,29 @@ define void @vscale_negativescale(ptr %p) vscale_range(1,16) {
ret void
}

; CHECK-LABEL: onevscale
; CHECK-DAG: MustAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
define void @onevscale(ptr %p) vscale_range(1,16) {
%v1 = call i64 @llvm.vscale.i64()
%vp1 = mul nsw i64 %v1, 16
%vp2 = mul nsw i64 %v1, 16
%vp3 = mul nsw i64 %v1, 17
%vp161 = getelementptr i8, ptr %p, i64 %vp1
%vp162 = getelementptr i8, ptr %p, i64 %vp2
%vp161b = getelementptr i8, ptr %vp161, i64 %vp3
load <vscale x 4 x i32>, ptr %vp161
load <vscale x 4 x i32>, ptr %vp162
load <vscale x 4 x i32>, ptr %vp161b
ret void
}

; CHECK-LABEL: twovscales
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp162
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161, <vscale x 4 x i32>* %vp161b
; CHECK-DAG: MayAlias: <vscale x 4 x i32>* %vp161b, <vscale x 4 x i32>* %vp162
define void @twovscales(ptr %p) {
define void @twovscales(ptr %p) vscale_range(1,16) {
%v1 = call i64 @llvm.vscale.i64()
%v2 = call i64 @llvm.vscale.i64()
%vp1 = mul nsw i64 %v1, 16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,25 +220,28 @@ body: |
; CHECK-NEXT: [[AND5:%[0-9]+]]:_(s64) = G_AND [[LSHR3]], [[C5]]
; CHECK-NEXT: [[OR6:%[0-9]+]]:_(s64) = G_OR [[OR5]], [[AND5]]
; CHECK-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
; CHECK-NEXT: [[C8:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1085102592571150096
; CHECK-NEXT: [[AND6:%[0-9]+]]:_(s64) = G_AND [[OR6]], [[C8]]
; CHECK-NEXT: [[CONSTANT_POOL:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.2
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[CONSTANT_POOL]](p0) :: (load (s64) from constant-pool)
; CHECK-NEXT: [[AND6:%[0-9]+]]:_(s64) = G_AND [[OR6]], [[LOAD]]
; CHECK-NEXT: [[LSHR4:%[0-9]+]]:_(s64) = G_LSHR [[AND6]], [[C7]](s64)
; CHECK-NEXT: [[SHL4:%[0-9]+]]:_(s64) = G_SHL [[OR6]], [[C7]](s64)
; CHECK-NEXT: [[AND7:%[0-9]+]]:_(s64) = G_AND [[SHL4]], [[C8]]
; CHECK-NEXT: [[AND7:%[0-9]+]]:_(s64) = G_AND [[SHL4]], [[LOAD]]
; CHECK-NEXT: [[OR7:%[0-9]+]]:_(s64) = G_OR [[LSHR4]], [[AND7]]
; CHECK-NEXT: [[C9:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
; CHECK-NEXT: [[C10:%[0-9]+]]:_(s64) = G_CONSTANT i64 -3689348814741910324
; CHECK-NEXT: [[AND8:%[0-9]+]]:_(s64) = G_AND [[OR7]], [[C10]]
; CHECK-NEXT: [[LSHR5:%[0-9]+]]:_(s64) = G_LSHR [[AND8]], [[C9]](s64)
; CHECK-NEXT: [[SHL5:%[0-9]+]]:_(s64) = G_SHL [[OR7]], [[C9]](s64)
; CHECK-NEXT: [[AND9:%[0-9]+]]:_(s64) = G_AND [[SHL5]], [[C10]]
; CHECK-NEXT: [[C8:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
; CHECK-NEXT: [[CONSTANT_POOL1:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.1
; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(s64) = G_LOAD [[CONSTANT_POOL1]](p0) :: (load (s64) from constant-pool)
; CHECK-NEXT: [[AND8:%[0-9]+]]:_(s64) = G_AND [[OR7]], [[LOAD1]]
; CHECK-NEXT: [[LSHR5:%[0-9]+]]:_(s64) = G_LSHR [[AND8]], [[C8]](s64)
; CHECK-NEXT: [[SHL5:%[0-9]+]]:_(s64) = G_SHL [[OR7]], [[C8]](s64)
; CHECK-NEXT: [[AND9:%[0-9]+]]:_(s64) = G_AND [[SHL5]], [[LOAD1]]
; CHECK-NEXT: [[OR8:%[0-9]+]]:_(s64) = G_OR [[LSHR5]], [[AND9]]
; CHECK-NEXT: [[C11:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
; CHECK-NEXT: [[C12:%[0-9]+]]:_(s64) = G_CONSTANT i64 -6148914691236517206
; CHECK-NEXT: [[AND10:%[0-9]+]]:_(s64) = G_AND [[OR8]], [[C12]]
; CHECK-NEXT: [[LSHR6:%[0-9]+]]:_(s64) = G_LSHR [[AND10]], [[C11]](s64)
; CHECK-NEXT: [[SHL6:%[0-9]+]]:_(s64) = G_SHL [[OR8]], [[C11]](s64)
; CHECK-NEXT: [[AND11:%[0-9]+]]:_(s64) = G_AND [[SHL6]], [[C12]]
; CHECK-NEXT: [[C9:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
; CHECK-NEXT: [[CONSTANT_POOL2:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0
; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(s64) = G_LOAD [[CONSTANT_POOL2]](p0) :: (load (s64) from constant-pool)
; CHECK-NEXT: [[AND10:%[0-9]+]]:_(s64) = G_AND [[OR8]], [[LOAD2]]
; CHECK-NEXT: [[LSHR6:%[0-9]+]]:_(s64) = G_LSHR [[AND10]], [[C9]](s64)
; CHECK-NEXT: [[SHL6:%[0-9]+]]:_(s64) = G_SHL [[OR8]], [[C9]](s64)
; CHECK-NEXT: [[AND11:%[0-9]+]]:_(s64) = G_AND [[SHL6]], [[LOAD2]]
; CHECK-NEXT: [[OR9:%[0-9]+]]:_(s64) = G_OR [[LSHR6]], [[AND11]]
; CHECK-NEXT: $x10 = COPY [[OR9]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ name: const_i8
body: |
bb.0.entry:
; CHECK-LABEL: name: const_i8
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -127
; CHECK-NEXT: $x10 = COPY [[C]](s64)
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -127
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32)
; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s8) = G_CONSTANT i8 129
%1:_(s64) = G_ANYEXT %0(s8)
Expand All @@ -20,8 +21,9 @@ name: const_i15
body: |
bb.0.entry:
; CHECK-LABEL: name: const_i15
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 15
; CHECK-NEXT: $x10 = COPY [[C]](s64)
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32)
; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s15) = G_CONSTANT i15 15
%1:_(s64) = G_ANYEXT %0(s15)
Expand All @@ -34,8 +36,9 @@ name: const_i16
body: |
bb.0.entry:
; CHECK-LABEL: name: const_i16
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 767
; CHECK-NEXT: $x10 = COPY [[C]](s64)
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 767
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32)
; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s16) = G_CONSTANT i16 -64769
%1:_(s64) = G_ANYEXT %0(s16)
Expand All @@ -48,8 +51,9 @@ name: const_i32
body: |
bb.0.entry:
; CHECK-LABEL: name: const_i32
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -64769
; CHECK-NEXT: $x10 = COPY [[C]](s64)
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -64769
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[C]](s32)
; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s32) = G_CONSTANT i32 -64769
%1:_(s64) = G_ANYEXT %0(s32)
Expand Down Expand Up @@ -180,3 +184,19 @@ body: |
PseudoRET implicit $x10

...

...
---
name: constant_pool_i64
body: |
bb.0.entry:
; CHECK-LABEL: name: constant_pool_i64
; CHECK: [[CONSTANT_POOL:%[0-9]+]]:_(p0) = G_CONSTANT_POOL %const.0
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[CONSTANT_POOL]](p0) :: (load (s64) from constant-pool)
; CHECK-NEXT: $x10 = COPY [[LOAD]](s64)
; CHECK-NEXT: PseudoRET implicit $x10
%0:_(s64) = G_CONSTANT i64 -1085102592571150096
$x10 = COPY %0(s64)
PseudoRET implicit $x10

...
80 changes: 40 additions & 40 deletions llvm/test/CodeGen/RISCV/callee-saved-gprs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -150,24 +150,24 @@ define void @callee() nounwind {
;
; RV32I-ILP32E-LABEL: callee:
; RV32I-ILP32E: # %bb.0:
; RV32I-ILP32E-NEXT: addi sp, sp, -48
; RV32I-ILP32E-NEXT: sw ra, 44(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw s0, 40(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw s1, 36(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: addi sp, sp, -36
; RV32I-ILP32E-NEXT: sw ra, 32(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw s0, 28(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw s1, 24(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lui a6, %hi(var)
; RV32I-ILP32E-NEXT: lw a0, %lo(var)(a6)
; RV32I-ILP32E-NEXT: sw a0, 32(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 20(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lw a0, %lo(var+4)(a6)
; RV32I-ILP32E-NEXT: sw a0, 28(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 16(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lw a0, %lo(var+8)(a6)
; RV32I-ILP32E-NEXT: sw a0, 24(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lw a0, %lo(var+12)(a6)
; RV32I-ILP32E-NEXT: sw a0, 20(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 8(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: addi a5, a6, %lo(var)
; RV32I-ILP32E-NEXT: lw a0, 16(a5)
; RV32I-ILP32E-NEXT: sw a0, 16(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 4(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lw a0, 20(a5)
; RV32I-ILP32E-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: sw a0, 0(sp) # 4-byte Folded Spill
; RV32I-ILP32E-NEXT: lw t0, 24(a5)
; RV32I-ILP32E-NEXT: lw t1, 28(a5)
; RV32I-ILP32E-NEXT: lw t2, 32(a5)
Expand Down Expand Up @@ -220,22 +220,22 @@ define void @callee() nounwind {
; RV32I-ILP32E-NEXT: sw t2, 32(a5)
; RV32I-ILP32E-NEXT: sw t1, 28(a5)
; RV32I-ILP32E-NEXT: sw t0, 24(a5)
; RV32I-ILP32E-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 0(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, 20(a5)
; RV32I-ILP32E-NEXT: lw a0, 16(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 4(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, 16(a5)
; RV32I-ILP32E-NEXT: lw a0, 20(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, %lo(var+12)(a6)
; RV32I-ILP32E-NEXT: lw a0, 24(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, %lo(var+8)(a6)
; RV32I-ILP32E-NEXT: lw a0, 28(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 16(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, %lo(var+4)(a6)
; RV32I-ILP32E-NEXT: lw a0, 32(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw a0, 20(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: sw a0, %lo(var)(a6)
; RV32I-ILP32E-NEXT: lw ra, 44(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw s0, 40(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw s1, 36(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: addi sp, sp, 48
; RV32I-ILP32E-NEXT: lw ra, 32(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw s0, 28(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: lw s1, 24(sp) # 4-byte Folded Reload
; RV32I-ILP32E-NEXT: addi sp, sp, 36
; RV32I-ILP32E-NEXT: ret
;
; RV32I-WITH-FP-LABEL: callee:
Expand Down Expand Up @@ -659,24 +659,24 @@ define void @callee() nounwind {
;
; RV64I-LP64E-LABEL: callee:
; RV64I-LP64E: # %bb.0:
; RV64I-LP64E-NEXT: addi sp, sp, -80
; RV64I-LP64E-NEXT: sd ra, 72(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: sd s0, 64(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: sd s1, 56(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: addi sp, sp, -72
; RV64I-LP64E-NEXT: sd ra, 64(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: sd s0, 56(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: sd s1, 48(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lui a6, %hi(var)
; RV64I-LP64E-NEXT: lw a0, %lo(var)(a6)
; RV64I-LP64E-NEXT: sd a0, 48(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, %lo(var+4)(a6)
; RV64I-LP64E-NEXT: sd a0, 40(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, %lo(var+8)(a6)
; RV64I-LP64E-NEXT: lw a0, %lo(var+4)(a6)
; RV64I-LP64E-NEXT: sd a0, 32(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, %lo(var+12)(a6)
; RV64I-LP64E-NEXT: lw a0, %lo(var+8)(a6)
; RV64I-LP64E-NEXT: sd a0, 24(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, %lo(var+12)(a6)
; RV64I-LP64E-NEXT: sd a0, 16(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: addi a5, a6, %lo(var)
; RV64I-LP64E-NEXT: lw a0, 16(a5)
; RV64I-LP64E-NEXT: sd a0, 16(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, 20(a5)
; RV64I-LP64E-NEXT: sd a0, 8(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw a0, 20(a5)
; RV64I-LP64E-NEXT: sd a0, 0(sp) # 8-byte Folded Spill
; RV64I-LP64E-NEXT: lw t0, 24(a5)
; RV64I-LP64E-NEXT: lw t1, 28(a5)
; RV64I-LP64E-NEXT: lw t2, 32(a5)
Expand Down Expand Up @@ -729,22 +729,22 @@ define void @callee() nounwind {
; RV64I-LP64E-NEXT: sw t2, 32(a5)
; RV64I-LP64E-NEXT: sw t1, 28(a5)
; RV64I-LP64E-NEXT: sw t0, 24(a5)
; RV64I-LP64E-NEXT: ld a0, 8(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 0(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, 20(a5)
; RV64I-LP64E-NEXT: ld a0, 16(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 8(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, 16(a5)
; RV64I-LP64E-NEXT: ld a0, 24(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 16(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, %lo(var+12)(a6)
; RV64I-LP64E-NEXT: ld a0, 32(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 24(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, %lo(var+8)(a6)
; RV64I-LP64E-NEXT: ld a0, 40(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 32(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, %lo(var+4)(a6)
; RV64I-LP64E-NEXT: ld a0, 48(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld a0, 40(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: sw a0, %lo(var)(a6)
; RV64I-LP64E-NEXT: ld ra, 72(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld s0, 64(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld s1, 56(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: addi sp, sp, 80
; RV64I-LP64E-NEXT: ld ra, 64(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld s0, 56(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: ld s1, 48(sp) # 8-byte Folded Reload
; RV64I-LP64E-NEXT: addi sp, sp, 72
; RV64I-LP64E-NEXT: ret
;
; RV64I-WITH-FP-LABEL: callee:
Expand Down
208 changes: 104 additions & 104 deletions llvm/test/CodeGen/RISCV/calling-conv-ilp32e.ll

Large diffs are not rendered by default.

226 changes: 113 additions & 113 deletions llvm/test/CodeGen/RISCV/rv64-legal-i32/vararg.ll
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,28 @@ define i32 @va1(ptr %fmt, ...) {
;
; LP64E-FPELIM-LABEL: va1:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -64
; LP64E-FPELIM-NEXT: .cfi_def_cfa_offset 64
; LP64E-FPELIM-NEXT: addi sp, sp, -56
; LP64E-FPELIM-NEXT: .cfi_def_cfa_offset 56
; LP64E-FPELIM-NEXT: mv a0, a1
; LP64E-FPELIM-NEXT: sd a5, 56(sp)
; LP64E-FPELIM-NEXT: sd a4, 48(sp)
; LP64E-FPELIM-NEXT: sd a3, 40(sp)
; LP64E-FPELIM-NEXT: sd a2, 32(sp)
; LP64E-FPELIM-NEXT: sd a1, 24(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 28
; LP64E-FPELIM-NEXT: sd a1, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 64
; LP64E-FPELIM-NEXT: sd a5, 48(sp)
; LP64E-FPELIM-NEXT: sd a4, 40(sp)
; LP64E-FPELIM-NEXT: sd a3, 32(sp)
; LP64E-FPELIM-NEXT: sd a2, 24(sp)
; LP64E-FPELIM-NEXT: sd a1, 16(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 20
; LP64E-FPELIM-NEXT: sd a1, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 56
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va1:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -80
; LP64E-WITHFP-NEXT: .cfi_def_cfa_offset 80
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi sp, sp, -72
; LP64E-WITHFP-NEXT: .cfi_def_cfa_offset 72
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: .cfi_offset ra, -56
; LP64E-WITHFP-NEXT: .cfi_offset s0, -64
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: .cfi_def_cfa s0, 48
; LP64E-WITHFP-NEXT: mv a0, a1
; LP64E-WITHFP-NEXT: sd a5, 40(s0)
Expand All @@ -107,9 +107,9 @@ define i32 @va1(ptr %fmt, ...) {
; LP64E-WITHFP-NEXT: sd a1, 8(s0)
; LP64E-WITHFP-NEXT: addi a1, s0, 12
; LP64E-WITHFP-NEXT: sd a1, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 80
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 72
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -161,24 +161,24 @@ define i32 @va1_va_arg(ptr %fmt, ...) nounwind {
;
; LP64E-FPELIM-LABEL: va1_va_arg:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -64
; LP64E-FPELIM-NEXT: addi sp, sp, -56
; LP64E-FPELIM-NEXT: mv a0, a1
; LP64E-FPELIM-NEXT: sd a5, 56(sp)
; LP64E-FPELIM-NEXT: sd a4, 48(sp)
; LP64E-FPELIM-NEXT: sd a3, 40(sp)
; LP64E-FPELIM-NEXT: sd a2, 32(sp)
; LP64E-FPELIM-NEXT: sd a1, 24(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 32
; LP64E-FPELIM-NEXT: sd a1, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 64
; LP64E-FPELIM-NEXT: sd a5, 48(sp)
; LP64E-FPELIM-NEXT: sd a4, 40(sp)
; LP64E-FPELIM-NEXT: sd a3, 32(sp)
; LP64E-FPELIM-NEXT: sd a2, 24(sp)
; LP64E-FPELIM-NEXT: sd a1, 16(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 24
; LP64E-FPELIM-NEXT: sd a1, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 56
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va1_va_arg:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -80
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -72
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: mv a0, a1
; LP64E-WITHFP-NEXT: sd a5, 40(s0)
; LP64E-WITHFP-NEXT: sd a4, 32(s0)
Expand All @@ -187,9 +187,9 @@ define i32 @va1_va_arg(ptr %fmt, ...) nounwind {
; LP64E-WITHFP-NEXT: sd a1, 8(s0)
; LP64E-WITHFP-NEXT: addi a1, s0, 16
; LP64E-WITHFP-NEXT: sd a1, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 80
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 72
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -435,24 +435,24 @@ define i64 @va2(ptr %fmt, ...) nounwind {
;
; LP64E-FPELIM-LABEL: va2:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -64
; LP64E-FPELIM-NEXT: addi sp, sp, -56
; LP64E-FPELIM-NEXT: mv a0, a1
; LP64E-FPELIM-NEXT: sd a5, 56(sp)
; LP64E-FPELIM-NEXT: sd a4, 48(sp)
; LP64E-FPELIM-NEXT: sd a3, 40(sp)
; LP64E-FPELIM-NEXT: sd a2, 32(sp)
; LP64E-FPELIM-NEXT: sd a1, 24(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 39
; LP64E-FPELIM-NEXT: sd a1, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 64
; LP64E-FPELIM-NEXT: sd a5, 48(sp)
; LP64E-FPELIM-NEXT: sd a4, 40(sp)
; LP64E-FPELIM-NEXT: sd a3, 32(sp)
; LP64E-FPELIM-NEXT: sd a2, 24(sp)
; LP64E-FPELIM-NEXT: sd a1, 16(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 31
; LP64E-FPELIM-NEXT: sd a1, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 56
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va2:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -80
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -72
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: mv a0, a1
; LP64E-WITHFP-NEXT: sd a5, 40(s0)
; LP64E-WITHFP-NEXT: sd a4, 32(s0)
Expand All @@ -461,9 +461,9 @@ define i64 @va2(ptr %fmt, ...) nounwind {
; LP64E-WITHFP-NEXT: sd a1, 8(s0)
; LP64E-WITHFP-NEXT: addi a1, s0, 23
; LP64E-WITHFP-NEXT: sd a1, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 80
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 72
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -521,24 +521,24 @@ define i64 @va2_va_arg(ptr %fmt, ...) nounwind {
;
; LP64E-FPELIM-LABEL: va2_va_arg:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -64
; LP64E-FPELIM-NEXT: addi sp, sp, -56
; LP64E-FPELIM-NEXT: mv a0, a1
; LP64E-FPELIM-NEXT: sd a5, 56(sp)
; LP64E-FPELIM-NEXT: sd a4, 48(sp)
; LP64E-FPELIM-NEXT: sd a3, 40(sp)
; LP64E-FPELIM-NEXT: sd a2, 32(sp)
; LP64E-FPELIM-NEXT: sd a1, 24(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 32
; LP64E-FPELIM-NEXT: sd a1, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 64
; LP64E-FPELIM-NEXT: sd a5, 48(sp)
; LP64E-FPELIM-NEXT: sd a4, 40(sp)
; LP64E-FPELIM-NEXT: sd a3, 32(sp)
; LP64E-FPELIM-NEXT: sd a2, 24(sp)
; LP64E-FPELIM-NEXT: sd a1, 16(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 24
; LP64E-FPELIM-NEXT: sd a1, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 56
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va2_va_arg:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -80
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -72
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: mv a0, a1
; LP64E-WITHFP-NEXT: sd a5, 40(s0)
; LP64E-WITHFP-NEXT: sd a4, 32(s0)
Expand All @@ -547,9 +547,9 @@ define i64 @va2_va_arg(ptr %fmt, ...) nounwind {
; LP64E-WITHFP-NEXT: sd a1, 8(s0)
; LP64E-WITHFP-NEXT: addi a1, s0, 16
; LP64E-WITHFP-NEXT: sd a1, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 80
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 72
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -654,33 +654,33 @@ define i64 @va3(i32 %a, i64 %b, ...) nounwind {
;
; LP64E-FPELIM-LABEL: va3:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -48
; LP64E-FPELIM-NEXT: sd a5, 40(sp)
; LP64E-FPELIM-NEXT: sd a4, 32(sp)
; LP64E-FPELIM-NEXT: sd a3, 24(sp)
; LP64E-FPELIM-NEXT: sd a2, 16(sp)
; LP64E-FPELIM-NEXT: addi a3, sp, 31
; LP64E-FPELIM-NEXT: addi sp, sp, -40
; LP64E-FPELIM-NEXT: sd a5, 32(sp)
; LP64E-FPELIM-NEXT: sd a4, 24(sp)
; LP64E-FPELIM-NEXT: sd a3, 16(sp)
; LP64E-FPELIM-NEXT: sd a2, 8(sp)
; LP64E-FPELIM-NEXT: addi a3, sp, 23
; LP64E-FPELIM-NEXT: add a0, a1, a2
; LP64E-FPELIM-NEXT: sd a3, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 48
; LP64E-FPELIM-NEXT: sd a3, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 40
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va3:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -64
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -56
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: sd a5, 24(s0)
; LP64E-WITHFP-NEXT: sd a4, 16(s0)
; LP64E-WITHFP-NEXT: sd a3, 8(s0)
; LP64E-WITHFP-NEXT: sd a2, 0(s0)
; LP64E-WITHFP-NEXT: addi a3, s0, 15
; LP64E-WITHFP-NEXT: add a0, a1, a2
; LP64E-WITHFP-NEXT: sd a3, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 64
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 56
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -737,33 +737,33 @@ define i64 @va3_va_arg(i32 %a, i64 %b, ...) nounwind {
;
; LP64E-FPELIM-LABEL: va3_va_arg:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -48
; LP64E-FPELIM-NEXT: sd a5, 40(sp)
; LP64E-FPELIM-NEXT: sd a4, 32(sp)
; LP64E-FPELIM-NEXT: sd a3, 24(sp)
; LP64E-FPELIM-NEXT: sd a2, 16(sp)
; LP64E-FPELIM-NEXT: addi a3, sp, 24
; LP64E-FPELIM-NEXT: addi sp, sp, -40
; LP64E-FPELIM-NEXT: sd a5, 32(sp)
; LP64E-FPELIM-NEXT: sd a4, 24(sp)
; LP64E-FPELIM-NEXT: sd a3, 16(sp)
; LP64E-FPELIM-NEXT: sd a2, 8(sp)
; LP64E-FPELIM-NEXT: addi a3, sp, 16
; LP64E-FPELIM-NEXT: add a0, a1, a2
; LP64E-FPELIM-NEXT: sd a3, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 48
; LP64E-FPELIM-NEXT: sd a3, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 40
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va3_va_arg:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -64
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -56
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: sd a5, 24(s0)
; LP64E-WITHFP-NEXT: sd a4, 16(s0)
; LP64E-WITHFP-NEXT: sd a3, 8(s0)
; LP64E-WITHFP-NEXT: sd a2, 0(s0)
; LP64E-WITHFP-NEXT: addi a3, s0, 8
; LP64E-WITHFP-NEXT: add a0, a1, a2
; LP64E-WITHFP-NEXT: sd a3, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 64
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 56
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down Expand Up @@ -1208,24 +1208,24 @@ define i32 @va6_no_fixed_args(...) nounwind {
;
; LP64E-FPELIM-LABEL: va6_no_fixed_args:
; LP64E-FPELIM: # %bb.0:
; LP64E-FPELIM-NEXT: addi sp, sp, -64
; LP64E-FPELIM-NEXT: sd a5, 56(sp)
; LP64E-FPELIM-NEXT: sd a4, 48(sp)
; LP64E-FPELIM-NEXT: sd a3, 40(sp)
; LP64E-FPELIM-NEXT: sd a2, 32(sp)
; LP64E-FPELIM-NEXT: sd a1, 24(sp)
; LP64E-FPELIM-NEXT: sd a0, 16(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 24
; LP64E-FPELIM-NEXT: sd a1, 8(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 64
; LP64E-FPELIM-NEXT: addi sp, sp, -56
; LP64E-FPELIM-NEXT: sd a5, 48(sp)
; LP64E-FPELIM-NEXT: sd a4, 40(sp)
; LP64E-FPELIM-NEXT: sd a3, 32(sp)
; LP64E-FPELIM-NEXT: sd a2, 24(sp)
; LP64E-FPELIM-NEXT: sd a1, 16(sp)
; LP64E-FPELIM-NEXT: sd a0, 8(sp)
; LP64E-FPELIM-NEXT: addi a1, sp, 16
; LP64E-FPELIM-NEXT: sd a1, 0(sp)
; LP64E-FPELIM-NEXT: addi sp, sp, 56
; LP64E-FPELIM-NEXT: ret
;
; LP64E-WITHFP-LABEL: va6_no_fixed_args:
; LP64E-WITHFP: # %bb.0:
; LP64E-WITHFP-NEXT: addi sp, sp, -80
; LP64E-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 32
; LP64E-WITHFP-NEXT: addi sp, sp, -72
; LP64E-WITHFP-NEXT: sd ra, 16(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
; LP64E-WITHFP-NEXT: addi s0, sp, 24
; LP64E-WITHFP-NEXT: sd a5, 40(s0)
; LP64E-WITHFP-NEXT: sd a4, 32(s0)
; LP64E-WITHFP-NEXT: sd a3, 24(s0)
Expand All @@ -1234,9 +1234,9 @@ define i32 @va6_no_fixed_args(...) nounwind {
; LP64E-WITHFP-NEXT: sd a0, 0(s0)
; LP64E-WITHFP-NEXT: addi a1, s0, 8
; LP64E-WITHFP-NEXT: sd a1, -24(s0)
; LP64E-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 80
; LP64E-WITHFP-NEXT: ld ra, 16(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
; LP64E-WITHFP-NEXT: addi sp, sp, 72
; LP64E-WITHFP-NEXT: ret
%va = alloca ptr
call void @llvm.va_start(ptr %va)
Expand Down
134 changes: 134 additions & 0 deletions llvm/test/CodeGen/RISCV/shadowcallstack.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
; RUN: | FileCheck %s --check-prefix=RV32
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefix=RV64
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfiss < %s \
; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=RV32-ZICFISS
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss < %s \
; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=RV64-ZICFISS
; RUN: llc -mtriple=riscv32 -mattr=+experimental-zicfiss,forced-sw-shadow-stack \
; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfiss,forced-sw-shadow-stack \
; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64

define void @f1() shadowcallstack {
; RV32-LABEL: f1:
Expand All @@ -12,6 +20,14 @@ define void @f1() shadowcallstack {
; RV64-LABEL: f1:
; RV64: # %bb.0:
; RV64-NEXT: ret
;
; RV32-ZICFISS-LABEL: f1:
; RV32-ZICFISS: # %bb.0:
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f1:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: ret
ret void
}

Expand All @@ -25,6 +41,14 @@ define void @f2() shadowcallstack {
; RV64-LABEL: f2:
; RV64: # %bb.0:
; RV64-NEXT: tail foo
;
; RV32-ZICFISS-LABEL: f2:
; RV32-ZICFISS: # %bb.0:
; RV32-ZICFISS-NEXT: tail foo
;
; RV64-ZICFISS-LABEL: f2:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: tail foo
tail call void @foo()
ret void
}
Expand Down Expand Up @@ -65,6 +89,32 @@ define i32 @f3() shadowcallstack {
; RV64-NEXT: addi gp, gp, -8
; RV64-NEXT: .cfi_restore gp
; RV64-NEXT: ret
;
; RV32-ZICFISS-LABEL: f3:
; RV32-ZICFISS: # %bb.0:
; RV32-ZICFISS-NEXT: sspush ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: .cfi_offset ra, -4
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: sspopchk ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f3:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: sspush ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: .cfi_offset ra, -8
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: addi sp, sp, 16
; RV64-ZICFISS-NEXT: sspopchk ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
Expand Down Expand Up @@ -140,6 +190,68 @@ define i32 @f4() shadowcallstack {
; RV64-NEXT: addi gp, gp, -8
; RV64-NEXT: .cfi_restore gp
; RV64-NEXT: ret
;
; RV32-ZICFISS-LABEL: f4:
; RV32-ZICFISS: # %bb.0:
; RV32-ZICFISS-NEXT: sspush ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: .cfi_def_cfa_offset 16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: sw s2, 0(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: .cfi_offset ra, -4
; RV32-ZICFISS-NEXT: .cfi_offset s0, -8
; RV32-ZICFISS-NEXT: .cfi_offset s1, -12
; RV32-ZICFISS-NEXT: .cfi_offset s2, -16
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: mv s0, a0
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: mv s1, a0
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: mv s2, a0
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: add s0, s0, s1
; RV32-ZICFISS-NEXT: add a0, s2, a0
; RV32-ZICFISS-NEXT: add a0, s0, a0
; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: lw s2, 0(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: sspopchk ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f4:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: sspush ra
; RV64-ZICFISS-NEXT: addi sp, sp, -32
; RV64-ZICFISS-NEXT: .cfi_def_cfa_offset 32
; RV64-ZICFISS-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: sd s2, 0(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: .cfi_offset ra, -8
; RV64-ZICFISS-NEXT: .cfi_offset s0, -16
; RV64-ZICFISS-NEXT: .cfi_offset s1, -24
; RV64-ZICFISS-NEXT: .cfi_offset s2, -32
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: mv s0, a0
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: mv s1, a0
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: mv s2, a0
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: add s0, s0, s1
; RV64-ZICFISS-NEXT: add a0, s2, a0
; RV64-ZICFISS-NEXT: addw a0, s0, a0
; RV64-ZICFISS-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: ld s2, 0(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: addi sp, sp, 32
; RV64-ZICFISS-NEXT: sspopchk ra
; RV64-ZICFISS-NEXT: ret
%res1 = call i32 @bar()
%res2 = call i32 @bar()
%res3 = call i32 @bar()
Expand Down Expand Up @@ -176,6 +288,28 @@ define i32 @f5() shadowcallstack nounwind {
; RV64-NEXT: ld ra, -8(gp)
; RV64-NEXT: addi gp, gp, -8
; RV64-NEXT: ret
;
; RV32-ZICFISS-LABEL: f5:
; RV32-ZICFISS: # %bb.0:
; RV32-ZICFISS-NEXT: sspush ra
; RV32-ZICFISS-NEXT: addi sp, sp, -16
; RV32-ZICFISS-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32-ZICFISS-NEXT: call bar
; RV32-ZICFISS-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32-ZICFISS-NEXT: addi sp, sp, 16
; RV32-ZICFISS-NEXT: sspopchk ra
; RV32-ZICFISS-NEXT: ret
;
; RV64-ZICFISS-LABEL: f5:
; RV64-ZICFISS: # %bb.0:
; RV64-ZICFISS-NEXT: sspush ra
; RV64-ZICFISS-NEXT: addi sp, sp, -16
; RV64-ZICFISS-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64-ZICFISS-NEXT: call bar
; RV64-ZICFISS-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64-ZICFISS-NEXT: addi sp, sp, 16
; RV64-ZICFISS-NEXT: sspopchk ra
; RV64-ZICFISS-NEXT: ret
%res = call i32 @bar()
%res1 = add i32 %res, 1
ret i32 %res
Expand Down
Loading