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);
40 FCMP_TABLE;
41 #undef X
42
43 volatile double *Values;
44 size_t NumValues;
45
initializeValues()46 void 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
testsScalar(size_t & TotalTests,size_t & Passes,size_t & Failures)65 void 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
testsVector(size_t & TotalTests,size_t & Passes,size_t & Failures)160 void 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
main(int argc,char * argv[])204 int 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