Skip to content

Instantly share code, notes, and snippets.

@vedantk
Last active January 3, 2018 22:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vedantk/3eb9c88f82e5c32f2e590555b4af5081 to your computer and use it in GitHub Desktop.
Save vedantk/3eb9c88f82e5c32f2e590555b4af5081 to your computer and use it in GitHub Desktop.
// 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