Skip to content

Commit 831e6b2

Browse files
committed
[MERGE #5721 @sigatrev] ARM/ARM64: Implement LowererMD::GenerateFastCmXx(R8)
Merge pull request #5721 from sigatrev:CmXx This path was previously only hit in AsmJs, but PR #5686 caused it to be hit with normal JS. This commit implements the methods for ARM and ARM64.
2 parents 10a6930 + 2ea61b5 commit 831e6b2

File tree

4 files changed

+310
-8
lines changed

4 files changed

+310
-8
lines changed

lib/Backend/arm/LowerMD.cpp

+154-2
Original file line numberDiff line numberDiff line change
@@ -2874,9 +2874,161 @@ LowererMD::GenerateFastCmSrEqConst(IR::Instr *instr)
28742874
return false;
28752875
}
28762876

2877-
bool LowererMD::GenerateFastCmXxI4(IR::Instr *instr)
2877+
void LowererMD::GenerateFastCmXxI4(IR::Instr *instr)
28782878
{
2879-
return this->GenerateFastCmXxTaggedInt(instr);
2879+
this->GenerateFastCmXx(instr);
2880+
}
2881+
2882+
void LowererMD::GenerateFastCmXxR8(IR::Instr * instr)
2883+
{
2884+
this->GenerateFastCmXx(instr);
2885+
}
2886+
2887+
void LowererMD::GenerateFastCmXx(IR::Instr *instr)
2888+
{
2889+
// For float src:
2890+
// LDIMM dst, trueResult
2891+
// FCMP src1, src2
2892+
// - BVS $done (NaN check iff B.cond is BNE)
2893+
// B.cond $done
2894+
// LDIMM dst, falseResult
2895+
// $done
2896+
2897+
// For Int src:
2898+
// LDIMM dst, trueResult
2899+
// CMP src1, src2
2900+
// B.cond $done
2901+
// LDIMM dst, falseResult
2902+
// $done:
2903+
2904+
IR::Opnd * src1 = instr->UnlinkSrc1();
2905+
IR::Opnd * src2 = instr->UnlinkSrc2();
2906+
IR::Opnd * dst = instr->UnlinkDst();
2907+
bool isIntDst = dst->AsRegOpnd()->m_sym->IsInt32();
2908+
bool isFloatSrc = src1->IsFloat();
2909+
Assert(!isFloatSrc || src2->IsFloat());
2910+
Assert(!src1->IsInt64() || src2->IsInt64());
2911+
Assert(!isFloatSrc || AutoSystemInfo::Data.SSE2Available());
2912+
Assert(src1->IsRegOpnd());
2913+
IR::Opnd * opndTrue;
2914+
IR::Opnd * opndFalse;
2915+
IR::Instr * newInstr;
2916+
IR::LabelInstr * done = IR::LabelInstr::New(Js::OpCode::Label, m_func);
2917+
2918+
if (dst->IsEqual(src1))
2919+
{
2920+
IR::RegOpnd *newSrc1 = IR::RegOpnd::New(src1->GetType(), m_func);
2921+
Lowerer::InsertMove(newSrc1, src1, instr);
2922+
src1 = newSrc1;
2923+
}
2924+
2925+
if (dst->IsEqual(src2))
2926+
{
2927+
IR::RegOpnd *newSrc2 = IR::RegOpnd::New(src1->GetType(), m_func);
2928+
Lowerer::InsertMove(newSrc2, src2, instr);
2929+
src2 = newSrc2;
2930+
}
2931+
2932+
if (isIntDst)
2933+
{
2934+
opndTrue = IR::IntConstOpnd::New(1, TyInt32, this->m_func);
2935+
opndFalse = IR::IntConstOpnd::New(0, TyInt32, this->m_func);
2936+
}
2937+
else
2938+
{
2939+
opndTrue = this->m_lowerer->LoadLibraryValueOpnd(instr, LibraryValue::ValueTrue);
2940+
opndFalse = this->m_lowerer->LoadLibraryValueOpnd(instr, LibraryValue::ValueFalse);
2941+
}
2942+
2943+
Lowerer::InsertMove(dst, opndTrue, instr);
2944+
2945+
// CMP src1, src2
2946+
newInstr = IR::Instr::New(isFloatSrc ? Js::OpCode::VCMPF64 : Js::OpCode::CMP, this->m_func);
2947+
newInstr->SetSrc1(src1);
2948+
newInstr->SetSrc2(src2);
2949+
instr->InsertBefore(newInstr);
2950+
LowererMD::Legalize(newInstr);
2951+
2952+
if (isFloatSrc)
2953+
{
2954+
instr->InsertBefore(IR::Instr::New(Js::OpCode::VMRS, this->m_func));
2955+
}
2956+
2957+
bool addNaNCheck = false;
2958+
Js::OpCode opcode = Js::OpCode::InvalidOpCode;
2959+
2960+
switch (instr->m_opcode)
2961+
{
2962+
case Js::OpCode::CmEq_A:
2963+
case Js::OpCode::CmSrEq_A:
2964+
case Js::OpCode::CmEq_I4:
2965+
opcode = Js::OpCode::BEQ;
2966+
break;
2967+
2968+
case Js::OpCode::CmNeq_A:
2969+
case Js::OpCode::CmSrNeq_A:
2970+
case Js::OpCode::CmNeq_I4:
2971+
opcode = Js::OpCode::BNE;
2972+
addNaNCheck = isFloatSrc;
2973+
break;
2974+
2975+
case Js::OpCode::CmGt_A:
2976+
case Js::OpCode::CmGt_I4:
2977+
opcode = Js::OpCode::BGT;
2978+
break;
2979+
2980+
case Js::OpCode::CmGe_A:
2981+
case Js::OpCode::CmGe_I4:
2982+
opcode = Js::OpCode::BGE;
2983+
break;
2984+
2985+
case Js::OpCode::CmLt_A:
2986+
case Js::OpCode::CmLt_I4:
2987+
//Can't use BLT as is set when the operands are unordered (NaN).
2988+
opcode = isFloatSrc ? Js::OpCode::BCC : Js::OpCode::BLT;
2989+
break;
2990+
2991+
case Js::OpCode::CmLe_A:
2992+
case Js::OpCode::CmLe_I4:
2993+
//Can't use BLE as it is set when the operands are unordered (NaN).
2994+
opcode = isFloatSrc ? Js::OpCode::BLS : Js::OpCode::BLE;
2995+
break;
2996+
2997+
case Js::OpCode::CmUnGt_A:
2998+
case Js::OpCode::CmUnGt_I4:
2999+
opcode = Js::OpCode::BHI;
3000+
break;
3001+
3002+
case Js::OpCode::CmUnGe_A:
3003+
case Js::OpCode::CmUnGe_I4:
3004+
opcode = Js::OpCode::BCS;
3005+
break;
3006+
3007+
case Js::OpCode::CmUnLt_A:
3008+
case Js::OpCode::CmUnLt_I4:
3009+
opcode = Js::OpCode::BCC;
3010+
break;
3011+
3012+
case Js::OpCode::CmUnLe_A:
3013+
case Js::OpCode::CmUnLe_I4:
3014+
opcode = Js::OpCode::BLS;
3015+
break;
3016+
3017+
default: Assert(false);
3018+
}
3019+
3020+
if (addNaNCheck)
3021+
{
3022+
newInstr = IR::BranchInstr::New(Js::OpCode::BVS, done, m_func);
3023+
instr->InsertBefore(newInstr);
3024+
}
3025+
3026+
newInstr = IR::BranchInstr::New(opcode, done, m_func);
3027+
instr->InsertBefore(newInstr);
3028+
3029+
Lowerer::InsertMove(dst, opndFalse, instr);
3030+
instr->InsertBefore(done);
3031+
instr->Remove();
28803032
}
28813033

