-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix silent bad codegen for vectorized
meow_element()
above 4 GB (#3619
- Loading branch information
1 parent
adaf68c
commit cb86d7e
Showing
6 changed files
with
170 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#pragma once | ||
|
||
#include <algorithm> | ||
#include <cassert> | ||
#include <cstddef> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#ifdef __cpp_lib_concepts | ||
#include <ranges> | ||
#endif | ||
|
||
template <class FwdIt> | ||
FwdIt last_known_good_min_element(FwdIt first, FwdIt last) { | ||
FwdIt result = first; | ||
|
||
for (; first != last; ++first) { | ||
if (*first < *result) { | ||
result = first; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
template <class FwdIt> | ||
FwdIt last_known_good_max_element(FwdIt first, FwdIt last) { | ||
FwdIt result = first; | ||
|
||
for (; first != last; ++first) { | ||
if (*result < *first) { | ||
result = first; | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
template <class FwdIt> | ||
std::pair<FwdIt, FwdIt> last_known_good_minmax_element(FwdIt first, FwdIt last) { | ||
// find smallest and largest elements | ||
std::pair<FwdIt, FwdIt> found(first, first); | ||
|
||
if (first != last) { | ||
while (++first != last) { // process one or two elements | ||
FwdIt next = first; | ||
if (++next == last) { // process last element | ||
if (*first < *found.first) { | ||
found.first = first; | ||
} else if (!(*first < *found.second)) { | ||
found.second = first; | ||
} | ||
} else { // process next two elements | ||
if (*next < *first) { // test next for new smallest | ||
if (*next < *found.first) { | ||
found.first = next; | ||
} | ||
|
||
if (!(*first < *found.second)) { | ||
found.second = first; | ||
} | ||
} else { // test first for new smallest | ||
if (*first < *found.first) { | ||
found.first = first; | ||
} | ||
|
||
if (!(*next < *found.second)) { | ||
found.second = next; | ||
} | ||
} | ||
first = next; | ||
} | ||
} | ||
} | ||
|
||
return found; | ||
} | ||
|
||
template <class T> | ||
void test_case_min_max_element(const std::vector<T>& input) { | ||
auto expected_min = last_known_good_min_element(input.begin(), input.end()); | ||
auto expected_max = last_known_good_max_element(input.begin(), input.end()); | ||
auto expected_minmax = last_known_good_minmax_element(input.begin(), input.end()); | ||
auto actual_min = std::min_element(input.begin(), input.end()); | ||
auto actual_max = std::max_element(input.begin(), input.end()); | ||
auto actual_minmax = std::minmax_element(input.begin(), input.end()); | ||
assert(expected_min == actual_min); | ||
assert(expected_max == actual_max); | ||
assert(expected_minmax == actual_minmax); | ||
#ifdef __cpp_lib_concepts | ||
using std::ranges::views::take, std::ptrdiff_t; | ||
|
||
auto actual_min_range = std::ranges::min_element(input); | ||
auto actual_max_range = std::ranges::max_element(input); | ||
auto actual_minmax_range = std::ranges::minmax_element(input); | ||
auto actual_min_sized_range = std::ranges::min_element(take(input, static_cast<ptrdiff_t>(input.size()))); | ||
auto actual_max_sized_range = std::ranges::max_element(take(input, static_cast<ptrdiff_t>(input.size()))); | ||
auto actual_minmax_sized_range = std::ranges::minmax_element(take(input, static_cast<ptrdiff_t>(input.size()))); | ||
assert(expected_min == actual_min_range); | ||
assert(expected_max == actual_max_range); | ||
assert(expected_minmax.first == actual_minmax_range.min); | ||
assert(expected_minmax.second == actual_minmax_range.max); | ||
assert(expected_min == actual_min_sized_range); | ||
assert(expected_max == actual_max_sized_range); | ||
assert(expected_minmax.first == actual_minmax_sized_range.min); | ||
assert(expected_minmax.second == actual_minmax_sized_range.max); | ||
#endif // __cpp_lib_concepts | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
RUNALL_INCLUDE ..\fast_matrix.lst |
44 changes: 44 additions & 0 deletions
44
tests/std/tests/GH_003617_vectorized_meow_element/test.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
// REQUIRES: x64 | ||
|
||
#ifdef _M_X64 | ||
|
||
#include <cstddef> | ||
#include <isa_availability.h> | ||
#include <vector> | ||
|
||
#include "test_min_max_element_support.hpp" | ||
|
||
using namespace std; | ||
|
||
extern "C" long __isa_enabled; | ||
|
||
void disable_instructions(ISA_AVAILABILITY isa) { | ||
__isa_enabled &= ~(1UL << static_cast<unsigned long>(isa)); | ||
} | ||
|
||
void test_gh_3617() { | ||
// Test GH-3617 "<algorithm>: Silent bad codegen for vectorized meow_element() above 4 GB". | ||
constexpr size_t n = 0x4000'0010; | ||
|
||
vector<int> v(n, 25); | ||
v[n - 2] = 24; | ||
v[n - 1] = 26; | ||
|
||
test_case_min_max_element(v); | ||
} | ||
|
||
int main() { | ||
test_gh_3617(); | ||
|
||
disable_instructions(__ISA_AVAILABLE_AVX2); | ||
test_gh_3617(); | ||
|
||
disable_instructions(__ISA_AVAILABLE_SSE42); | ||
test_gh_3617(); | ||
} | ||
#else // ^^^ x64 / other architectures vvv | ||
int main() {} | ||
#endif // ^^^ other architectures ^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters