@@ -6344,7 +6344,7 @@ void CodeGen::genSetRegToCond(regNumber dstReg, GenTreePtr tree)
6344
6344
6345
6345
#if !defined(_TARGET_64BIT_)
6346
6346
// ------------------------------------------------------------------------
6347
- // genIntToIntCast : Generate code for long to int casts on x86.
6347
+ // genLongToIntCast : Generate code for long to int casts on x86.
6348
6348
//
6349
6349
// Arguments:
6350
6350
// cast - The GT_CAST node
@@ -6454,14 +6454,15 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6454
6454
6455
6455
GenTreePtr castOp = treeNode->gtCast .CastOp ();
6456
6456
var_types srcType = genActualType (castOp->TypeGet ());
6457
+ noway_assert (genTypeSize (srcType) >= 4 );
6457
6458
6458
- #if !defined(_TARGET_64BIT_)
6459
+ #ifdef _TARGET_X86_
6459
6460
if (varTypeIsLong (srcType))
6460
6461
{
6461
6462
genLongToIntCast (treeNode);
6462
6463
return ;
6463
6464
}
6464
- #endif // !defined(_TARGET_64BIT_)
6465
+ #endif // _TARGET_X86_
6465
6466
6466
6467
regNumber targetReg = treeNode->gtRegNum ;
6467
6468
regNumber sourceReg = castOp->gtRegNum ;
@@ -6477,33 +6478,29 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6477
6478
}
6478
6479
6479
6480
bool requiresOverflowCheck = false ;
6480
- bool needAndAfter = false ;
6481
6481
6482
6482
assert (genIsValidIntReg (targetReg));
6483
6483
assert (genIsValidIntReg (sourceReg));
6484
6484
6485
- instruction ins = INS_invalid;
6486
- emitAttr size = EA_UNKNOWN;
6485
+ instruction ins = INS_invalid;
6486
+ emitAttr srcSize = EA_ATTR (genTypeSize (srcType));
6487
+ emitAttr dstSize = EA_ATTR (genTypeSize (dstType));
6487
6488
6488
- if (genTypeSize (srcType) < genTypeSize (dstType) )
6489
+ if (srcSize < dstSize )
6489
6490
{
6490
6491
// Widening cast
6491
-
6492
6492
// Is this an Overflow checking cast?
6493
6493
// We only need to handle one case, as the other casts can never overflow.
6494
6494
// cast from TYP_INT to TYP_ULONG
6495
6495
//
6496
6496
if (treeNode->gtOverflow () && (srcType == TYP_INT) && (dstType == TYP_ULONG))
6497
6497
{
6498
6498
requiresOverflowCheck = true ;
6499
- size = EA_ATTR (genTypeSize (srcType));
6500
6499
ins = INS_mov;
6501
6500
}
6502
6501
else
6503
6502
{
6504
- // we need the source size
6505
- size = EA_ATTR (genTypeSize (srcType));
6506
- noway_assert (size < EA_PTRSIZE);
6503
+ noway_assert (srcSize < EA_PTRSIZE);
6507
6504
6508
6505
ins = ins_Move_Extend (srcType, castOp->InReg ());
6509
6506
@@ -6513,44 +6510,30 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6513
6510
64-bit, and a regular 32-bit mov clears the high 32 bits (like the non-existant movzxd),
6514
6511
but for a sign extension from TYP_INT to TYP_LONG, we need to use movsxd opcode.
6515
6512
*/
6516
- if (!isUnsignedSrc && !isUnsignedDst && (size == EA_4BYTE) && ( genTypeSize (dstType) > EA_4BYTE) )
6513
+ if (!isUnsignedSrc && !isUnsignedDst)
6517
6514
{
6518
6515
#ifdef _TARGET_X86_
6519
6516
NYI_X86 (" Cast to 64 bit for x86/RyuJIT" );
6520
6517
#else // !_TARGET_X86_
6521
6518
ins = INS_movsxd;
6522
6519
#endif // !_TARGET_X86_
6523
6520
}
6524
-
6525
- /*
6526
- Special case: for a cast of byte to char we first
6527
- have to expand the byte (w/ sign extension), then
6528
- mask off the high bits.
6529
- Use 'movsx' followed by 'and'
6530
- */
6531
- if (!isUnsignedSrc && isUnsignedDst && (genTypeSize (dstType) < EA_4BYTE))
6532
- {
6533
- noway_assert (genTypeSize (dstType) == EA_2BYTE && size == EA_1BYTE);
6534
- needAndAfter = true ;
6535
- }
6536
6521
}
6537
6522
}
6538
6523
else
6539
6524
{
6540
6525
// Narrowing cast, or sign-changing cast
6541
- noway_assert (genTypeSize (srcType) >= genTypeSize (dstType) );
6526
+ noway_assert (srcSize >= dstSize );
6542
6527
6543
6528
// Is this an Overflow checking cast?
6544
6529
if (treeNode->gtOverflow ())
6545
6530
{
6546
6531
requiresOverflowCheck = true ;
6547
- size = EA_ATTR (genTypeSize (srcType));
6548
6532
ins = INS_mov;
6549
6533
}
6550
6534
else
6551
6535
{
6552
- size = EA_ATTR (genTypeSize (dstType));
6553
- ins = ins_Move_Extend (dstType, castOp->InReg ());
6536
+ ins = ins_Move_Extend (dstType, castOp->InReg ());
6554
6537
}
6555
6538
}
6556
6539
@@ -6632,7 +6615,7 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6632
6615
if (signCheckOnly)
6633
6616
{
6634
6617
// We only need to check for a negative value in sourceReg
6635
- inst_RV_IV (INS_cmp, sourceReg, 0 , size );
6618
+ inst_RV_IV (INS_cmp, sourceReg, 0 , srcSize );
6636
6619
genJumpToThrowHlpBlk (EJ_jl, SCK_OVERFLOW);
6637
6620
}
6638
6621
else
@@ -6645,13 +6628,13 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6645
6628
{
6646
6629
regNumber tmpReg = treeNode->GetSingleTempReg ();
6647
6630
inst_RV_RV (INS_mov, tmpReg, sourceReg, TYP_LONG); // Move the 64-bit value to a writeable temp reg
6648
- inst_RV_SH (INS_SHIFT_RIGHT_LOGICAL, size , tmpReg, 32 ); // Shift right by 32 bits
6649
- genJumpToThrowHlpBlk (EJ_jne, SCK_OVERFLOW); // Throw if result shift is non-zero
6631
+ inst_RV_SH (INS_SHIFT_RIGHT_LOGICAL, srcSize , tmpReg, 32 ); // Shift right by 32 bits
6632
+ genJumpToThrowHlpBlk (EJ_jne, SCK_OVERFLOW); // Throw if result shift is non-zero
6650
6633
}
6651
6634
else
6652
6635
{
6653
6636
noway_assert (typeMask != 0 );
6654
- inst_RV_IV (INS_TEST, sourceReg, typeMask, size );
6637
+ inst_RV_IV (INS_TEST, sourceReg, typeMask, srcSize );
6655
6638
genJumpToThrowHlpBlk (EJ_jne, SCK_OVERFLOW);
6656
6639
}
6657
6640
}
@@ -6665,12 +6648,12 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6665
6648
6666
6649
noway_assert ((typeMin != 0 ) && (typeMax != 0 ));
6667
6650
6668
- inst_RV_IV (INS_cmp, sourceReg, typeMax, size );
6651
+ inst_RV_IV (INS_cmp, sourceReg, typeMax, srcSize );
6669
6652
genJumpToThrowHlpBlk (EJ_jg, SCK_OVERFLOW);
6670
6653
6671
6654
// Compare with the MIN
6672
6655
6673
- inst_RV_IV (INS_cmp, sourceReg, typeMin, size );
6656
+ inst_RV_IV (INS_cmp, sourceReg, typeMin, srcSize );
6674
6657
genJumpToThrowHlpBlk (EJ_jl, SCK_OVERFLOW);
6675
6658
}
6676
6659
}
@@ -6680,15 +6663,13 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6680
6663
// On amd64, we can hit this path for a same-register
6681
6664
// 4-byte to 8-byte widening conversion, and need to
6682
6665
// emit the instruction to set the high bits correctly.
6683
- || (EA_ATTR ( genTypeSize (dstType)) == EA_8BYTE && EA_ATTR ( genTypeSize (srcType)) == EA_4BYTE)
6666
+ || (dstSize == EA_8BYTE && srcSize == EA_4BYTE)
6684
6667
#endif // _TARGET_AMD64_
6685
6668
)
6686
- inst_RV_RV (ins, targetReg, sourceReg, srcType, size );
6669
+ inst_RV_RV (ins, targetReg, sourceReg, srcType, srcSize );
6687
6670
}
6688
6671
else // non-overflow checking cast
6689
6672
{
6690
- noway_assert (size < EA_PTRSIZE || srcType == dstType);
6691
-
6692
6673
// We may have code transformations that result in casts where srcType is the same as dstType.
6693
6674
// e.g. Bug 824281, in which a comma is split by the rationalizer, leaving an assignment of a
6694
6675
// long constant to a long lclVar.
@@ -6697,7 +6678,7 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6697
6678
ins = INS_mov;
6698
6679
}
6699
6680
/* Is the value sitting in a non-byte-addressable register? */
6700
- else if (castOp->InReg () && (size == EA_1BYTE) && !isByteReg (sourceReg))
6681
+ else if (castOp->InReg () && (dstSize == EA_1BYTE) && !isByteReg (sourceReg))
6701
6682
{
6702
6683
if (isUnsignedDst)
6703
6684
{
@@ -6713,21 +6694,21 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6713
6694
/* Generate "mov targetReg, castOp->gtReg */
6714
6695
if (targetReg != sourceReg)
6715
6696
{
6716
- inst_RV_RV (INS_mov, targetReg, sourceReg, srcType);
6697
+ inst_RV_RV (INS_mov, targetReg, sourceReg, srcType, srcSize );
6717
6698
}
6718
6699
}
6719
6700
6720
6701
if (ins == INS_AND)
6721
6702
{
6722
- noway_assert ((needAndAfter == false ) && isUnsignedDst);
6703
+ noway_assert (isUnsignedDst);
6723
6704
6724
6705
/* Generate "and reg, MASK */
6725
6706
unsigned fillPattern;
6726
- if (size == EA_1BYTE)
6707
+ if (dstSize == EA_1BYTE)
6727
6708
{
6728
6709
fillPattern = 0xff ;
6729
6710
}
6730
- else if (size == EA_2BYTE)
6711
+ else if (dstSize == EA_2BYTE)
6731
6712
{
6732
6713
fillPattern = 0xffff ;
6733
6714
}
@@ -6741,37 +6722,29 @@ void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6741
6722
#ifdef _TARGET_AMD64_
6742
6723
else if (ins == INS_movsxd)
6743
6724
{
6744
- noway_assert (!needAndAfter);
6745
- inst_RV_RV (ins, targetReg, sourceReg, srcType, size);
6725
+ inst_RV_RV (ins, targetReg, sourceReg, srcType, srcSize);
6746
6726
}
6747
6727
#endif // _TARGET_AMD64_
6748
6728
else if (ins == INS_mov)
6749
6729
{
6750
- noway_assert (!needAndAfter);
6751
6730
if (targetReg != sourceReg
6752
6731
#ifdef _TARGET_AMD64_
6753
6732
// On amd64, 'mov' is the opcode used to zero-extend from
6754
6733
// 4 bytes to 8 bytes.
6755
- || (EA_ATTR ( genTypeSize (dstType)) == EA_8BYTE && EA_ATTR ( genTypeSize (srcType)) == EA_4BYTE)
6734
+ || (dstSize == EA_8BYTE && srcSize == EA_4BYTE)
6756
6735
#endif // _TARGET_AMD64_
6757
6736
)
6758
6737
{
6759
- inst_RV_RV (ins, targetReg, sourceReg, srcType, size );
6738
+ inst_RV_RV (ins, targetReg, sourceReg, srcType, srcSize );
6760
6739
}
6761
6740
}
6762
6741
else
6763
6742
{
6764
6743
noway_assert (ins == INS_movsx || ins == INS_movzx);
6744
+ noway_assert (srcSize >= dstSize);
6765
6745
6766
6746
/* Generate "mov targetReg, castOp->gtReg */
6767
- inst_RV_RV (ins, targetReg, sourceReg, srcType, size);
6768
-
6769
- /* Mask off high bits for cast from byte to char */
6770
- if (needAndAfter)
6771
- {
6772
- noway_assert (genTypeSize (dstType) == 2 && ins == INS_movsx);
6773
- inst_RV_IV (INS_AND, targetReg, 0xFFFF , EA_4BYTE);
6774
- }
6747
+ inst_RV_RV (ins, targetReg, sourceReg, srcType, dstSize);
6775
6748
}
6776
6749
}
6777
6750
0 commit comments