28823034
///----------------------------------------------------------------------------

lib/Backend/arm/LowerMD.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ class LowererMD
9494
void GenerateObjectPairTest(IR::Opnd * opndSrc1, IR::Opnd * opndSrc2, IR::Instr * insertInstr, IR::LabelInstr * labelTarget);
9595
bool GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr, IR::LabelInstr * labelTarget, bool fContinueLabel = false);
9696
bool GenerateFastCmSrEqConst(IR::Instr *instr);
97-
bool GenerateFastCmXxI4(IR::Instr *instr);
98-
bool GenerateFastCmXxR8(IR::Instr *instr) { Assert(UNREACHED); return nullptr; }
97+
void GenerateFastCmXxI4(IR::Instr *instr);
98+
void GenerateFastCmXxR8(IR::Instr *instr);
99+
void GenerateFastCmXx(IR::Instr *instr);
99100
bool GenerateFastCmXxTaggedInt(IR::Instr *instr, bool isInHelper = false);
100101
IR::Instr * GenerateConvBool(IR::Instr *instr);
101102
void GenerateClz(IR::Instr * instr);

lib/Backend/arm64/LowerMD.cpp

+150-2
Original file line numberDiff line numberDiff line change
@@ -2677,9 +2677,156 @@ LowererMD::GenerateFastCmSrEqConst(IR::Instr *instr)
26772677
return false;
26782678
}
26792679

