diff --git a/src/Tinyrossa/TRLinearScanRegisterAllocator.class.st b/src/Tinyrossa/TRLinearScanRegisterAllocator.class.st deleted file mode 100644 index 4a4d8a4..0000000 --- a/src/Tinyrossa/TRLinearScanRegisterAllocator.class.st +++ /dev/null @@ -1,126 +0,0 @@ -" -`TRLinearScanRegisterAllocator` is the old register allocator superseded by -`TRReverseLinearScanRegisterAllocator`. - -It's straightforward reimplementation from original 1999 paper [1] Note that -there's no need to deal with virtual registers being used across -basic block boundary - in Tinyrossa (as well as in Testarossa), the only way -to transfer value from one (extended) block to another is via `?store` and -`?load` IL operations. - -[1]: MASSIMILIANO POLETTO and VIVEK SARKAR: Linear Scan Register Allocation - http://web.cs.ucla.edu/~palsberg/course/cs132/linearscan.pdf - -" -Class { - #name : #TRLinearScanRegisterAllocator, - #superclass : #TRRegisterAllocator, - #instVars : [ - 'liveRanges', - 'activeRanges', - 'allocatableRegisters', - 'availableRegisters' - ], - #category : #'Tinyrossa-Codegen-Register Allocation' -} - -{ #category : #allocation } -TRLinearScanRegisterAllocator >> allocateRegisterFor: aTRVirtualRegister [ - self assert: aTRVirtualRegister allocation isNil. - - allocatableRegisters do: [:rReg | - (availableRegisters includes: rReg) ifTrue: [ - aTRVirtualRegister allocation: rReg. - availableRegisters remove: rReg. - ^ self. - ]. - ]. - self error: 'Should not happen!'. -] - -{ #category : #allocation } -TRLinearScanRegisterAllocator >> allocateRegisters [ - | insns | - - insns := codegen instructions. - allocatableRegisters := codegen linkage allocatableRegisters. - availableRegisters := allocatableRegisters asSet. - activeRanges := SortedCollection sortBlock: [ :a :b | a stop < b stop ]. - - "Step 1 - compute live intervals." - liveRanges := Dictionary new. - codegen virtualRegisters do: [:vReg | - liveRanges at: vReg put: (TRRegisterLiveInterval forRegister: vReg). - ]. - 1 to: insns size do: [:i | - | insn | - - insn := insns at: i. - codegen virtualRegistersUsedBy: insn do: [:vreg | - | liveRange | - - liveRange := liveRanges at: vreg. - liveRange used: i. - ]. - ]. - - " - Step 2. Allocate registers using collected intervals. - " - liveRanges := liveRanges associations sort: [ :a :b | a start < b start ]. - liveRanges do: [:liveRange | - self assert: liveRange start odd. - self assert: liveRange stop even. - self assert: liveRange start < liveRange stop. - - self expireOldIntervals: liveRange. - availableRegisters isEmpty ifTrue: [ - self error: 'Spilling not supported yet!' - ] ifFalse: [ - self allocateRegisterFor: liveRange. - activeRanges add: liveRange - ]. - ]. - - " - Step 3. Insert register moves to satisfy register dependencies - " - insns size downTo: 1 do: [:i | - | insn deps | - - insn := insns at: i. - deps := insn dependencies. - - deps notEmptyOrNil ifTrue: [ - codegen cursor: i. - deps post do: [:dep | - dep isDependency ifTrue:[ - self insertMoveFrom: dep rreg to: dep vreg. - ]. - ]. - - codegen cursor: i - 1. - deps pre do: [:dep | - dep isDependency ifTrue:[ - self insertMoveFrom: dep vreg to: dep rreg. - ]. - - ]. - ]. - ]. -] - -{ #category : #allocation } -TRLinearScanRegisterAllocator >> expireOldIntervals: newRange [ - self expireOldIntervalsAt: newRange start -] - -{ #category : #allocation } -TRLinearScanRegisterAllocator >> expireOldIntervalsAt: i [ - [ activeRanges notEmpty and:[ activeRanges first stop <= i ] ] whileTrue: [ - | expiredRange | - - expiredRange := activeRanges removeFirst. - availableRegisters add: expiredRange allocation - ]. -] diff --git a/src/Tinyrossa/TRNaiveConstraintSolvingRegisterAllocator.class.st b/src/Tinyrossa/TRNaiveConstraintSolvingRegisterAllocator.class.st deleted file mode 100644 index 4fefa49..0000000 --- a/src/Tinyrossa/TRNaiveConstraintSolvingRegisterAllocator.class.st +++ /dev/null @@ -1,59 +0,0 @@ -Class { - #name : #TRNaiveConstraintSolvingRegisterAllocator, - #superclass : #TRRegisterAllocator, - #category : #'Tinyrossa-Codegen-Register Allocation' -} - -{ #category : #allocation } -TRNaiveConstraintSolvingRegisterAllocator >> allocateRegisters [ - " - Following code is bogus, it does not really work. - Cannot handle running out of registers. Cannot spill. - Does not handle register liveness. Essentially it does - work only for very simple cases. - But hey, it does simulate register allocation and - it took mi literraly 5 mins to write it :-) - " - - | realRegisters insns solver | - - insns := codegen instructions. - realRegisters := codegen linkage allocatableRegisters. - solver := Z3Solver new. - - " - First, make sure each virtual register gets mapped to - some real, allocatable register. - " - codegen virtualRegisters do: [:vReg | - solver assert: (Bool or: (realRegisters collect: [ :rReg | vReg toInt eq: rReg toInt ])). - ]. - - " - Third, make sure that mapping has no conflicts. - Following code is absolutely bogus as it does not - take liveness into an account, but will do for now. - " - insns do: [:insn | - | used | - - used := codegen virtualRegistersUsedBy: insn. - used do: [:usedReg1 | used do: [:usedReg2 | - usedReg1 ~~ usedReg2 ifTrue: [ - solver assert: (usedReg1 toInt eq: usedReg2 toInt) not - ]. - ]]. - ]. - - solver check ifFalse: [ - self error: 'I give up, you''d better ask mr Chaitin help you here!' - ]. - - solver getModel constants keysAndValuesDo: [:vRegName :rRegValue | - | vReg rReg | - - vReg := codegen virtualRegisters at: vRegName. - rReg := realRegisters detect: [:each | each value = rRegValue value ]. - vReg allocation: rReg. - ]. -]