Changeset 157452 in webkit


Ignore:
Timestamp:
Oct 15, 2013 11:03:42 AM (11 years ago)
Author:
commit-queue@webkit.org
Message:

[sh4] Introduce const pools in LLINT.
https://bugs.webkit.org/show_bug.cgi?id=122746

Patch by Julien Brianceau <jbriance@cisco.com> on 2013-10-15
Reviewed by Michael Saboff.

In current implementation of LLINT for sh4, immediate values outside range -128..127 are
loaded this way:

mov.l .label, rx
bra out
nop
.balign 4
.label: .long immvalue
out:

This change introduces const pools for sh4 implementation to avoid lots of useless branches
and reduce code size. It also removes lines of dirty code, like jmpf and callf.

  • offlineasm/instructions.rb: Remove jmpf and callf sh4 specific instructions.
  • offlineasm/sh4.rb:
Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r157451 r157452  
     12013-10-15  Julien Brianceau  <jbriance@cisco.com>
     2
     3        [sh4] Introduce const pools in LLINT.
     4        https://bugs.webkit.org/show_bug.cgi?id=122746
     5
     6        Reviewed by Michael Saboff.
     7
     8        In current implementation of LLINT for sh4, immediate values outside range -128..127 are
     9        loaded this way:
     10
     11            mov.l .label, rx
     12            bra out
     13            nop
     14            .balign 4
     15            .label: .long immvalue
     16            out:
     17
     18        This change introduces const pools for sh4 implementation to avoid lots of useless branches
     19        and reduce code size. It also removes lines of dirty code, like jmpf and callf.
     20
     21        * offlineasm/instructions.rb: Remove jmpf and callf sh4 specific instructions.
     22        * offlineasm/sh4.rb:
     23
    1242013-10-15  Mark Lam  <mark.lam@apple.com>
    225
  • trunk/Source/JavaScriptCore/offlineasm/instructions.rb

    r154095 r157452  
    286286    "storedReversedAndDecrementAddress",
    287287    "ldspr",
    288     "stspr",
    289     "callf",
    290     "jmpf"
     288    "stspr"
    291289    ]
    292290
  • trunk/Source/JavaScriptCore/offlineasm/sh4.rb

    r155876 r157452  
    145145end
    146146
     147class ConstPool < Node
     148    attr_reader :size
     149    attr_reader :entries
     150
     151    def initialize(codeOrigin, entries, size)
     152        super(codeOrigin)
     153        raise "Invalid size #{size} for ConstPool" unless size == 16 or size == 32
     154        @size = size
     155        @entries = entries
     156    end
     157   
     158    def dump
     159        "#{size}: #{entries}"
     160    end
     161   
     162    def address?
     163        false
     164    end
     165   
     166    def label?
     167        false
     168    end
     169   
     170    def immediate?
     171        false
     172    end
     173   
     174    def register?
     175        false
     176    end
     177
     178    def lowerSH4
     179        if size == 16
     180            $asm.puts ".balign 2"
     181        else
     182            $asm.puts ".balign 4"
     183        end
     184        entries.map {
     185            |e|
     186            e.label.lower("SH4")
     187            if e.size == 16
     188                $asm.puts ".word #{e.value}"
     189            else
     190                $asm.puts ".long #{e.value}"
     191            end
     192        }
     193    end
     194end
     195
     196class ConstPoolEntry < Node
     197    attr_reader :size
     198    attr_reader :value
     199    attr_reader :label
     200    attr_reader :labelref
     201   
     202    def initialize(codeOrigin, value, size)
     203        super(codeOrigin)
     204        raise "Invalid size #{size} for ConstPoolEntry" unless size == 16 or size == 32
     205        @size = size
     206        @value = value
     207        @label = LocalLabel.unique("constpool#{size}")
     208        @labelref = LocalLabelReference.new(codeOrigin, label)
     209    end
     210   
     211    def dump
     212        "#{value} (#{size} @ #{label})"
     213    end
     214   
     215    def ==(other)
     216        other.is_a? ConstPoolEntry and other.value == @value
     217    end
     218   
     219    def address?
     220        false
     221    end
     222   
     223    def label?
     224        false
     225    end
     226   
     227    def immediate?
     228        false
     229    end
     230   
     231    def register?
     232        false
     233    end
     234end
     235
    147236
    148237#
     
    359448        if node.is_a? Instruction
    360449            case node.opcode
    361             when "jmp"
     450            when "jmp", "call"
    362451                if node.operands[0].is_a? LabelReference
    363452                    tmp = Tmp.new(codeOrigin, :gpr)
    364                     newList << Instruction.new(codeOrigin, "jmpf", [tmp, node.operands[0]])
     453                    newList << Instruction.new(codeOrigin, "move", [node.operands[0], tmp])
     454                    newList << Instruction.new(codeOrigin, node.opcode, [tmp])
    365455                else
    366456                    newList << node
    367457                end
    368             when "call"
    369                 if node.operands[0].is_a? LabelReference
    370                     tmp1 = Tmp.new(codeOrigin, :gpr)
    371                     tmp2 = Tmp.new(codeOrigin, :gpr)
    372                     newList << Instruction.new(codeOrigin, "callf", [tmp1, tmp2, node.operands[0]])
     458            else
     459                newList << node
     460            end
     461        else
     462            newList << node
     463        end
     464    }
     465    newList
     466end
     467
     468
     469#
     470# Group immediate values outside -128..127 range into constant pools for SH4.
     471# These constant pools will be placed behind non-return opcodes jmp and ret, for example:
     472#
     473# move 1024, foo
     474# ...
     475# ret
     476#
     477# becomes:
     478#
     479# move [label], foo
     480# ...
     481# ret
     482# label: 1024
     483#
     484
     485def sh4LowerConstPool(list)
     486    newList = []
     487    currentPool16 = []
     488    currentPool32 = []
     489    list.each {
     490        | node |
     491        if node.is_a? Instruction
     492            case node.opcode
     493            when "jmp", "ret"
     494                newList << node
     495                if not currentPool16.empty?
     496                    newList << ConstPool.new(codeOrigin, currentPool16, 16)
     497                    currentPool16 = []
     498                end
     499                if not currentPool32.empty?
     500                    newList << ConstPool.new(codeOrigin, currentPool32, 32)
     501                    currentPool32 = []
     502                end
     503            when "move"
     504                if node.operands[0].is_a? Immediate and not (-128..127).include? node.operands[0].value
     505                    poolEntry = nil
     506                    if (-32768..32767).include? node.operands[0].value
     507                        currentPool16.each { |e|
     508                            if e.value == node.operands[0].value
     509                                poolEntry = e
     510                            end
     511                        }
     512                        if !poolEntry
     513                            poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 16)
     514                            currentPool16 << poolEntry
     515                        end
     516                    else
     517                        currentPool32.each { |e|
     518                            if e.value == node.operands[0].value
     519                                poolEntry = e
     520                            end
     521                        }
     522                        if !poolEntry
     523                            poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].value, 32)
     524                            currentPool32 << poolEntry
     525                        end
     526                    end
     527                    newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]])
     528                elsif node.operands[0].is_a? LabelReference
     529                    poolEntry = nil
     530                    currentPool32.each { |e|
     531                        if e.value == node.operands[0].asmLabel
     532                            poolEntry = e
     533                        end
     534                    }
     535                    if !poolEntry
     536                        poolEntry = ConstPoolEntry.new(codeOrigin, node.operands[0].asmLabel, 32)
     537                        currentPool32 << poolEntry
     538                    end
     539                    newList << Instruction.new(codeOrigin, "move", [poolEntry, node.operands[1]])
    373540                else
    374541                    newList << node
     
    381548        end
    382549    }
     550    if not currentPool16.empty?
     551        newList << ConstPool.new(codeOrigin, currentPool16, 16)
     552    end
     553    if not currentPool32.empty?
     554        newList << ConstPool.new(codeOrigin, currentPool32, 32)
     555    end
    383556    newList
    384557end
     
    434607        result = assignRegistersToTemporaries(result, :gpr, SH4_TMP_FPRS)
    435608
     609        result = sh4LowerConstPool(result)
     610
    436611        return result
    437612    end
     
    440615def sh4Operands(operands)
    441616    operands.map{|v| v.sh4Operand}.join(", ")
    442 end
    443 
    444 def emitSH4Load32AndJump(constant, scratch)
    445     $asm.puts "mov.l 2f, #{scratch.sh4Operand}"
    446     $asm.puts "braf #{scratch.sh4Operand}"
    447     $asm.puts "nop"
    448     $asm.puts "1: .balign 4"
    449     $asm.puts "2: .long #{constant}-1b"
    450 end
    451 
    452 def emitSH4LoadImm(operands)
    453     if operands[0].value == 0x40000000
    454         # FirstConstantRegisterIndex const is often used (0x40000000).
    455         # It's more efficient to "build" the value with 3 opcodes without branch.
    456         $asm.puts "mov #64, #{operands[1].sh4Operand}"
    457         $asm.puts "shll16 #{operands[1].sh4Operand}"
    458         $asm.puts "shll8 #{operands[1].sh4Operand}"
    459     elsif (-128..127).include? operands[0].value
    460         $asm.puts "mov #{sh4Operands(operands)}"
    461     elsif (-32768..32767).include? operands[0].value
    462         constlabel = LocalLabel.unique("loadconstant")
    463         $asm.puts "mov.w @(6, PC), #{operands[1].sh4Operand}"
    464         $asm.puts "bra #{LocalLabelReference.new(codeOrigin, constlabel).asmLabel}"
    465         $asm.puts "nop"
    466         $asm.puts ".word #{operands[0].value}"
    467         constlabel.lower("SH4")
    468     else
    469         outlabel = LocalLabel.unique("load32out")
    470         constlabel = LocalLabel.unique("load32const")
    471         $asm.puts "mov.l #{LocalLabelReference.new(codeOrigin, constlabel).asmLabel}, #{operands[1].sh4Operand}"
    472         $asm.puts "bra #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}"
    473         $asm.puts "nop"
    474         $asm.puts ".balign 4"
    475         constlabel.lower("SH4")
    476         $asm.puts ".long #{operands[0].value}"
    477         outlabel.lower("SH4")
    478     end
    479617end
    480618
     
    507645    sh4opcode = neg ? "bt" : "bf"
    508646    $asm.puts "#{sh4opcode} #{LocalLabelReference.new(codeOrigin, outlabel).asmLabel}"
    509     if label.is_a? LocalLabelReference
    510         $asm.puts "bra #{label.asmLabel}"
    511         $asm.puts "nop"
    512     else
    513         emitSH4Load32AndJump(label.asmLabel, SH4_TMP_GPRS[0])
    514     end
     647    $asm.puts "bra #{label.asmLabel}"
     648    $asm.puts "nop"
    515649    outlabel.lower("SH4")
    516650end
     
    572706        when "subi", "subp"
    573707            if operands.size == 3
    574                 if operands[1] == operands[2]
     708                if operands[1].sh4Operand == operands[2].sh4Operand
    575709                    $asm.puts "neg #{sh4Operands([operands[2], operands[2]])}"
    576710                    $asm.puts "add #{sh4Operands([operands[0], operands[2]])}"
     
    715849                raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}"
    716850            end
    717         when "callf"
    718             $asm.puts ".balign 4"
    719             $asm.puts "mov r0, #{operands[0].sh4Operand}"
    720             $asm.puts "mova @(14, PC), r0"
    721             $asm.puts "lds r0, pr"
    722             $asm.puts "mov.l @(6, PC), #{operands[1].sh4Operand}"
    723             $asm.puts "braf #{operands[1].sh4Operand}"
    724             $asm.puts "mov #{operands[0].sh4Operand}, r0"
    725             $asm.puts ".long #{operands[2].asmLabel}-."
    726851        when "jmp"
    727852            if operands[0].is_a? LocalLabelReference
     
    733858                raise "Unhandled parameters for opcode #{opcode} at #{codeOriginString}"
    734859            end
    735         when "jmpf"
    736             emitSH4Load32AndJump(operands[1].asmLabel, operands[0])
    737860        when "ret"
    738861            $asm.puts "rts"
     
    749872            $asm.puts "mov.l #{sh4Operands(operands)}"
    750873        when "move"
    751             if operands[0].is_a? Immediate
    752                 emitSH4LoadImm(operands)
     874            if operands[0].is_a? ConstPoolEntry
     875                if operands[0].size == 16
     876                    $asm.puts "mov.w #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}"
     877                else
     878                    $asm.puts "mov.l #{operands[0].labelref.asmLabel}, #{operands[1].sh4Operand}"
     879                end
    753880            else
    754881                $asm.puts "mov #{sh4Operands(operands)}"
Note: See TracChangeset for help on using the changeset viewer.