@@ -98,10 +98,9 @@ type Liveness struct {
98
98
}
99
99
100
100
type progeffectscache struct {
101
- tailuevar []int32
102
- retuevar []int32
103
- textvarkill []int32
104
101
textavarinit []int32
102
+ retuevar []int32
103
+ tailuevar []int32
105
104
uevar [3 ]int32
106
105
varkill [3 ]int32
107
106
avarinit [3 ]int32
@@ -458,12 +457,12 @@ func (lv *Liveness) initcache() {
458
457
// all the parameters for correctness, and similarly it must not
459
458
// read the out arguments - they won't be set until the new
460
459
// function runs.
460
+
461
461
lv .cache .tailuevar = append (lv .cache .tailuevar , int32 (i ))
462
462
463
463
if node .Addrtaken () {
464
464
lv .cache .textavarinit = append (lv .cache .textavarinit , int32 (i ))
465
465
}
466
- lv .cache .textvarkill = append (lv .cache .textvarkill , int32 (i ))
467
466
468
467
case PPARAMOUT :
469
468
// If the result had its address taken, it is being tracked
@@ -500,31 +499,11 @@ func (lv *Liveness) progeffects(prog *obj.Prog) (uevar, varkill, avarinit []int3
500
499
return
501
500
}
502
501
503
- // A return instruction with a p.to is a tail return, which brings
504
- // the stack pointer back up (if it ever went down) and then jumps
505
- // to a new function entirely. That form of instruction must read
506
- // all the parameters for correctness, and similarly it must not
507
- // read the out arguments - they won't be set until the new
508
- // function runs.
509
- if (prog .As == obj .AJMP || prog .As == obj .ARET ) && prog .To .Type == obj .TYPE_MEM && prog .To .Name == obj .NAME_EXTERN {
510
- // This is a tail call. Ensure the arguments are still alive.
511
- // See issue 16016.
512
- return lv .cache .tailuevar , nil , nil
513
- }
514
-
515
- if prog .As == obj .ARET {
516
- if prog .To .Type == obj .TYPE_NONE {
517
- return lv .cache .retuevar , nil , nil
518
- }
502
+ switch prog .As {
503
+ case obj .ATEXT , obj .ARET , obj .AJMP , obj .AUNDEF :
519
504
return nil , nil , nil
520
505
}
521
506
522
- if prog .As == obj .ATEXT {
523
- // A text instruction marks the entry point to a function and
524
- // the definition point of all in arguments.
525
- return nil , lv .cache .textvarkill , lv .cache .textavarinit
526
- }
527
-
528
507
uevar = lv .cache .uevar [:0 ]
529
508
varkill = lv .cache .varkill [:0 ]
530
509
avarinit = lv .cache .avarinit [:0 ]
@@ -1020,17 +999,7 @@ func livenesssolve(lv *Liveness) {
1020
999
for change := true ; change ; {
1021
1000
change = false
1022
1001
for _ , bb := range lv .cfg {
1023
- any .Clear ()
1024
- all .Clear ()
1025
- for j , pred := range bb .pred {
1026
- if j == 0 {
1027
- any .Copy (pred .avarinitany )
1028
- all .Copy (pred .avarinitall )
1029
- } else {
1030
- any .Or (any , pred .avarinitany )
1031
- all .And (all , pred .avarinitall )
1032
- }
1033
- }
1002
+ lv .avarinitanyall (bb , any , all )
1034
1003
1035
1004
any .AndNot (any , bb .varkill )
1036
1005
all .AndNot (all , bb .varkill )
@@ -1060,13 +1029,34 @@ func livenesssolve(lv *Liveness) {
1060
1029
for i := len (lv .cfg ) - 1 ; i >= 0 ; i -- {
1061
1030
bb := lv .cfg [i ]
1062
1031
1063
- // A variable is live on output from this block
1064
- // if it is live on input to some successor.
1065
- //
1066
- // out[b] = \bigcup_{s \in succ[b]} in[s]
1067
1032
newliveout .Clear ()
1068
- for _ , succ := range bb .succ {
1069
- newliveout .Or (newliveout , succ .livein )
1033
+ if len (bb .succ ) == 0 {
1034
+ switch prog := bb .last ; {
1035
+ case prog .As == obj .ARET && prog .To .Type == obj .TYPE_NONE :
1036
+ // ssa.BlockRet
1037
+ for _ , pos := range lv .cache .retuevar {
1038
+ newliveout .Set (pos )
1039
+ }
1040
+ case (prog .As == obj .AJMP || prog .As == obj .ARET ) && prog .To .Type == obj .TYPE_MEM && prog .To .Name == obj .NAME_EXTERN :
1041
+ // ssa.BlockRetJmp
1042
+ for _ , pos := range lv .cache .tailuevar {
1043
+ newliveout .Set (pos )
1044
+ }
1045
+ case prog .As == obj .AUNDEF :
1046
+ // ssa.BlockExit
1047
+ // nothing to do
1048
+ default :
1049
+ Fatalf ("unexpected terminal prog: %v" , prog )
1050
+ }
1051
+ } else {
1052
+ // A variable is live on output from this block
1053
+ // if it is live on input to some successor.
1054
+ //
1055
+ // out[b] = \bigcup_{s \in succ[b]} in[s]
1056
+ newliveout .Copy (bb .succ [0 ].livein )
1057
+ for _ , succ := range bb .succ [1 :] {
1058
+ newliveout .Or (newliveout , succ .livein )
1059
+ }
1070
1060
}
1071
1061
1072
1062
if ! bb .liveout .Eq (newliveout ) {
@@ -1128,18 +1118,7 @@ func livenessepilogue(lv *Liveness) {
1128
1118
// Compute avarinitany and avarinitall for entry to block.
1129
1119
// This duplicates information known during livenesssolve
1130
1120
// but avoids storing two more vectors for each block.
1131
- any .Clear ()
1132
- all .Clear ()
1133
- for j := 0 ; j < len (bb .pred ); j ++ {
1134
- pred := bb .pred [j ]
1135
- if j == 0 {
1136
- any .Copy (pred .avarinitany )
1137
- all .Copy (pred .avarinitall )
1138
- } else {
1139
- any .Or (any , pred .avarinitany )
1140
- all .And (all , pred .avarinitall )
1141
- }
1142
- }
1121
+ lv .avarinitanyall (bb , any , all )
1143
1122
1144
1123
// Walk forward through the basic block instructions and
1145
1124
// allocate liveness maps for those instructions that need them.
@@ -1248,21 +1227,6 @@ func livenessepilogue(lv *Liveness) {
1248
1227
// Found an interesting instruction, record the
1249
1228
// corresponding liveness information.
1250
1229
1251
- // Useful sanity check: on entry to the function,
1252
- // the only things that can possibly be live are the
1253
- // input parameters.
1254
- if p .As == obj .ATEXT {
1255
- for j := int32 (0 ); j < liveout .n ; j ++ {
1256
- if ! liveout .Get (j ) {
1257
- continue
1258
- }
1259
- n := lv .vars [j ]
1260
- if n .Class != PPARAM {
1261
- Fatalf ("internal error: %v %L recorded as live on entry, p.Pc=%v" , Curfn .Func .Nname , n , p .Pc )
1262
- }
1263
- }
1264
- }
1265
-
1266
1230
// Record live variables.
1267
1231
live := lv .livevars [pos ]
1268
1232
live .Or (live , liveout )
@@ -1344,6 +1308,34 @@ func livenessepilogue(lv *Liveness) {
1344
1308
}
1345
1309
1346
1310
flusherrors ()
1311
+
1312
+ // Useful sanity check: on entry to the function,
1313
+ // the only things that can possibly be live are the
1314
+ // input parameters.
1315
+ for j , n := range lv .vars {
1316
+ if n .Class != PPARAM && lv .livevars [0 ].Get (int32 (j )) {
1317
+ Fatalf ("internal error: %v %L recorded as live on entry" , Curfn .Func .Nname , n )
1318
+ }
1319
+ }
1320
+ }
1321
+
1322
+ func (lv * Liveness ) avarinitanyall (bb * BasicBlock , any , all bvec ) {
1323
+ if len (bb .pred ) == 0 {
1324
+ any .Clear ()
1325
+ all .Clear ()
1326
+ for _ , pos := range lv .cache .textavarinit {
1327
+ any .Set (pos )
1328
+ all .Set (pos )
1329
+ }
1330
+ return
1331
+ }
1332
+
1333
+ any .Copy (bb .pred [0 ].avarinitany )
1334
+ all .Copy (bb .pred [0 ].avarinitall )
1335
+ for _ , pred := range bb .pred [1 :] {
1336
+ any .Or (any , pred .avarinitany )
1337
+ all .And (all , pred .avarinitall )
1338
+ }
1347
1339
}
1348
1340
1349
1341
// FNV-1 hash function constants.
0 commit comments