d: Implement core.bitop.rol() and core.bitop.ror() as intrinsics.
gcc/d/ChangeLog: * intrinsics.cc (expand_intrinsic_rotate): Add function. (maybe_expand_intrinsic): Handle rol and ror intrinsics. * intrinsics.def (ROL): Add intrinsic. (ROL_TIARG): Add intrinsic. (ROR): Add intrinsic. (ROR_TIARG): Add intrinsic. gcc/testsuite/ChangeLog: * gdc.dg/intrinsics.d: Add ror and rol tests.
This commit is contained in:
parent
6ee874f135
commit
7d4ee8bc58
3 changed files with 67 additions and 0 deletions
|
@ -390,6 +390,56 @@ expand_intrinsic_popcnt (tree callexp)
|
|||
return call_builtin_fn (callexp, code, 1, arg);
|
||||
}
|
||||
|
||||
/* Expand a front-end intrinsic call to INTRINSIC, which is either a call to
|
||||
rol() or ror(). These intrinsics expect to take one or two arguments,
|
||||
the signature to which can be either:
|
||||
|
||||
T rol(T) (const T value, const uint count);
|
||||
T rol(uint count, T) (const T value);
|
||||
T ror(T) (const T value, const uint count);
|
||||
T ror(uint count, T) (const T value);
|
||||
|
||||
This bitwise rotates VALUE left or right by COUNT bit positions. */
|
||||
|
||||
static tree
|
||||
expand_intrinsic_rotate (intrinsic_code intrinsic, tree callexp)
|
||||
{
|
||||
tree type = TREE_TYPE (callexp);
|
||||
tree value = CALL_EXPR_ARG (callexp, 0);
|
||||
tree count;
|
||||
tree_code code;
|
||||
|
||||
/* Get the equivalent tree code for the intrinsic. */
|
||||
if (intrinsic == INTRINSIC_ROL || intrinsic == INTRINSIC_ROL_TIARG)
|
||||
code = LROTATE_EXPR;
|
||||
else if (intrinsic == INTRINSIC_ROR || intrinsic == INTRINSIC_ROR_TIARG)
|
||||
code = RROTATE_EXPR;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
/* Get the COUNT parameter. Either from the call expression arguments or the
|
||||
template instantiation arguments. */
|
||||
if (intrinsic == INTRINSIC_ROL || intrinsic == INTRINSIC_ROR)
|
||||
count = CALL_EXPR_ARG (callexp, 1);
|
||||
else
|
||||
{
|
||||
tree callee = CALL_EXPR_FN (callexp);
|
||||
|
||||
if (TREE_CODE (callee) == ADDR_EXPR)
|
||||
callee = TREE_OPERAND (callee, 0);
|
||||
|
||||
/* Retrieve from the encoded template instantation. */
|
||||
TemplateInstance *ti = DECL_LANG_FRONTEND (callee)->isInstantiated ();
|
||||
gcc_assert (ti && ti->tiargs && ti->tiargs->length == 2);
|
||||
|
||||
Expression *e = isExpression ((*ti->tiargs)[0]);
|
||||
gcc_assert (e && e->op == TOKint64);
|
||||
count = build_expr (e, true);
|
||||
}
|
||||
|
||||
return fold_build2 (code, type, value, count);
|
||||
}
|
||||
|
||||
/* Expand a front-end intrinsic call to copysign(). This takes two arguments,
|
||||
the signature to which can be either:
|
||||
|
||||
|
@ -737,6 +787,12 @@ maybe_expand_intrinsic (tree callexp)
|
|||
case INTRINSIC_POPCNT64:
|
||||
return expand_intrinsic_popcnt (callexp);
|
||||
|
||||
case INTRINSIC_ROL:
|
||||
case INTRINSIC_ROL_TIARG:
|
||||
case INTRINSIC_ROR:
|
||||
case INTRINSIC_ROR_TIARG:
|
||||
return expand_intrinsic_rotate (intrinsic, callexp);
|
||||
|
||||
case INTRINSIC_BSWAP32:
|
||||
case INTRINSIC_BSWAP64:
|
||||
case INTRINSIC_CEIL:
|
||||
|
|
|
@ -59,6 +59,11 @@ DEF_D_BUILTIN (BSWAP64, BSWAP64, "bswap", "core.bitop", "FNaNbNiNfmZm")
|
|||
DEF_D_BUILTIN (POPCNT32, NONE, "popcnt", "core.bitop", "FNaNbNiNfkZi")
|
||||
DEF_D_BUILTIN (POPCNT64, NONE, "popcnt", "core.bitop", "FNaNbNiNfmZi")
|
||||
|
||||
DEF_D_BUILTIN (ROL, NONE, "rol", "core.bitop", "FNaI1TkZI1T")
|
||||
DEF_D_BUILTIN (ROL_TIARG, NONE, "rol", "core.bitop", "FNaI1TZI1T")
|
||||
DEF_D_BUILTIN (ROR, NONE, "ror", "core.bitop", "FNaI1TkZI1T")
|
||||
DEF_D_BUILTIN (ROR_TIARG, NONE, "ror", "core.bitop", "FNaI1TZI1T")
|
||||
|
||||
DEF_D_BUILTIN (VLOAD8, NONE, "volatileLoad", "core.bitop", "FNbNiNfPhZh")
|
||||
DEF_D_BUILTIN (VLOAD16, NONE, "volatileLoad", "core.bitop", "FNbNiNfPtZt")
|
||||
DEF_D_BUILTIN (VLOAD32, NONE, "volatileLoad", "core.bitop", "FNbNiNfPkZk")
|
||||
|
|
|
@ -38,6 +38,12 @@ void test_volatileStore(ubyte *a, ubyte b) { return volatileStore(a, b); }
|
|||
void test_volatileStore(ushort *a, ushort b) { return volatileStore(a, b); }
|
||||
void test_volatileStore(uint *a, uint b) { return volatileStore(a, b); }
|
||||
void test_volatileStore(ulong *a, ulong b) { return volatileStore(a, b); }
|
||||
// { dg-final { scan-tree-dump-not " rol " "original" } }
|
||||
ubyte test_rol(ubyte a, uint b) { return rol!ubyte(a, b); }
|
||||
uint test_rol(uint a) { return rol!(1, uint)(a); }
|
||||
// { dg-final { scan-tree-dump-not " ror " "original" } }
|
||||
ushort test_ror(ushort a, uint b) { return ror!ushort(a, b); }
|
||||
ulong test_ror(ulong a) { return ror!(1, ulong)(a); }
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// core.checkedint
|
||||
|
|
Loading…
Add table
Reference in a new issue