Commit 57a8aab2 by Jim Stichnoth

Subzero: Enable Non-SFI vector cross tests.

The driver programs for vector tests use a loop to initialize vector-type values one element at a time. The PNaCl ABI requires the vector element index to be a constant, and the createConstantInsertExtractElementIndexPass() transformation creates an alloca instruction. When this alloca is inside a loop, it can (and does in the cross tests) cause a stack overflow. The workaround here is to use a noinline helper function to do the insertelement. We didn't run into this problem until now because native and sandbox cross tests build the driver in a different way that presumably avoids running the PNaCl ABI simplification passes. BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/1560933002 .
parent 8ff4b281
......@@ -405,7 +405,7 @@ check-xtest: $(OBJDIR)/pnacl-sz make_symlink runtime
-i x8632,native,sse2 \
-i x8632,native,sse4.1,test_vector_ops \
-i x8632,sandbox,sse4.1,Om1 \
-i x8632,nonsfi,sse2,O2 -e x8632,nonsfi,test_select \
-i x8632,nonsfi,sse2,O2 \
-i x8664,native,sse2 \
-i x8664,native,sse4.1,test_vector_ops \
-e x8664,sandbox,sse4.1,Om1 \
......
//===- subzero/crosstest/insertelement.h - Helper for PNaCl workaround. ---===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Helper function to work around a potential stack overflow issue.
//
//===----------------------------------------------------------------------===//
#ifndef INSERTELEMENT_H
#define INSERTELEMENT_H
// Helper function to perform the insertelement bitcode instruction. The PNaCl
// ABI simplifications transform insertelement/extractelement instructions with
// a non-constant index into something involving alloca. This can cause a stack
// overflow if the alloca is inside a loop.
template <typename VectorType, typename ElementType>
void __attribute__((noinline))
setElement(VectorType &Value, size_t Index, ElementType Element) {
Value[Index] = Element;
}
#endif // INSERTELEMENT_H
......@@ -28,12 +28,14 @@
// Subzero_ namespace, corresponding to the llc and Subzero translated
// object files, respectively.
#include "test_arith.h"
#include "xdefs.h"
namespace Subzero_ {
#include "test_arith.h"
}
#include "insertelement.h"
#include "xdefs.h"
template <class T> bool inputsMayTriggerException(T Value1, T Value2) {
// Avoid HW divide-by-zero exception.
if (Value2 == 0)
......@@ -162,7 +164,7 @@ const static size_t MaxTestsPerFunc = 100000;
template <typename TypeUnsignedLabel, typename TypeSignedLabel>
void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
#if !defined(ARM32) && !defined(NONSFI)
#if !defined(ARM32)
// TODO(jpp): remove this once vector support is implemented.
typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned;
typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned;
......@@ -212,8 +214,8 @@ void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
continue;
if (Funcs[f].MaskShiftOperations)
Element2 &= CHAR_BIT * sizeof(ElementTypeUnsigned) - 1;
Value1[j] = Element1;
Value2[j] = Element2;
setElement(Value1, j, Element1);
setElement(Value2, j, Element2);
}
// Perform the test.
TypeUnsigned ResultSz, ResultLlc;
......@@ -239,7 +241,7 @@ void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
}
}
}
#endif // !ARM32 && !NONSFI
#endif // !ARM32
}
template <typename Type>
......@@ -315,7 +317,7 @@ void testsFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
}
void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
#if !defined(ARM32) && !defined(NONSFI)
#if !defined(ARM32)
// TODO(jpp): remove this once vector support is implemented.
static const float NegInf = -1.0 / 0.0;
static const float PosInf = 1.0 / 0.0;
......@@ -343,8 +345,8 @@ void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
// Initialize the test vectors.
v4f32 Value1, Value2;
for (size_t j = 0; j < NumElementsInType; ++j) {
Value1[j] = Values[Index() % NumValues];
Value2[j] = Values[Index() % NumValues];
setElement(Value1, j, Values[Index() % NumValues]);
setElement(Value2, j, Values[Index() % NumValues]);
}
// Perform the test.
v4f32 ResultSz = Funcs[f].FuncSz(Value1, Value2);
......@@ -375,7 +377,7 @@ void testsVecFp(size_t &TotalTests, size_t &Passes, size_t &Failures) {
}
}
}
#endif // !ARM32 && !NONSFI
#endif // !ARM32
}
#ifdef X8664_STACK_HACK
......
......@@ -28,6 +28,7 @@ namespace Subzero_ {
#include "test_icmp.h"
}
#include "insertelement.h"
#include "xdefs.h"
volatile unsigned Values[] = {
......@@ -197,10 +198,12 @@ const static size_t MaxTestsPerFunc = 100000;
template <typename TypeUnsignedLabel, typename TypeSignedLabel>
void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
#if !defined(ARM32) && !defined(NONSFI)
#if !defined(ARM32)
// TODO(jpp): remove this once vector support is implemented.
typedef typename Vectors<TypeUnsignedLabel>::Ty TypeUnsigned;
typedef typename Vectors<TypeSignedLabel>::Ty TypeSigned;
typedef typename Vectors<TypeUnsignedLabel>::ElementTy ElementTypeUnsigned;
typedef typename Vectors<TypeSignedLabel>::ElementTy ElementTypeSigned;
typedef TypeUnsigned (*FuncTypeUnsigned)(TypeUnsigned, TypeUnsigned);
typedef TypeSigned (*FuncTypeSigned)(TypeSigned, TypeSigned);
static struct {
......@@ -232,10 +235,9 @@ void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
for (size_t i = 0; i < MaxTestsPerFunc; ++i) {
// Initialize the test vectors.
TypeUnsigned Value1, Value2;
for (size_t j = 0; j < NumElementsInType;) {
Value1[j] = Values[Index() % NumValues];
Value2[j] = Values[Index() % NumValues];
++j;
for (size_t j = 0; j < NumElementsInType; ++j) {
setElement(Value1, j, Values[Index() % NumValues]);
setElement(Value2, j, Values[Index() % NumValues]);
}
// Perform the test.
TypeUnsigned ResultSz = Funcs[f].FuncSz(Value1, Value2);
......@@ -255,11 +257,13 @@ void testsVecInt(size_t &TotalTests, size_t &Passes, size_t &Failures) {
}
}
}
#endif // !ARM32 && !NONSFI
#endif // !ARM32
}
// Return true on wraparound
template <typename T> bool incrementI1Vector(typename Vectors<T>::Ty &Vect) {
template <typename T>
bool __attribute__((noinline))
incrementI1Vector(typename Vectors<T>::Ty &Vect) {
size_t Pos = 0;
const static size_t NumElements = Vectors<T>::NumElements;
for (Pos = 0; Pos < NumElements; ++Pos) {
......@@ -274,7 +278,7 @@ template <typename T> bool incrementI1Vector(typename Vectors<T>::Ty &Vect) {
template <typename T>
void testsVecI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
#if !defined(ARM32) && !defined(NONSFI)
#if !defined(ARM32)
// TODO(jpp): remove this once vector support is implemented.
typedef typename Vectors<T>::Ty Ty;
typedef Ty (*FuncType)(Ty, Ty);
......@@ -324,8 +328,8 @@ void testsVecI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
Ty Value1, Value2;
// Initialize the test vectors.
for (size_t j = 0; j < NumElements; ++j) {
Value1[j] = Index() % 2;
Value2[j] = Index() % 2;
setElement(Value1, j, Index() % 2);
setElement(Value2, j, Index() % 2);
}
// Perform the test.
Ty ResultSz = Funcs[f].FuncSz(Value1, Value2);
......@@ -343,7 +347,7 @@ void testsVecI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
}
}
}
#endif // !ARM32 && !NONSFI
#endif // !ARM32
}
#ifdef X8664_STACK_HACK
......
......@@ -25,6 +25,8 @@ namespace Subzero_ {
#include "test_select.h"
}
#include "insertelement.h"
static const size_t MaxTestsPerFunc = 100000;
template <typename T, typename TI1>
......@@ -43,9 +45,9 @@ void testSelect(size_t &TotalTests, size_t &Passes, size_t &Failures) {
TyI1 Cond;
Ty Value1, Value2;
for (size_t j = 0; j < NumElements; ++j) {
Cond[j] = Index() % 2;
Value1[j] = Values[Index() % NumValues];
Value2[j] = Values[Index() % NumValues];
setElement(Cond, j, Index() % 2);
setElement(Value1, j, Values[Index() % NumValues]);
setElement(Value2, j, Values[Index() % NumValues]);
}
Ty ResultLlc = select(Cond, Value1, Value2);
Ty ResultSz = Subzero_::select(Cond, Value1, Value2);
......@@ -79,9 +81,9 @@ void testSelect<v4f32, v4i1>(size_t &TotalTests, size_t &Passes,
v4si32 Cond;
v4f32 Value1, Value2;
for (size_t j = 0; j < NumElements; ++j) {
Cond[j] = Index() % 2;
Value1[j] = Values[Index() % NumValues];
Value2[j] = Values[Index() % NumValues];
setElement(Cond, j, Index() % 2);
setElement(Value1, j, Values[Index() % NumValues]);
setElement(Value2, j, Values[Index() % NumValues]);
}
v4f32 ResultLlc = select(Cond, Value1, Value2);
v4f32 ResultSz = Subzero_::select(Cond, Value1, Value2);
......@@ -109,9 +111,9 @@ void testSelectI1(size_t &TotalTests, size_t &Passes, size_t &Failures) {
Ty Cond;
Ty Value1, Value2;
for (size_t j = 0; j < NumElements; ++j) {
Cond[j] = Index() % 2;
Value1[j] = Index() % 2;
Value2[j] = Index() % 2;
setElement(Cond, j, Index() % 2);
setElement(Value1, j, Index() % 2);
setElement(Value2, j, Index() % 2);
}
Ty ResultLlc = select_i1(Cond, Value1, Value2);
Ty ResultSz = Subzero_::select_i1(Cond, Value1, Value2);
......
......@@ -126,7 +126,6 @@ def main():
bitcode = os.path.join(args.dir, base + '.' + key + '.pnacl.ll')
shellcmd(['{bin}/pnacl-clang'.format(bin=bindir),
('-O2' if args.clang_opt else '-O0'),
get_sfi_string(args, '', '-DNONSFI', ''),
('-DARM32' if args.target == 'arm32' else ''), '-c', arg,
'-o', bitcode_nonfinal])
shellcmd(['{bin}/pnacl-opt'.format(bin=bindir),
......@@ -211,8 +210,6 @@ def main():
if args.target == 'arm32':
target_params.append('-DARM32')
target_params.append('-static')
if args.nonsfi:
target_params.append('-DNONSFI')
pure_c = os.path.splitext(args.driver)[1] == '.c'
if not args.nonsfi:
......@@ -242,7 +239,6 @@ def main():
cc='clang' if pure_c else 'clang++')
shellcmd([compiler,
args.driver,
'-DNONSFI' if args.nonsfi else '',
'-O2',
'-o', bitcode_nonfinal,
'-Wl,-r'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment