Skip to content

Commit 1ec0d4f

Browse files
committed
[AArch64] Lift FEAT_CSSC instructions
`abs`, `smax`, `smin`, `umax`, and `umin` are lifted to instruction sequences involving comparisons, while `cnt` and `ctz` are lifted to intrinsics.
1 parent 419e7ef commit 1ec0d4f

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

arch/arm64/arch_arm64.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,10 @@ class Arm64Architecture : public Architecture
996996
return "_eret";
997997
case ARM64_INTRIN_CLZ:
998998
return "_CountLeadingZeros";
999+
case ARM64_INTRIN_CNT:
1000+
return "_PopulationCount";
1001+
case ARM64_INTRIN_CTZ:
1002+
return "_CountTrailingZeros";
9991003
case ARM64_INTRIN_CLREX:
10001004
return "__clrex";
10011005
case ARM64_INTRIN_REV:
@@ -1086,6 +1090,8 @@ class Arm64Architecture : public Architecture
10861090
};
10871091
break;
10881092
case ARM64_INTRIN_CLZ: // reads <Xn>
1093+
case ARM64_INTRIN_CNT: // reads <Xn>
1094+
case ARM64_INTRIN_CTZ: // reads <Xn>
10891095
case ARM64_INTRIN_PRFM:
10901096
case ARM64_INTRIN_REV: // reads <Xn>
10911097
case ARM64_INTRIN_RBIT: // reads <Xn>
@@ -1149,6 +1155,8 @@ class Arm64Architecture : public Architecture
11491155
case ARM64_INTRIN_XPACD: // writes <Xd>
11501156
case ARM64_INTRIN_XPACI: // writes <Xd>
11511157
case ARM64_INTRIN_CLZ: // writes <Xd>
1158+
case ARM64_INTRIN_CNT: // writes <Xd>
1159+
case ARM64_INTRIN_CTZ: // writes <Xd>
11521160
case ARM64_INTRIN_REV: // writes <Xd>
11531161
case ARM64_INTRIN_RBIT: // writes <Xd>
11541162
return {Type::IntegerType(8, false)};

