@@ -406,12 +406,12 @@ IRNativeReg IRNativeRegCacheBase::FindFreeReg(MIPSLoc type, MIPSMap flags) const
406
406
407
407
bool IRNativeRegCacheBase::IsGPRClobbered (IRReg gpr) const {
408
408
_dbg_assert_ (IsValidGPR (gpr));
409
- return IsRegClobbered (MIPSLoc::REG, MIPSMap::INIT, gpr);
409
+ return IsRegClobbered (MIPSLoc::REG, gpr);
410
410
}
411
411
412
412
bool IRNativeRegCacheBase::IsFPRClobbered (IRReg fpr) const {
413
413
_dbg_assert_ (IsValidFPR (fpr));
414
- return IsRegClobbered (MIPSLoc::FREG, MIPSMap::INIT, fpr + 32 );
414
+ return IsRegClobbered (MIPSLoc::FREG, fpr + 32 );
415
415
}
416
416
417
417
IRUsage IRNativeRegCacheBase::GetNextRegUsage (const IRSituation &info, MIPSLoc type, IRReg r) const {
@@ -423,7 +423,7 @@ IRUsage IRNativeRegCacheBase::GetNextRegUsage(const IRSituation &info, MIPSLoc t
423
423
return IRUsage::UNKNOWN;
424
424
}
425
425
426
- bool IRNativeRegCacheBase::IsRegClobbered (MIPSLoc type, MIPSMap flags, IRReg r) const {
426
+ bool IRNativeRegCacheBase::IsRegClobbered (MIPSLoc type, IRReg r) const {
427
427
static const int UNUSED_LOOKAHEAD_OPS = 30 ;
428
428
429
429
IRSituation info;
@@ -450,6 +450,21 @@ bool IRNativeRegCacheBase::IsRegClobbered(MIPSLoc type, MIPSMap flags, IRReg r)
450
450
return false ;
451
451
}
452
452
453
+ bool IRNativeRegCacheBase::IsRegRead (MIPSLoc type, IRReg first) const {
454
+ static const int UNUSED_LOOKAHEAD_OPS = 30 ;
455
+
456
+ IRSituation info;
457
+ info.lookaheadCount = UNUSED_LOOKAHEAD_OPS;
458
+ // We look starting one ahead, unlike spilling.
459
+ info.currentIndex = irIndex_ + 1 ;
460
+ info.instructions = irBlock_->GetInstructions ();
461
+ info.numInstructions = irBlock_->GetNumInstructions ();
462
+
463
+ // Note: this intentionally doesn't look at the full reg, only the lane.
464
+ IRUsage usage = GetNextRegUsage (info, type, first);
465
+ return usage == IRUsage::READ;
466
+ }
467
+
453
468
IRNativeReg IRNativeRegCacheBase::FindBestToSpill (MIPSLoc type, MIPSMap flags, bool unusedOnly, bool *clobbered) const {
454
469
int allocCount = 0 , base = 0 ;
455
470
const int *allocOrder = GetAllocationOrder (type, flags, allocCount, base);
@@ -501,7 +516,7 @@ IRNativeReg IRNativeRegCacheBase::FindBestToSpill(MIPSLoc type, MIPSMap flags, b
501
516
return -1 ;
502
517
}
503
518
504
- bool IRNativeRegCacheBase::IsNativeRegCompatible (IRNativeReg nreg, MIPSLoc type, MIPSMap flags) {
519
+ bool IRNativeRegCacheBase::IsNativeRegCompatible (IRNativeReg nreg, MIPSLoc type, MIPSMap flags, int lanes ) {
505
520
int allocCount = 0 , base = 0 ;
506
521
const int *allocOrder = GetAllocationOrder (type, flags, allocCount, base);
507
522
@@ -514,6 +529,11 @@ bool IRNativeRegCacheBase::IsNativeRegCompatible(IRNativeReg nreg, MIPSLoc type,
514
529
return false ;
515
530
}
516
531
532
+ bool IRNativeRegCacheBase::TransferNativeReg (IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) {
533
+ // To be overridden if the backend supports transfers.
534
+ return false ;
535
+ }
536
+
517
537
void IRNativeRegCacheBase::DiscardNativeReg (IRNativeReg nreg) {
518
538
_assert_msg_ (nreg >= 0 && nreg < config_.totalNativeRegs , " DiscardNativeReg on invalid register %d" , nreg);
519
539
if (nr[nreg].mipsReg != IRREG_INVALID) {
@@ -930,21 +950,28 @@ IRNativeReg IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRReg first, int la
930
950
case MIPSLoc::REG:
931
951
if (type != MIPSLoc::REG) {
932
952
nreg = AllocateReg (type, flags);
933
- } else if (!IsNativeRegCompatible (nreg, type, flags)) {
953
+ } else if (!IsNativeRegCompatible (nreg, type, flags, lanes )) {
934
954
// If it's not compatible, we'll need to reallocate.
935
- // TODO: Could do a transfer and avoid memory flush.
936
- FlushNativeReg (nreg);
937
- nreg = AllocateReg (type, flags);
955
+ if (TransferNativeReg (nreg, -1 , type, first, lanes, flags)) {
956
+ nreg = mr[first].nReg ;
957
+ } else {
958
+ FlushNativeReg (nreg);
959
+ nreg = AllocateReg (type, flags);
960
+ }
938
961
}
939
962
break ;
940
963
941
964
case MIPSLoc::FREG:
942
965
case MIPSLoc::VREG:
943
966
if (type != mr[first].loc ) {
944
967
nreg = AllocateReg (type, flags);
945
- } else if (!IsNativeRegCompatible (nreg, type, flags)) {
946
- FlushNativeReg (nreg);
947
- nreg = AllocateReg (type, flags);
968
+ } else if (!IsNativeRegCompatible (nreg, type, flags, lanes)) {
969
+ if (TransferNativeReg (nreg, -1 , type, first, lanes, flags)) {
970
+ nreg = mr[first].nReg ;
971
+ } else {
972
+ FlushNativeReg (nreg);
973
+ nreg = AllocateReg (type, flags);
974
+ }
948
975
}
949
976
break ;
950
977
@@ -981,10 +1008,13 @@ void IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRNativeReg nreg, IRReg fi
981
1008
_assert_msg_ (!mreg.isStatic , " Cannot MapNativeReg a static reg mismatch" );
982
1009
if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) {
983
1010
// If we need init, we have to flush mismatches.
984
- // TODO: Do a shuffle if interior only?
985
- // TODO: We may also be motivated to have multiple read-only "views" or an IRReg.
986
- // For example Vec4Scale v0..v3, v0..v3, v3
987
- FlushNativeReg (mreg.nReg );
1011
+ if (!TransferNativeReg (mreg.nReg , nreg, type, first, lanes, flags)) {
1012
+ // TODO: We may also be motivated to have multiple read-only "views" or an IRReg.
1013
+ // For example Vec4Scale v0..v3, v0..v3, v3
1014
+ FlushNativeReg (mreg.nReg );
1015
+ }
1016
+ // The mismatch has been "resolved" now.
1017
+ mismatch = false ;
988
1018
} else if (oldlanes != 1 ) {
989
1019
// Even if we don't care about the current contents, we can't discard outside.
990
1020
bool extendsBefore = oldlane > i;
@@ -1017,6 +1047,9 @@ void IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRNativeReg nreg, IRReg fi
1017
1047
DiscardNativeReg (mreg.nReg );
1018
1048
else
1019
1049
FlushNativeReg (mreg.nReg );
1050
+
1051
+ // That took care of the mismatch, either by clobber or flush.
1052
+ mismatch = false ;
1020
1053
}
1021
1054
}
1022
1055
}
@@ -1027,8 +1060,8 @@ void IRNativeRegCacheBase::MapNativeReg(MIPSLoc type, IRNativeReg nreg, IRReg fi
1027
1060
if ((flags & MIPSMap::NOINIT) != MIPSMap::NOINIT) {
1028
1061
// We better not be trying to map to a different nreg if it's in one now.
1029
1062
// This might happen on some sort of transfer...
1030
- // TODO: Make a direct transfer, i.e. FREG -> VREG?
1031
- FlushNativeReg (mreg.nReg );
1063
+ if (! TransferNativeReg (mreg. nReg , nreg, type, first, lanes, flags))
1064
+ FlushNativeReg (mreg.nReg );
1032
1065
} else {
1033
1066
DiscardNativeReg (mreg.nReg );
1034
1067
}
0 commit comments