Test driver for https://reviews.llvm.org/D41149
| // 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