2680-
bool LowererMD::GenerateFastCmXxI4(IR::Instr *instr)
2680+
void LowererMD::GenerateFastCmXxI4(IR::Instr *instr)
26812681
{
2682-
return this->GenerateFastCmXxTaggedInt(instr);
2682+
this->GenerateFastCmXx(instr);
2683+
}
2684+
2685+
void LowererMD::GenerateFastCmXxR8(IR::Instr *instr)
2686+
{
2687+
this->GenerateFastCmXx(instr);
2688+
}
2689+
2690+
void LowererMD::GenerateFastCmXx(IR::Instr *instr)
2691+
{
2692+
// For float src:
2693+
// LDIMM dst, trueResult
2694+
// FCMP src1, src2
2695+
// - BVS $done (NaN check iff B.cond is BNE)
2696+
// B.cond $done
2697+
// LDIMM dst, falseResult
2698+
// $done
2699+
2700+
// For Int src:
2701+
// LDIMM dst, trueResult
2702+
// CMP src1, src2
2703+
// B.cond $done
2704+
// LDIMM dst, falseResult
2705+
// $done:
2706+
2707+
IR::Opnd * src1 = instr->UnlinkSrc1();
2708+
IR::Opnd * src2 = instr->UnlinkSrc2();
2709+
IR::Opnd * dst = instr->UnlinkDst();
2710+
bool isIntDst = dst->AsRegOpnd()->m_sym->IsInt32();
2711+
bool isFloatSrc = src1->IsFloat();
2712+
Assert(!isFloatSrc || src2->IsFloat());
2713+
Assert(!src1->IsInt64() || src2->IsInt64());
2714+
Assert(!isFloatSrc || AutoSystemInfo::Data.SSE2Available());
2715+
Assert(src1->IsRegOpnd());
2716+
IR::Opnd * opndTrue;
2717+
IR::Opnd * opndFalse;
2718+
IR::Instr * newInstr;
2719+
IR::LabelInstr * done = IR::LabelInstr::New(Js::OpCode::Label, m_func);
2720+
2721+
if (dst->IsEqual(src1))
2722+
{
2723+
IR::RegOpnd *newSrc1 = IR::RegOpnd::New(src1->GetType(), m_func);
2724+
Lowerer::InsertMove(newSrc1, src1, instr);
2725+
src1 = newSrc1;
2726+
}
2727+
2728+
if (dst->IsEqual(src2))
2729+
{
2730+
IR::RegOpnd *newSrc2 = IR::RegOpnd::New(src1->GetType(), m_func);
2731+
Lowerer::InsertMove(newSrc2, src2, instr);
2732+
src2 = newSrc2;
2733+
}
2734+
2735+
if (isIntDst)
2736+
{
2737+
opndTrue = IR::IntConstOpnd::New(1, TyInt32, this->m_func);
2738+
opndFalse = IR::IntConstOpnd::New(0, TyInt32, this->m_func);
2739+
}
2740+
else
2741+
{
2742+
opndTrue = this->m_lowerer->LoadLibraryValueOpnd(instr, LibraryValue::ValueTrue);
2743+
opndFalse = this->m_lowerer->LoadLibraryValueOpnd(instr, LibraryValue::ValueFalse);
2744+
}
2745+
2746+
Lowerer::InsertMove(dst, opndTrue, instr);
2747+
2748+
// CMP src1, src2
2749+
newInstr = IR::Instr::New(isFloatSrc ? Js::OpCode::FCMP : Js::OpCode::CMP, this->m_func);
2750+
newInstr->SetSrc1(src1);
2751+
newInstr->SetSrc2(src2);
2752+
instr->InsertBefore(newInstr);
2753+
LowererMD::Legalize(newInstr);
2754+
2755+
bool addNaNCheck = false;
2756+
Js::OpCode opcode = Js::OpCode::InvalidOpCode;
2757+
2758+
switch (instr->m_opcode)
2759+
{
2760+
case Js::OpCode::CmEq_A:
2761+
case Js::OpCode::CmSrEq_A:
2762+
case Js::OpCode::CmEq_I4:
2763+
opcode = Js::OpCode::BEQ;
2764+
break;
2765+
2766+
case Js::OpCode::CmNeq_A:
2767+
case Js::OpCode::CmSrNeq_A:
2768+
case Js::OpCode::CmNeq_I4:
2769+
opcode = Js::OpCode::BNE;
2770+
addNaNCheck = isFloatSrc;
2771+
break;
2772+
2773+
case Js::OpCode::CmGt_A:
2774+
case Js::OpCode::CmGt_I4:
2775+
opcode = Js::OpCode::BGT;
2776+
break;
2777+
2778+
case Js::OpCode::CmGe_A:
2779+
case Js::OpCode::CmGe_I4:
2780+
opcode = Js::OpCode::BGE;
2781+
break;
2782+
2783+
case Js::OpCode::CmLt_A:
2784+
case Js::OpCode::CmLt_I4:
2785+
//Can't use BLT as is set when the operands are unordered (NaN).
2786+
opcode = isFloatSrc ? Js::OpCode::BCC : Js::OpCode::BLT;
2787+
break;
2788+
2789+
case Js::OpCode::CmLe_A:
2790+
case Js::OpCode::CmLe_I4:
2791+
//Can't use BLE as it is set when the operands are unordered (NaN).
2792+
opcode = isFloatSrc ? Js::OpCode::BLS : Js::OpCode::BLE;
2793+
break;
2794+
2795+
case Js::OpCode::CmUnGt_A:
2796+
case Js::OpCode::CmUnGt_I4:
2797+
opcode = Js::OpCode::BHI;
2798+
break;
2799+
2800+
case Js::OpCode::CmUnGe_A:
2801+
case Js::OpCode::CmUnGe_I4:
2802+
opcode = Js::OpCode::BCS;
2803+
break;
2804+
2805+
case Js::OpCode::CmUnLt_A:
2806+
case Js::OpCode::CmUnLt_I4:
2807+
opcode = Js::OpCode::BCC;
2808+
break;
2809+
2810+
case Js::OpCode::CmUnLe_A:
2811+
case Js::OpCode::CmUnLe_I4:
2812+
opcode = Js::OpCode::BLS;
2813+
break;
2814+
2815+
default: Assert(false);
2816+
}
2817+
2818+
if (addNaNCheck)
2819+
{
2820+
newInstr = IR::BranchInstr::New(Js::OpCode::BVS, done, m_func);
2821+
instr->InsertBefore(newInstr);
2822+
}
2823+
2824+
newInstr = IR::BranchInstr::New(opcode, done, m_func);
2825+
instr->InsertBefore(newInstr);
2826+
2827+
Lowerer::InsertMove(dst, opndFalse, instr);
2828+
instr->InsertBefore(done);
2829+
instr->Remove();
26832830
}
26842831

