1//===- subzero/crosstest/test_fcmp_main.cpp - Driver for tests ------------===//
2//
3//                        The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Driver for cross testing the fcmp bitcode instruction
11//
12//===----------------------------------------------------------------------===//
13
14/* crosstest.py --test=test_fcmp.pnacl.ll --driver=test_fcmp_main.cpp \
15   --prefix=Subzero_ --output=test_fcmp */
16
17#include <cassert>
18#include <cfloat>
19#include <cmath>
20#include <cstring>
21#include <iostream>
22
23#include "vectors.h"
24#include "test_arith.def"
25#include "test_fcmp.def"
26
27#define X(cmp)                                                                 \
28  extern "C" bool fcmp##cmp##Float(float a, float b);                          \
29  extern "C" bool fcmp##cmp##Double(double a, double b);                       \
30  extern "C" int fcmpSelect##cmp##Float(float a, float b, int c, int d);       \
31  extern "C" int fcmpSelect##cmp##Double(double a, double b, int c, int d);    \
32  extern "C" v4si32 fcmp##cmp##Vector(v4f32 a, v4f32 b);                       \
33  extern "C" bool Subzero_fcmp##cmp##Float(float a, float b);                  \
34  extern "C" bool Subzero_fcmp##cmp##Double(double a, double b);               \
35  extern "C" int Subzero_fcmpSelect##cmp##Float(float a, float b, int c,       \
36                                                int d);                        \
37  extern "C" int Subzero_fcmpSelect##cmp##Double(double a, double b, int c,    \
38                                                 int d);                       \
39  extern "C" v4si32 Subzero_fcmp##cmp##Vector(v4f32 a, v4f32 b);
40FCMP_TABLE;
41#undef X
42
43volatile double *Values;
44size_t NumValues;
45
46void initializeValues() {
47  static const double NegInf = -1.0 / 0.0;
48  static const double Zero = 0.0;
49  static const double PosInf = 1.0 / 0.0;
50  static const double Nan = 0.0 / 0.0;
51  static const double NegNan = -0.0 / 0.0;
52  assert(std::fpclassify(NegInf) == FP_INFINITE);
53  assert(std::fpclassify(PosInf) == FP_INFINITE);
54  assert(std::fpclassify(Nan) == FP_NAN);
55  assert(std::fpclassify(NegNan) == FP_NAN);
56  assert(NegInf < Zero);
57  assert(NegInf < PosInf);
58  assert(Zero < PosInf);
59  static volatile double InitValues[] =
60      FP_VALUE_ARRAY(NegInf, PosInf, NegNan, Nan);
61  NumValues = sizeof(InitValues) / sizeof(*InitValues);
62  Values = InitValues;
63}
64
65void testsScalar(size_t &TotalTests, size_t &Passes, size_t &Failures) {
66  typedef bool (*FuncTypeFloat)(float, float);
67  typedef bool (*FuncTypeDouble)(double, double);
68  typedef int (*FuncTypeFloatSelect)(float, float, int, int);
69  typedef int (*FuncTypeDoubleSelect)(double, double, int, int);
70  static struct {
71    const char *Name;
72    FuncTypeFloat FuncFloatSz;
73    FuncTypeFloat FuncFloatLlc;
74    FuncTypeDouble FuncDoubleSz;
75    FuncTypeDouble FuncDoubleLlc;
76    FuncTypeFloatSelect FuncFloatSelectSz;
77    FuncTypeFloatSelect FuncFloatSelectLlc;
78    FuncTypeDoubleSelect FuncDoubleSelectSz;
79    FuncTypeDoubleSelect FuncDoubleSelectLlc;
80  } Funcs[] = {
81#define X(cmp)                                                                 \
82  {                                                                            \
83    "fcmp" STR(cmp), Subzero_fcmp##cmp##Float, fcmp##cmp##Float,               \
84        Subzero_fcmp##cmp##Double, fcmp##cmp##Double,                          \
85        Subzero_fcmpSelect##cmp##Float, fcmpSelect##cmp##Float,                \
86        Subzero_fcmpSelect##cmp##Double, fcmpSelect##cmp##Double               \
87  }                                                                            \
88  ,
89      FCMP_TABLE
90#undef X
91  };
92  const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
93
94  bool ResultSz, ResultLlc;
95
96  assert(Values && NumValues);
97
98  for (size_t f = 0; f < NumFuncs; ++f) {
99    for (size_t i = 0; i < NumValues; ++i) {
100      for (size_t j = 0; j < NumValues; ++j) {
101        ++TotalTests;
102        float Value1Float = Values[i];
103        float Value2Float = Values[j];
104        ResultSz = Funcs[f].FuncFloatSz(Value1Float, Value2Float);
105        ResultLlc = Funcs[f].FuncFloatLlc(Value1Float, Value2Float);
106        if (ResultSz == ResultLlc) {
107          ++Passes;
108        } else {
109          ++Failures;
110          std::cout << Funcs[f].Name << "Float(" << Value1Float << ", "
111                    << Value2Float << "): sz=" << ResultSz
112                    << " llc=" << ResultLlc << "\n";
113        }
114        ++TotalTests;
115        double Value1Double = Values[i];
116        double Value2Double = Values[j];
117        ResultSz = Funcs[f].FuncDoubleSz(Value1Double, Value2Double);
118        ResultLlc = Funcs[f].FuncDoubleLlc(Value1Double, Value2Double);
119        if (ResultSz == ResultLlc) {
120          ++Passes;
121        } else {
122          ++Failures;
123          std::cout << Funcs[f].Name << "Double(" << Value1Double << ", "
124                    << Value2Double << "): sz=" << ResultSz
125                    << " llc=" << ResultLlc << "\n";
126        }
127        ++TotalTests;
128        float Value1SelectFloat = Values[i];
129        float Value2SelectFloat = Values[j];
130        ResultSz = Funcs[f].FuncFloatSelectSz(Value1Float, Value2Float, 1, 2);
131        ResultLlc = Funcs[f].FuncFloatSelectLlc(Value1Float, Value2Float, 1, 2);
132        if (ResultSz == ResultLlc) {
133          ++Passes;
134        } else {
135          ++Failures;
136          std::cout << Funcs[f].Name << "SelectFloat(" << Value1Float << ", "
137                    << Value2Float << "): sz=" << ResultSz
138                    << " llc=" << ResultLlc << "\n";
139        }
140        ++TotalTests;
141        double Value1SelectDouble = Values[i];
142        double Value2SelectDouble = Values[j];
143        ResultSz =
144            Funcs[f].FuncDoubleSelectSz(Value1Double, Value2Double, 1, 2);
145        ResultLlc =
146            Funcs[f].FuncDoubleSelectLlc(Value1Double, Value2Double, 1, 2);
147        if (ResultSz == ResultLlc) {
148          ++Passes;
149        } else {
150          ++Failures;
151          std::cout << Funcs[f].Name << "SelectDouble(" << Value1Double << ", "
152                    << Value2Double << "): sz=" << ResultSz
153                    << " llc=" << ResultLlc << "\n";
154        }
155      }
156    }
157  }
158}
159
160void testsVector(size_t &TotalTests, size_t &Passes, size_t &Failures) {
161  typedef v4si32 (*FuncTypeVector)(v4f32, v4f32);
162  static struct {
163    const char *Name;
164    FuncTypeVector FuncVectorSz;
165    FuncTypeVector FuncVectorLlc;
166  } Funcs[] = {
167#define X(cmp)                                                                 \
168  { "fcmp" STR(cmp), Subzero_fcmp##cmp##Vector, fcmp##cmp##Vector }            \
169  ,
170      FCMP_TABLE
171#undef X
172  };
173  const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs);
174  const static size_t NumElementsInType = 4;
175  const static size_t MaxTestsPerFunc = 100000;
176
177  assert(Values && NumValues);
178
179  for (size_t f = 0; f < NumFuncs; ++f) {
180    PRNG Index;
181    for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
182      v4f32 Value1, Value2;
183      for (size_t j = 0; j < NumElementsInType; ++j) {
184        Value1[j] = Values[Index() % NumValues];
185        Value2[j] = Values[Index() % NumValues];
186      }
187      ++TotalTests;
188      v4si32 ResultSz, ResultLlc;
189      ResultSz = Funcs[f].FuncVectorSz(Value1, Value2);
190      ResultLlc = Funcs[f].FuncVectorLlc(Value1, Value2);
191      if (!memcmp(&ResultSz, &ResultLlc, sizeof(ResultSz))) {
192        ++Passes;
193      } else {
194        ++Failures;
195        std::cout << Funcs[f].Name << "Vector(" << vectAsString<v4f32>(Value1)
196                  << ", " << vectAsString<v4f32>(Value2)
197                  << "): sz=" << vectAsString<v4si32>(ResultSz)
198                  << " llc=" << vectAsString<v4si32>(ResultLlc) << "\n";
199      }
200    }
201  }
202}
203
204int main(int argc, char *argv[]) {
205  size_t TotalTests = 0;
206  size_t Passes = 0;
207  size_t Failures = 0;
208
209  initializeValues();
210
211  testsScalar(TotalTests, Passes, Failures);
212  testsVector(TotalTests, Passes, Failures);
213
214  std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes
215            << " Failures=" << Failures << "\n";
216  return Failures;
217}
218