Fix problems due to generating Neon instructions on non-Neon capable
hosts:
* iselNeon64Expr, iselNeonExpr: assert that the host is actually
Neon-capable.
* iselIntExpr_R_wrk, existing cases for Iop_GetElem8x8,
Iop_GetElem16x4, Iop_GetElem32x2, Iop_GetElem8x16, Iop_GetElem16x8,
Iop_GetElem32x4:
Limit these to cases where the host is Neon capable, else we wind up
generating code which can't run on the host.
* iselIntExpr_R_wrk: add alternative implementation for
Iop_GetElem32x2 for non-Neon capable hosts.
git-svn-id: svn://svn.valgrind.org/vex/trunk@3098 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_arm_isel.c b/priv/host_arm_isel.c
index c55d83b..023fb74 100644
--- a/priv/host_arm_isel.c
+++ b/priv/host_arm_isel.c
@@ -1373,51 +1373,70 @@
if (e->Iex.Binop.op == Iop_GetElem8x8
|| e->Iex.Binop.op == Iop_GetElem16x4
|| e->Iex.Binop.op == Iop_GetElem32x2) {
- HReg res = newVRegI(env);
- HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1);
- UInt index, size;
- if (e->Iex.Binop.arg2->tag != Iex_Const ||
- typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) {
- vpanic("ARM target supports GetElem with constant "
- "second argument only\n");
+ if (env->hwcaps & VEX_HWCAPS_ARM_NEON) {
+ HReg res = newVRegI(env);
+ HReg arg = iselNeon64Expr(env, e->Iex.Binop.arg1);
+ UInt index, size;
+ if (e->Iex.Binop.arg2->tag != Iex_Const ||
+ typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) {
+ vpanic("ARM target supports GetElem with constant "
+ "second argument only (neon)\n");
+ }
+ index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
+ switch (e->Iex.Binop.op) {
+ case Iop_GetElem8x8: vassert(index < 8); size = 0; break;
+ case Iop_GetElem16x4: vassert(index < 4); size = 1; break;
+ case Iop_GetElem32x2: vassert(index < 2); size = 2; break;
+ default: vassert(0);
+ }
+ addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS,
+ mkARMNRS(ARMNRS_Reg, res, 0),
+ mkARMNRS(ARMNRS_Scalar, arg, index),
+ size, False));
+ return res;
}
- index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
- switch (e->Iex.Binop.op) {
- case Iop_GetElem8x8: vassert(index < 8); size = 0; break;
- case Iop_GetElem16x4: vassert(index < 4); size = 1; break;
- case Iop_GetElem32x2: vassert(index < 2); size = 2; break;
- default: vassert(0);
+ }
+
+ if (e->Iex.Binop.op == Iop_GetElem32x2
+ && e->Iex.Binop.arg2->tag == Iex_Const
+ && !(env->hwcaps & VEX_HWCAPS_ARM_NEON)) {
+ /* We may have to do GetElem32x2 on a non-NEON capable
+ target. */
+ IRConst* con = e->Iex.Binop.arg2->Iex.Const.con;
+ vassert(con->tag == Ico_U8); /* else IR is ill-typed */
+ UInt index = con->Ico.U8;
+ if (index >= 0 && index <= 1) {
+ HReg rHi, rLo;
+ iselInt64Expr(&rHi, &rLo, env, e->Iex.Binop.arg1);
+ return index == 0 ? rLo : rHi;
}
- addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS,
- mkARMNRS(ARMNRS_Reg, res, 0),
- mkARMNRS(ARMNRS_Scalar, arg, index),
- size, False));
- return res;
}
if (e->Iex.Binop.op == Iop_GetElem8x16
|| e->Iex.Binop.op == Iop_GetElem16x8
|| e->Iex.Binop.op == Iop_GetElem32x4) {
- HReg res = newVRegI(env);
- HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1);
- UInt index, size;
- if (e->Iex.Binop.arg2->tag != Iex_Const ||
- typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) {
- vpanic("ARM target supports GetElem with constant "
- "second argument only\n");
+ if (env->hwcaps & VEX_HWCAPS_ARM_NEON) {
+ HReg res = newVRegI(env);
+ HReg arg = iselNeonExpr(env, e->Iex.Binop.arg1);
+ UInt index, size;
+ if (e->Iex.Binop.arg2->tag != Iex_Const ||
+ typeOfIRExpr(env->type_env, e->Iex.Binop.arg2) != Ity_I8) {
+ vpanic("ARM target supports GetElem with constant "
+ "second argument only (neon)\n");
+ }
+ index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
+ switch (e->Iex.Binop.op) {
+ case Iop_GetElem8x16: vassert(index < 16); size = 0; break;
+ case Iop_GetElem16x8: vassert(index < 8); size = 1; break;
+ case Iop_GetElem32x4: vassert(index < 4); size = 2; break;
+ default: vassert(0);
+ }
+ addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS,
+ mkARMNRS(ARMNRS_Reg, res, 0),
+ mkARMNRS(ARMNRS_Scalar, arg, index),
+ size, True));
+ return res;
}
- index = e->Iex.Binop.arg2->Iex.Const.con->Ico.U8;
- switch (e->Iex.Binop.op) {
- case Iop_GetElem8x16: vassert(index < 16); size = 0; break;
- case Iop_GetElem16x8: vassert(index < 8); size = 1; break;
- case Iop_GetElem32x4: vassert(index < 4); size = 2; break;
- default: vassert(0);
- }
- addInstr(env, ARMInstr_NUnaryS(ARMneon_GETELEMS,
- mkARMNRS(ARMNRS_Reg, res, 0),
- mkARMNRS(ARMNRS_Scalar, arg, index),
- size, True));
- return res;
}
/* All cases involving host-side helper calls. */
@@ -2165,7 +2184,9 @@
static HReg iselNeon64Expr ( ISelEnv* env, IRExpr* e )
{
- HReg r = iselNeon64Expr_wrk( env, e );
+ HReg r;
+ vassert(env->hwcaps & VEX_HWCAPS_ARM_NEON);
+ r = iselNeon64Expr_wrk( env, e );
vassert(hregClass(r) == HRcFlt64);
vassert(hregIsVirtual(r));
return r;
@@ -3773,9 +3794,12 @@
vpanic("iselNeon64Expr");
}
+
static HReg iselNeonExpr ( ISelEnv* env, IRExpr* e )
{
- HReg r = iselNeonExpr_wrk( env, e );
+ HReg r;
+ vassert(env->hwcaps & VEX_HWCAPS_ARM_NEON);
+ r = iselNeonExpr_wrk( env, e );
vassert(hregClass(r) == HRcVec128);
vassert(hregIsVirtual(r));
return r;