26852832
///----------------------------------------------------------------------------
@@ -2804,6 +2951,7 @@ bool LowererMD::GenerateFastCmXxTaggedInt(IR::Instr *instr, bool isInHelper /*
28042951
Lowerer::InsertMove(newSrc1, src1, instr);
28052952
src1 = newSrc1;
28062953
}
2954+
28072955
if (dst->IsEqual(src2))
28082956
{
28092957
IR::RegOpnd *newSrc2 = IR::RegOpnd::New(TyMachReg, m_func);

lib/Backend/arm64/LowerMD.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ class LowererMD
9494
void GenerateTaggedZeroTest( IR::Opnd * opndSrc, IR::Instr * instrInsert, IR::LabelInstr * labelHelper = nullptr);
9595
bool GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr, IR::LabelInstr * labelTarget, bool fContinueLabel = false);
9696
bool GenerateFastCmSrEqConst(IR::Instr *instr);
97-
bool GenerateFastCmXxI4(IR::Instr *instr);
98-
bool GenerateFastCmXxR8(IR::Instr *instr) { Assert(UNREACHED); return nullptr; }
97+
void GenerateFastCmXxI4(IR::Instr *instr);
98+
void GenerateFastCmXxR8(IR::Instr *instr);
99+
void GenerateFastCmXx(IR::Instr *instr);
99100
bool GenerateFastCmXxTaggedInt(IR::Instr *instr, bool isInHelper = false);
100101
IR::Instr * GenerateConvBool(IR::Instr *instr);
101102
void GenerateClz(IR::Instr * instr);

0 commit comments

Comments
 (0)