@@ -10824,7 +10824,6 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10824
10824
}
10825
10825
bool isMulOverflow = false ;
10826
10826
bool isUnsignedMul = false ;
10827
- instruction ins2 = INS_invalid;
10828
10827
regNumber extraReg = REG_NA;
10829
10828
if (dst->gtOverflowEx ())
10830
10829
{
@@ -10840,7 +10839,6 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10840
10839
{
10841
10840
isMulOverflow = true ;
10842
10841
isUnsignedMul = ((dst->gtFlags & GTF_UNSIGNED) != 0 );
10843
- ins2 = isUnsignedMul ? INS_umulh : INS_smulh;
10844
10842
assert (intConst == nullptr ); // overflow format doesn't support an int constant operand
10845
10843
}
10846
10844
else
@@ -10856,43 +10854,68 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10856
10854
{
10857
10855
if (isMulOverflow)
10858
10856
{
10857
+ // Make sure that we have an internal register
10858
+ assert (genCountBits (dst->gtRsvdRegs ) == 2 );
10859
+
10860
+ // There will be two bits set in tmpRegsMask.
10861
+ // Remove the bit for 'dst->gtRegNum' from 'tmpRegsMask'
10862
+ regMaskTP tmpRegsMask = dst->gtRsvdRegs & ~genRegMask (dst->gtRegNum);
10863
+ regMaskTP tmpRegMask = genFindLowestBit (tmpRegsMask); // set tmpRegMsk to a one-bit mask
10864
+ extraReg = genRegNumFromMask (tmpRegMask); // set tmpReg from that mask
10865
+
10866
+ // Make sure the two registers are not the same.
10867
+ assert (extraReg != dst->gtRegNum );
10868
+
10859
10869
if (isUnsignedMul)
10860
10870
{
10861
- assert (genCountBits (dst->gtRsvdRegs ) == 1 );
10862
- extraReg = genRegNumFromMask (dst->gtRsvdRegs );
10871
+ if (attr == EA_4BYTE)
10872
+ {
10873
+ // Compute 8 byte results from 4 byte by 4 byte multiplication.
10874
+ emitIns_R_R_R (INS_umull, EA_8BYTE, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10863
10875
10864
- // Compute the high result
10865
- emitIns_R_R_R (ins2, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10876
+ // Get the high result by shifting dst.
10877
+ emitIns_R_R_I (INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum , 32 );
10878
+ }
10879
+ else
10880
+ {
10881
+ assert (attr == EA_8BYTE);
10882
+ // Compute the high result.
10883
+ emitIns_R_R_R (INS_umulh, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10866
10884
10867
- emitIns_R_I (INS_cmp, EA_8BYTE, extraReg, 0 );
10868
- codeGen->genCheckOverflow (dst);
10885
+ // Now multiply without skewing the high result.
10886
+ emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10887
+ }
10869
10888
10870
- // Now multiply without skewing the high result if no overflow.
10871
- emitIns_R_R_R (ins , attr, dst-> gtRegNum , src1-> gtRegNum , src2-> gtRegNum );
10889
+ // zero-sign bit comparision to detect overflow.
10890
+ emitIns_R_I (INS_cmp , attr, extraReg, 0 );
10872
10891
}
10873
10892
else
10874
10893
{
10875
- // Make sure that we have an internal register
10876
- assert (genCountBits (dst->gtRsvdRegs ) == 2 );
10877
-
10878
- // There will be two bits set in tmpRegsMask.
10879
- // Remove the bit for 'dst->gtRegNum' from 'tmpRegsMask'
10880
- regMaskTP tmpRegsMask = dst->gtRsvdRegs & ~genRegMask (dst->gtRegNum);
10881
- regMaskTP tmpRegMask = genFindLowestBit (tmpRegsMask); // set tmpRegMsk to a one-bit mask
10882
- extraReg = genRegNumFromMask (tmpRegMask); // set tmpReg from that mask
10894
+ int bitShift = 0 ;
10895
+ if (attr == EA_4BYTE)
10896
+ {
10897
+ // Compute 8 byte results from 4 byte by 4 byte multiplication.
10898
+ emitIns_R_R_R (INS_smull, EA_8BYTE, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10883
10899
10884
- // Make sure the two registers are not the same .
10885
- assert (extraReg != dst->gtRegNum );
10900
+ // Get the high result by shifting dst .
10901
+ emitIns_R_R_I (INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum , 32 );
10886
10902
10887
- // Save the high result in a temporary register
10888
- emitIns_R_R_R (ins2, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10903
+ bitShift = 31 ;
10904
+ }
10905
+ else
10906
+ {
10907
+ assert (attr == EA_8BYTE);
10908
+ // Save the high result in a temporary register.
10909
+ emitIns_R_R_R (INS_smulh, attr, extraReg, src1->gtRegNum , src2->gtRegNum );
10889
10910
10890
- // Now multiply without skewing the high result.
10891
- emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10911
+ // Now multiply without skewing the high result.
10912
+ emitIns_R_R_R (ins, attr, dst->gtRegNum , src1->gtRegNum , src2->gtRegNum );
10892
10913
10893
- emitIns_R_R_I (INS_cmp, EA_8BYTE, extraReg, dst->gtRegNum , 63 , INS_OPTS_ASR);
10914
+ bitShift = 63 ;
10915
+ }
10894
10916
10895
- codeGen->genCheckOverflow (dst);
10917
+ // Sign bit comparision to detect overflow.
10918
+ emitIns_R_R_I (INS_cmp, attr, extraReg, dst->gtRegNum , bitShift, INS_OPTS_ASR);
10896
10919
}
10897
10920
}
10898
10921
else
@@ -10902,7 +10925,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
10902
10925
}
10903
10926
}
10904
10927
10905
- if (dst->gtOverflowEx () && !isMulOverflow )
10928
+ if (dst->gtOverflowEx ())
10906
10929
{
10907
10930
assert (!varTypeIsFloating (dst));
10908
10931
codeGen->genCheckOverflow (dst);
0 commit comments