arch/arm64/il.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,13 @@ bool GetLowLevelILForInstruction(
13071307
LowLevelILLabel trueLabel, falseLabel;
13081308
switch (instr.operation)
13091309
{
1310+
case ARM64_ABS:
1311+
{
1312+
ExprId src = ILREG_O(operand2);
1313+
GenIfElse(il, il.CompareSignedLessThan(REGSZ_O(operand2), src, il.Const(REGSZ_O(operand2), 0)),
1314+
ILSETREG_O(operand1, il.Neg(REGSZ_O(operand2), src)), ILSETREG_O(operand1, src));
1315+
break;
1316+
}
13101317
case ARM64_ADD:
13111318
switch (instr.encoding)
13121319
{
@@ -1733,6 +1740,14 @@ bool GetLowLevelILForInstruction(
17331740
il.AddInstruction(il.Intrinsic(
17341741
{RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_CLZ, {ILREG_O(operand2)}));
17351742
break;
1743+
case ARM64_CNT:
1744+
il.AddInstruction(
1745+
il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_CNT, {ILREG_O(operand2)}));
1746+
break;
1747+
case ARM64_CTZ:
1748+
il.AddInstruction(
1749+
il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_CTZ, {ILREG_O(operand2)}));
1750+
break;
17361751
case ARM64_DC:
17371752
// il.AddInstruction(
17381753
// il.Intrinsic({}, ARM64_INTRIN_DC, {ILREG_O(operand2)})); /* operand1 is <dc_op> */
@@ -3730,6 +3745,54 @@ bool GetLowLevelILForInstruction(
37303745
il.MultDoublePrecSigned(REGSZ_O(operand1), ILREG_O(operand2), ILREG_O(operand3)),
37313746
il.Const(1, 64))))));
37323747
break;
3748+
case ARM64_SMAX:
3749+
{
3750+
ExprId op2 = ILREG_O(operand2);
3751+
ExprId op3;
3752+
3753+
switch (instr.encoding)
3754+
{
3755+
case ENC_SMAX_32_MINMAX_IMM:
3756+
case ENC_SMAX_64_MINMAX_IMM:
3757+
op3 = il.Const(REGSZ_O(operand2), operand3.immediate);
3758+
break;
3759+
case ENC_SMAX_32_DP_2SRC:
3760+
case ENC_SMAX_64_DP_2SRC:
3761+
op3 = ILREG_O(operand3);
3762+
break;
3763+
default:
3764+
il.AddInstruction(il.Unimplemented());
3765+
return true;
3766+
}
3767+
3768+
GenIfElse(il, il.CompareSignedGreaterThan(REGSZ_O(operand2), op2, op3), ILSETREG_O(operand1, op2),
3769+
ILSETREG_O(operand1, op3));
3770+
break;
3771+
}
3772+
case ARM64_SMIN:
3773+
{
3774+
ExprId op2 = ILREG_O(operand2);
3775+
ExprId op3;
3776+
3777+
switch (instr.encoding)
3778+
{
3779+
case ENC_SMIN_32_MINMAX_IMM:
3780+
case ENC_SMIN_64_MINMAX_IMM:
3781+
op3 = il.Const(REGSZ_O(operand2), operand3.immediate);
3782+
break;
3783+
case ENC_SMIN_32_DP_2SRC:
3784+
case ENC_SMIN_64_DP_2SRC:
3785+
op3 = ILREG_O(operand3);
3786+
break;
3787+
default:
3788+
il.AddInstruction(il.Unimplemented());
3789+
return true;
3790+
}
3791+
3792+
GenIfElse(il, il.CompareSignedLessThan(REGSZ_O(operand2), op2, op3), ILSETREG_O(operand1, op2),
3793+
ILSETREG_O(operand1, op3));
3794+
break;
3795+
}
37333796
case ARM64_UDIV:
37343797
switch (instr.encoding)
37353798
{
@@ -3742,6 +3805,54 @@ bool GetLowLevelILForInstruction(
37423805
il.AddInstruction(ILSETREG_O(
37433806
operand1, il.DivUnsigned(REGSZ_O(operand2), ILREG_O(operand2), ILREG_O(operand3))));
37443807
break;
3808+
case ARM64_UMAX:
3809+
{
3810+
ExprId op2 = ILREG_O(operand2);
3811+
ExprId op3;
3812+
3813+
switch (instr.encoding)
3814+
{
3815+
case ENC_UMAX_32U_MINMAX_IMM:
3816+
case ENC_UMAX_64U_MINMAX_IMM:
3817+
op3 = il.Const(REGSZ_O(operand2), operand3.immediate);
3818+
break;
3819+
case ENC_UMAX_32_DP_2SRC:
3820+
case ENC_UMAX_64_DP_2SRC:
3821+
op3 = ILREG_O(operand3);
3822+
break;
3823+
default:
3824+
il.AddInstruction(il.Unimplemented());
3825+
return true;
3826+
}
3827+
3828+
GenIfElse(il, il.CompareUnsignedGreaterThan(REGSZ_O(operand2), op2, op3), ILSETREG_O(operand1, op2),
3829+
ILSETREG_O(operand1, op3));
3830+
break;
3831+
}
3832+
case ARM64_UMIN:
3833+
{
3834+
ExprId op2 = ILREG_O(operand2);
3835+
ExprId op3;
3836+
3837+
switch (instr.encoding)
3838+
{
3839+
case ENC_UMIN_32U_MINMAX_IMM:
3840+
case ENC_UMIN_64U_MINMAX_IMM:
3841+
op3 = il.Const(REGSZ_O(operand2), operand3.immediate);
3842+
break;
3843+
case ENC_UMIN_32_DP_2SRC:
3844+
case ENC_UMIN_64_DP_2SRC:
3845+
op3 = ILREG_O(operand3);
3846+
break;
3847+
default:
3848+
il.AddInstruction(il.Unimplemented());
3849+
return true;
3850+
}
3851+
3852+
GenIfElse(il, il.CompareUnsignedLessThan(REGSZ_O(operand2), op2, op3), ILSETREG_O(operand1, op2),
3853+
ILSETREG_O(operand1, op3));
3854+
break;
3855+
}
37453856
case ARM64_UBFIZ:
37463857
il.AddInstruction(
37473858
ILSETREG_O(operand1, il.ZeroExtend(REGSZ_O(operand1),

arch/arm64/il.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ enum Arm64Intrinsic : uint32_t
7373
ARM64_INTRIN_YIELD,
7474
ARM64_INTRIN_ERET,
7575
ARM64_INTRIN_CLZ,
76+
ARM64_INTRIN_CNT,
77+
ARM64_INTRIN_CTZ,
7678
ARM64_INTRIN_CLREX,
7779
ARM64_INTRIN_REV,
7880
ARM64_INTRIN_RBIT,

0 commit comments

Comments
 (0)