Changes in directory llvm-test/SingleSource/UnitTests/Integer/APInt:
gptest.cpp added (r1.1) --- Log message: A test program to test APInt against the results produced by pari/gp. If there's no output other than the bit size banners, everything is fine. If outputs vary from pari/gp, they are printed. Program requires "gp" to be in the user's path. --- Diffs of the changes: (+380 -0) gptest.cpp | 380 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 380 insertions(+) Index: llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp diff -c /dev/null llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp:1.1 *** /dev/null Tue Feb 20 14:44:11 2007 --- llvm-test/SingleSource/UnitTests/Integer/APInt/gptest.cpp Tue Feb 20 14:44:00 2007 *************** *** 0 **** --- 1,380 ---- + //===--- gptest.cpp --- Test Cases for Bit Accurate Types -----------------===// + // + // This file was developed by Guoling Han and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This is a validating test for arithmetic operations that uses the gp (pari) + // calculator to validate APInt's computations. + // + //===----------------------------------------------------------------------===// + + #include "llvm/ADT/APInt.h" + #include <stdio.h> + #include <stdlib.h> + #include <sys/wait.h> + #include <unistd.h> + #include "llvm/System/Signals.h" + + using namespace llvm; + + APInt x(21, 0x1fffff); + APInt y(21, 0x0fffff); + + void print(const APInt& X, bool wantSigned = false, bool withNL = true) { + std::string decstr = X.toString(10,wantSigned); + printf("%s", decstr.c_str()); + if (withNL) + printf("\n"); + } + + APInt randomAPInt(unsigned bits) { + APInt val(bits, 0u); + for (unsigned i = 0; i < bits; ++i) { + unsigned bit = rand() % 2; + val = val.shl(1); + val |= APInt(bits, bit); + } + return val; + } + + void test_interface(const APInt &val) { + printf("INTERFACE TEST: val = "); print(val); + unsigned bitwidth = val.getBitWidth(); + unsigned pos = rand() % bitwidth; + printf("val[%u] = %d\n", pos, val[pos]); + APInt smax(APInt::getMaxValue(bitwidth, true)); + APInt umax(APInt::getMaxValue(bitwidth, false)); + APInt smin(APInt::getMinValue(bitwidth, true)); + APInt umin(APInt::getMinValue(bitwidth, false)); + printf("APInt::getMinValue(%d, true) = ", bitwidth); print(smin,true); + printf("APInt::getMaxValue(%d, true) = ", bitwidth); print(smax,true); + printf("APInt::getMinValue(%d, false) = ", bitwidth); print(umin); + printf("APInt::getMaxValue(%d, false) = ", bitwidth); print(umax); + APInt null = APInt::getNullValue(bitwidth); + APInt allone = APInt::getAllOnesValue(bitwidth); + printf("APInt::getNullValue(%d) = ", bitwidth); print(null); + printf("APInt::getAllOnesValue(%d) = ", bitwidth); print(allone); + APInt x(val); + x.set(pos); + printf("val.set(%d) = ", pos); print(x); + x.set(); + printf("val.set() = "); print(x); + x = val; + x.clear(pos); + printf("val.clear(%d) = ", pos); print(x); + x.clear(); + printf("val.clear() = "); print(x); + x = val; + x.flip(pos); + printf("val.flip(%d) = ", pos); print(x); + x = val; + x.flip(); + printf("val.flip() = "); print(x); + unsigned bitsize = bitwidth / 2; + printf("val.getHiBits(%d) = ", bitsize); print(val.getHiBits(bitsize)); + printf("val.getLoBits(%d) = ", bitsize); print(val.getLoBits(bitsize)); + printf("val.isIntN(%d) = %d\n", bitwidth, val.isIntN(bitwidth)); + } + + void test_unops(const APInt &val) { + printf("UNARY OPERATORS TEST: val = "); print(val); + APInt x(val); + x++; + printf("val++ = "); print(x); + x = val; + ++x; + printf("++val = "); print(x); + x = val; + x--; + printf("val-- = "); print(x); + x = val; + --x; + printf("--val = "); print(x); + x = -val; + printf("-val = "); print(x); + x = ~val; + printf("~val = "); print(x); + printf("!val = %d\n", !val); + printf("val.isPowerOf2() = %d\n", val.isPowerOf2()); + printf("val.logBase2() = %d\n", val.logBase2()); + printf("val.countLeadingZeros() = %d\n", val.countLeadingZeros()); + printf("val.countTrailingZeros() = %d\n", val.countTrailingZeros()); + printf("val.countPopulation() = %d\n", val.countPopulation()); + printf("val.getBitWidth() = %d\n", val.getBitWidth()); + if (val.getBitWidth() >= 16 && val.getBitWidth() % 16 == 0) { + x = val.byteSwap(); + printf("val.byteSwap() = "); print(x); + } + printf("val.roundToDouble(false) = %f\n", val.roundToDouble(false)); + printf("val.roundToDouble(true) = %f\n", val.roundToDouble(true)); + printf("val.getValue() = "); + if (val.getBitWidth() > 64) + printf("too wide\n"); + else + printf("%lu\n", val.getValue()); + } + + void old_test_binops(const APInt &v1, const APInt &v2) { + printf("BINARY OPERATORS TEST: \n vl: "); print(v1,false,false); + printf("\n v2: "); print(v2); + APInt result(v1); + result &= v2; + printf("v1 &= v2: "); print(result); + result = v1; + result |= v2; + printf("v1 |= v2: "); print(result); + result = v1; + result ^= v2; + printf("v1 ^= v2: "); print(result); + result = v1; + result *= v2; + printf("v1 *= v2: "); print(result); + result = v1; + result += v2; + printf("v1 += v2: "); print(result); + result = v1; + result -= v2; + printf("v1 -= v2: "); print(result); + result = v1 & v2; + printf("v1 & v2: "); print(result); + result = v1 | v2; + printf("v1 | v2: "); print(result); + result = v1 ^ v2; + printf("v1 ^ v2: "); print(result); + result = v1 * v2; + printf("v1 * v2: "); print(result); + result = v1 + v2; + printf("v1 + v2: "); print(result); + result = v1 - v2; + printf("v1 - v2: "); print(result); + printf("v1 == v2: %d\n", v1 == v2); + printf("v1 != v2: %d\n", v1 != v2); + printf("v1.eq(v2): %d\n", v1.eq(v2)); + printf("v1.ne(v2): %d\n", v1.ne(v2)); + printf("v1.ult(v2): %d\n", v1.ult(v2)); + printf("v1.slt(v2): %d\n", v1.slt(v2)); + printf("v1.ule(v2): %d\n", v1.ule(v2)); + printf("v1.sle(v2): %d\n", v1.sle(v2)); + printf("v1.ugt(v2): %d\n", v1.ugt(v2)); + printf("v1.sgt(v2): %d\n", v1.sgt(v2)); + printf("v1.uge(v2): %d\n", v1.uge(v2)); + printf("v1.sge(v2): %d\n", v1.sge(v2)); + { + using namespace APIntOps; + unsigned shiftAmt = rand() % v1.getBitWidth(); + result = ashr(v1,shiftAmt); + printf("ashr(v1,%d) = ", shiftAmt); print(result); + result = lshr(v1,shiftAmt); + printf("lshr(v1,%d) = ", shiftAmt); print(result); + result = shl(v1,shiftAmt); + printf("shl(v1,%d) = ", shiftAmt); print(result); + if (v2 == APInt(v2.getBitWidth(), 0)) + printf("sdiv/udiv/srem/urem not tested, v2 == 0\n"); + else { + result = sdiv(v1,v2); + printf("sdiv(v1,v2) = "); print(result); + result = udiv(v1,v2); + printf("udiv(v1,v2) = "); print(result); + result = srem(v1,v2); + printf("srem(v1,v2) = "); print(result); + result = urem(v1,v2); + printf("urem(v1,v2) = "); print(result); + } + } + } + + static int input = 0, output = 0; + + std::string getBinopCmd(const APInt &v1, std::string op, const APInt &v2, + bool wantSigned = false) { + std::string Result; + Result += "truncate("; + Result += v1.toString(10,wantSigned); + Result += " " + op + " "; + Result += v2.toString(10,wantSigned); + Result += ")\n"; + return Result; + } + + std::string getResult(const std::string& cmd) { + const char *command = cmd.c_str(); + if (-1 == write(output, command, cmd.size())) { + std::string msg = "write: " + cmd; + perror(msg.c_str()); + exit(1); + } + usleep(1000); // try to switch contexts + char buf[1024]; + int len = read(input, buf, 1024); + if (-1 == len) { + std::string msg = "read: " + cmd; + perror(msg.c_str()); + exit(1); + } + // We're only interested in the last line. + if (char * nl = strrchr(buf, '\n')) { + *nl = 0; + if (char *nnl = strrchr(nl, '\n')) + return std::string(nnl+1); + } + return std::string(buf); + } + + void doMultiply(const APInt &v1, const APInt &v2) { + std::string cmd = getBinopCmd(v1, "*", v2); + std::string result = getResult(cmd); + APInt r = v1 * v2; + std::string apresult = r.toString(10, false); + if (result != apresult) { + printf("ERROR: "); + print(v1, false, false); + printf(" * "); + print(v2, false, false); + printf(" = %s (not %s)\n", result.c_str(), apresult.c_str()); + } + } + + void test_binops(const APInt &v1, const APInt &v2) { + doMultiply(v1, v2); + } + + void Shutdown() { + close(input); + close(output); + } + + /* function executed by the user-interacting process. */ + void test_driver(int input_pipe[], int output_pipe[]) { + + int c; /* user input - must be 'int', to recognize EOF (= -1). */ + char ch; /* the same - as a char. */ + int rc; /* return values of functions. */ + + /* first, close unnecessary file descriptors */ + close(input_pipe[1]); /* we don't need to write to this pipe. */ + close(output_pipe[0]); /* we don't need to read from this pipe. */ + + // Simplify input/output file descriptors + input = input_pipe[0]; + output = output_pipe[1]; + + // Make sure we close these to give gp an eof and terminate it + sys::SetInterruptFunction(Shutdown); + + // Initialize random number generator + srand(0); + + // Start loop over the range of bits of interest + for (unsigned bits = 1; bits <= 256; ++bits) { + // Indicate which test case we are running + printf("\nTEST CASE: %d BITS\n\n", bits); + // Gather some test data + APInt zero(bits,0); + APInt one(bits,1); + APInt two(bits,2); + APInt three(bits,3); + APInt min = APInt::getMinValue(bits, true); + APInt max = APInt::getMaxValue(bits, true); + APInt mid = APIntOps::lshr(max, bits/2); + APInt r1 = randomAPInt(bits); + APInt r2 = randomAPInt(bits); + APInt *list[9]; + list[0] = &zero; + list[1] = &one; + list[2] = &two; + list[3] = &three; + list[4] = &min; + list[5] = &r1; + list[6] = ∣ + list[7] = &r2; + list[8] = &max; + + // Generate and issue commands to calculator for + // all combinations of pairs of values. + for (unsigned i = 0; i < 9; ++i) { + for (unsigned j = 0; j < 9; ++j) { + test_binops(*(list[i]), *(list[j])); + } + } + } + + /* close pipes and exit. */ + Shutdown(); + exit(0); + } + + /* now comes the function executed by the translator process. */ + void calculator(int input_pipe[], int output_pipe[]) + { + int c; /* user input - must be 'int', to recognize EOF (= -1). */ + char ch; /* the same - as a char. */ + int rc; /* return values of functions. */ + + printf("In translator\n"); + + /* first, close unnecessary file descriptors */ + close(input_pipe[1]); /* we don't need to write to this pipe. */ + close(output_pipe[0]); /* we don't need to read from this pipe. */ + + /* set up the stdin/stdout */ + if (-1 == dup2(input_pipe[0], STDIN_FILENO)) { + perror("dup2 for stdin"); + exit(1); + } + if (-1 == dup2(output_pipe[1], STDOUT_FILENO)) { + perror("dup2 for stdout"); + exit(1); + } + + // exec gp with modes: + // --quiet (don't print banner), + // --fast (don't read init files) + // --test (no history, wrap long lines) + execlp("gp", "gp", "--quiet", "--fast", "--test", (char*)NULL); + perror("execlp"); + exit(1); + } + + /* and finally, the main function: spawn off two processes, */ + /* and let each of them execute its function. */ + int main(int argc, char* argv[]) + { + /* 2 arrays to contain file descriptors, for two pipes. */ + int user_to_translator[2]; + int translator_to_user[2]; + int pid; /* pid of child process, or 0, as returned via fork. */ + int rc; /* stores return values of various routines. */ + + /* first, create one pipe. */ + rc = pipe(user_to_translator); + if (rc == -1) { + perror("main: pipe user_to_translator"); + exit(1); + } + /* then, create another pipe. */ + rc = pipe(translator_to_user); + if (rc == -1) { + perror("main: pipe translator_to_user"); + exit(1); + } + + /* now fork off a child process, and set their handling routines. */ + pid = fork(); + + switch (pid) { + case -1: /* fork failed. */ + perror("main: fork"); + exit(1); + case 0: /* inside child process. */ + calculator(user_to_translator, translator_to_user); /* line 'A' */ + /* NOT REACHED */ + default: /* inside parent process. */ + test_driver(translator_to_user, user_to_translator); /* line 'B' */ + /* NOT REACHED */ + } + + return 0; /* NOT REACHED */ + } + _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits