Commit a7979bfd by Jaydeep Patil Committed by Jim Stichnoth

[SubZero] Fix f64 to/from i64 moves

The allocation of Hi/Lo part of i64 on stack has been corrected as per MIPS32 ABI. The patch also fixes ZEXT issues occurred while lowering unsigned operations. Following tests from cross-test framework were testing successfully: (non-vector, ASM mode, Om1, O2) mem_intrin TotalTests=114300 Passes=114300 Failures=0 simple_loop TotalTests=102 Passes=102 Failures=0 test_arith TotalTests=49489704 Passes=49489704 Failures=0 test_bitmanip TotalTests=1200 Passes=1200 Failures=0 test_cast TotalTests=3722 Passes=3722 Failures=0 test_fcmp TotalTests=123904 Passes=123904 Failures=0 test_global TotalTests=270 Passes=270 Failures=0 test_icmp TotalTests=3341520 Passes=3341520 Failures=0 test_strengthreduce TotalTests=240 Passes=240 Failures=0 Following tests are disabled as they are either all-vectors or contain unimplemented intrinsic lowering: test_calling_conv test_select test_stacksave test_sync_atomic test_vector_ops There are couple of fixes to ARM32 and X86 specific files occurred due to compile-time errors. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2432373002 . Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
parent a3688eaf
......@@ -28,6 +28,20 @@ ToType __attribute__((noinline)) castBits(FromType a) {
return *(ToType *)&a;
}
template <typename FromType, typename ToType>
ToType __attribute__((noinline)) cast(int i, FromType a, int j) {
(void)i;
(void)j;
return (ToType)a;
}
template <typename FromType, typename ToType>
ToType __attribute__((noinline)) castBits(int i, FromType a, int j) {
(void)i;
(void)j;
return *(ToType *)&a;
}
// The purpose of the following sets of templates is to force
// cast<A,B>() to be instantiated in the resulting bitcode file for
// all <A,B>, so that they can be called from the driver.
......@@ -43,6 +57,17 @@ template <typename ToType> class Caster {
static ToType f(uint64 a) { return cast<uint64, ToType>(a); }
static ToType f(float a) { return cast<float, ToType>(a); }
static ToType f(double a) { return cast<double, ToType>(a); }
static ToType f(int i, bool a) { return cast<bool, ToType>(i, a, i); }
static ToType f(int i, myint8_t a) { return cast<myint8_t, ToType>(i, a, i); }
static ToType f(int i, uint8_t a) { return cast<uint8_t, ToType>(i, a, i); }
static ToType f(int i, int16_t a) { return cast<int16_t, ToType>(i, a, i); }
static ToType f(int i, uint16_t a) { return cast<uint16_t, ToType>(i, a, i); }
static ToType f(int i, int32_t a) { return cast<int32_t, ToType>(i, a, i); }
static ToType f(int i, uint32_t a) { return cast<uint32_t, ToType>(i, a, i); }
static ToType f(int i, int64 a) { return cast<int64, ToType>(i, a, i); }
static ToType f(int i, uint64 a) { return cast<uint64, ToType>(i, a, i); }
static ToType f(int i, float a) { return cast<float, ToType>(i, a, i); }
static ToType f(int i, double a) { return cast<double, ToType>(i, a, i); }
};
// Comment out the definition of Caster<bool> because clang compiles
......@@ -71,5 +96,9 @@ double makeBitCasters() {
Result += castBits<uint64, double>(0);
Result += castBits<float, uint32_t>(0);
Result += castBits<double, uint64>(0);
Result += castBits<uint32_t, float>(1, 0, 2);
Result += castBits<uint64, double>(1, 0, 2);
Result += castBits<float, uint32_t>(1, 0, 2);
Result += castBits<double, uint64>(1, 0, 2);
return Result;
}
......@@ -21,3 +21,12 @@ typedef signed char myint8_t;
template <typename FromType, typename ToType> ToType cast(FromType a);
template <typename FromType, typename ToType> ToType castBits(FromType a);
// Targets like MIPS32, pass floating-point arguments in general purpose
// registers when the first argument is passed in a general purpose register.
// Overloaded cast and castBits functions take two extra integer argument to
// check proper conversion of floating-point to/from general purpose registers.
template <typename FromType, typename ToType>
ToType cast(int i, FromType a, int j);
template <typename FromType, typename ToType>
ToType castBits(int i, FromType a, int j);
......@@ -54,6 +54,26 @@ namespace Subzero_ {
} \
} while (0)
#define COMPARE_ARG(Func, FromCName, ToCName, Input, FromString) \
do { \
ToCName ResultSz, ResultLlc; \
ResultLlc = Func<FromCName, ToCName>(1, Input, 2); \
ResultSz = Subzero_::Func<FromCName, ToCName>(1, Input, 2); \
++TotalTests; \
if (!memcmp(&ResultLlc, &ResultSz, sizeof(ToCName))) { \
++Passes; \
} else { \
++Failures; \
std::cout << std::fixed << XSTR(Func) << "<" << FromString \
<< ", " XSTR(ToCName) ">(" << Input << "): "; \
if (sizeof(ToCName) == 1) \
std::cout << "sz=" << (int)ResultSz << " llc=" << (int)ResultLlc; \
else \
std::cout << "sz=" << ResultSz << " llc=" << ResultLlc; \
std::cout << "\n"; \
} \
} while (0)
#define COMPARE_VEC(Func, FromCName, ToCName, Input, FromString, ToString) \
do { \
ToCName ResultSz, ResultLlc; \
......@@ -87,6 +107,17 @@ void testValue(FromType Val, size_t &TotalTests, size_t &Passes,
COMPARE(cast, FromType, int64, Val, FromTypeString);
COMPARE(cast, FromType, float, Val, FromTypeString);
COMPARE(cast, FromType, double, Val, FromTypeString);
COMPARE_ARG(cast, FromType, bool, Val, FromTypeString);
COMPARE_ARG(cast, FromType, uint8_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, myint8_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, uint16_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, int16_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, uint32_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, int32_t, Val, FromTypeString);
COMPARE_ARG(cast, FromType, uint64, Val, FromTypeString);
COMPARE_ARG(cast, FromType, int64, Val, FromTypeString);
COMPARE_ARG(cast, FromType, float, Val, FromTypeString);
COMPARE_ARG(cast, FromType, double, Val, FromTypeString);
}
template <typename FromType, typename ToType>
......@@ -198,6 +229,7 @@ int main(int argc, char *argv[]) {
uint32_t Val = ValsUi32[i];
testValue<uint32_t>(Val, TotalTests, Passes, Failures, "uint32_t");
COMPARE(castBits, uint32_t, float, Val, "uint32_t");
COMPARE_ARG(castBits, uint32_t, float, Val, "uint32_t");
}
for (size_t i = 0; i < NumValsSi32; ++i) {
int32_t Val = ValsSi32[i];
......@@ -207,6 +239,7 @@ int main(int argc, char *argv[]) {
uint64 Val = ValsUi64[i];
testValue<uint64>(Val, TotalTests, Passes, Failures, "uint64");
COMPARE(castBits, uint64, double, Val, "uint64");
COMPARE_ARG(castBits, uint64, double, Val, "uint64");
}
for (size_t i = 0; i < NumValsSi64; ++i) {
int64 Val = ValsSi64[i];
......@@ -219,6 +252,7 @@ int main(int argc, char *argv[]) {
Val = -Val;
testValue<float>(Val, TotalTests, Passes, Failures, "float");
COMPARE(castBits, float, uint32_t, Val, "float");
COMPARE_ARG(castBits, float, uint32_t, Val, "float");
}
}
for (size_t i = 0; i < NumValsF64; ++i) {
......@@ -228,8 +262,10 @@ int main(int argc, char *argv[]) {
Val = -Val;
testValue<double>(Val, TotalTests, Passes, Failures, "double");
COMPARE(castBits, double, uint64, Val, "double");
COMPARE_ARG(castBits, double, uint64, Val, "double");
}
}
testVector<v4ui32, v4f32>(TotalTests, Passes, Failures, "v4ui32", "v4f32");
testVector<v4si32, v4f32>(TotalTests, Passes, Failures, "v4si32", "v4f32");
testVector<v4f32, v4si32>(TotalTests, Passes, Failures, "v4f32", "v4si32");
......
......@@ -90,3 +90,92 @@ entry:
%tobool.ret_ext = zext i1 %tobool.i1 to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIbbET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%a.arg_trunc = trunc i32 %a to i1
%a.arg_trunc.ret_ext = zext i1 %a.arg_trunc to i32
ret i32 %a.arg_trunc.ret_ext
}
define internal i32 @_Z4castIabET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%a.arg_trunc = trunc i32 %a to i8
; %tobool = icmp ne i8 %a.arg_trunc, 0
%tobool = trunc i8 %a.arg_trunc to i1
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIhbET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%a.arg_trunc = trunc i32 %a to i8
; %tobool = icmp ne i8 %a.arg_trunc, 0
%tobool = trunc i8 %a.arg_trunc to i1
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIsbET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%a.arg_trunc = trunc i32 %a to i16
; %tobool = icmp ne i16 %a.arg_trunc, 0
%tobool = trunc i16 %a.arg_trunc to i1
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castItbET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%a.arg_trunc = trunc i32 %a to i16
; %tobool = icmp ne i16 %a.arg_trunc, 0
%tobool = trunc i16 %a.arg_trunc to i1
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIibET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%tobool = icmp ne i32 %a, 0
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIjbET0_iT_i(i32 %i, i32 %a, i32 %j) {
entry:
%tobool = icmp ne i32 %a, 0
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIxbET0_iT_i(i32 %i, i64 %a, i32 %j) {
entry:
%tobool = icmp ne i64 %a, 0
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIybET0_iT_i(i32 %i, i64 %a, i32 %j) {
entry:
%tobool = icmp ne i64 %a, 0
%tobool.ret_ext = zext i1 %tobool to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIfbET0_iT_i(i32 %i, float %a, i32 %j) {
entry:
; %tobool = fcmp une float %a, 0.000000e+00
%tobool = fptoui float %a to i32
%tobool.i1 = trunc i32 %tobool to i1
%tobool.ret_ext = zext i1 %tobool.i1 to i32
ret i32 %tobool.ret_ext
}
define internal i32 @_Z4castIdbET0_iT_i(i32 %i, double %a, i32 %j) {
entry:
; %tobool = fcmp une double %a, 0.000000e+00
%tobool = fptoui double %a to i32
%tobool.i1 = trunc i32 %tobool to i1
%tobool.ret_ext = zext i1 %tobool.i1 to i32
ret i32 %tobool.ret_ext
}
......@@ -127,6 +127,7 @@ def main():
shellcmd(['{bin}/pnacl-clang'.format(bin=bindir),
('-O2' if args.clang_opt else '-O0'),
('-DARM32' if args.target == 'arm32' else ''), '-c', arg,
('-DMIPS32' if args.target == 'mips32' else ''),
'-o', bitcode_nonfinal])
shellcmd(['{bin}/pnacl-opt'.format(bin=bindir),
'-pnacl-abi-simplify-preopt',
......@@ -208,6 +209,9 @@ def main():
target_params.append('-DARM32')
target_params.append('-static')
if args.target == 'mips32':
target_params.append('-DMIPS32')
pure_c = os.path.splitext(args.driver)[1] == '.c'
if not args.nonsfi:
# Set compiler to clang, clang++, pnacl-clang, or pnacl-clang++.
......
......@@ -89,7 +89,8 @@ entry:
; MIPS32: ldc1 {{.*}}, %lo(.L$double$0012345678901234)({{.*}})
; MIPS32-O2: mfc1 $v1, $f{{[0-9]+}}
; MIPS32-O2: mfc1 $v0, $f{{[0-9]+}}
; MIPS32-OM1: sdc1
; MIPS32-OM1: mfc1
; MIPS32-OM1: mfc1
; MIPS32-OM1: lw
; MIPS32-OM1: lw
......
......@@ -77,11 +77,10 @@ entry:
; CHECK: movsd
; MIPS32-LABEL: storeDouble
; MIPS32: ldc1 $f{{.*}},4{{.*}}
; MIPS32: sdc1 $f{{.*}},0{{.*}}
; MIPS32O2-LABEL: storeDouble
; MIPS32O2: mtc1 a3,$f{{.*}}
; MIPS32O2: mtc1 a2,$f{{.*}}
; MIPS32O2: mtc1 a3,$f{{.*}}
; MIPS32O2: sdc1 $f{{.*}},0(a0)
define internal void @storeFloatConst(i32 %a) {
......
......@@ -24,8 +24,9 @@ entry:
}
; MIPS32-LABEL: load_i64
; MIPS32: lw {{.*}},0({{.*}})
; MIPS32-NEXT: lw {{.*}},4({{.*}})
; MIPS32: lw [[BASE:.*]],
; MIPS32-NEXT: lw {{.*}},0([[BASE]])
; MIPS32-NEXT: lw {{.*}},4([[BASE]])
define internal void @load_i32(i32 %addr_arg) {
entry:
......
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