Last active
January 3, 2018 22:29
-
-
Save vedantk/3eb9c88f82e5c32f2e590555b4af5081 to your computer and use it in GitHub Desktop.
Test driver for https://reviews.llvm.org/D41149
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
// Test driver for https://reviews.llvm.org/D41149 | |
#include <cstdint> | |
#include <limits> | |
#include <iostream> | |
#include <vector> | |
// Instructions: | |
// - Compile this program with a baseline compiler and a patched compiler. | |
// - Check that the output of the two executables is the same. | |
// - Flags: -std=c++11 -O3 | |
// Generate interesting test inputs for mul<S, U>(S a, U b). | |
template<typename S, typename U> | |
std::vector<std::pair<S, U>> gen() { | |
std::vector<S> SignedInputs; | |
std::vector<U> UnsignedInputs; | |
// Create some interesting signed and unsigned numbers. | |
for (int i = 0; i < 50; ++i) { // -49..49 | |
SignedInputs.push_back(i); | |
if (i > 0) SignedInputs.push_back(-i); | |
UnsignedInputs.push_back(i); | |
} | |
for (int i = 1; i < 50; ++i) { // {MIN, MAX} / 1..49 | |
SignedInputs.push_back(std::numeric_limits<S>::min() / i); | |
SignedInputs.push_back(std::numeric_limits<S>::max() / i); | |
UnsignedInputs.push_back(std::numeric_limits<U>::max() / i); | |
} | |
// Take the cartesian product of the interesting signed and unsigned numbers. | |
std::vector<std::pair<S, U>> Inputs; | |
for (S i : SignedInputs) | |
for (U u : UnsignedInputs) | |
Inputs.emplace_back(i, u); | |
return Inputs; | |
} | |
// Multiply a * b. Print out the result if there's no overflow. Return true | |
// iff there's an overflow. | |
template<typename S, typename U, typename R> | |
bool mul(S a, U b) { | |
R res; | |
bool oflow = __builtin_mul_overflow(a, b, &res); | |
std::cout << a << " * " << b << " = " << res << "\toflow: " << oflow << std::endl; | |
return oflow; | |
} | |
// Compute some interesting checked multiplications given the following types: | |
// | |
// S: signed type | |
// U: unsigned type | |
// R: result type | |
// | |
// Print out the number of overflows detected. | |
template<typename S, typename U, typename R> | |
void test_mul() { | |
uint64_t NumOverflows = 0; | |
for (auto I : gen<S, U>()) | |
if (mul<S, U, R>(I.first, I.second)) | |
++NumOverflows; | |
std::cout << "# overflows = " << NumOverflows << std::endl; | |
} | |
// Test 6 different result types for each pair of signed & unsigned types. | |
#define R(SignedTy, UnsignedTy) \ | |
test_mul<SignedTy, UnsignedTy, int16_t>(); \ | |
test_mul<SignedTy, UnsignedTy, int32_t>(); \ | |
test_mul<SignedTy, UnsignedTy, int64_t>(); \ | |
test_mul<SignedTy, UnsignedTy, uint16_t>(); \ | |
test_mul<SignedTy, UnsignedTy, uint32_t>(); \ | |
test_mul<SignedTy, UnsignedTy, uint64_t>(); | |
// Test 3 different unsigned types for each signed type. | |
#define U(SignedTy) \ | |
R(SignedTy, uint16_t) \ | |
R(SignedTy, uint32_t) \ | |
R(SignedTy, uint64_t) | |
// Test 3 different signed types. | |
#define S() \ | |
U(int16_t) \ | |
U(int32_t) \ | |
U(int64_t) | |
int main() { | |
S(); // Test 54 different combinations of signed, unsigned, and result types. | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment