Changeset 131989 in webkit


Ignore:
Timestamp:
Oct 20, 2012 1:06:39 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

LLInt backends of non-ARM RISC platforms should be able to share code with the existing ARMv7 backend
https://bugs.webkit.org/show_bug.cgi?id=99745

Reviewed by Geoffrey Garen.

This moves all of the things in armv7.rb that I thought are generally useful out
into risc.rb. It also separates some phases (branch ops is separated into one
phase that does sensible things, and another that does things that are painfully
ARM-specific), and removes ARM assumptions from others by using a callback to
drive exactly what lowering must happen. The goal here is to minimize the future
maintenance burden of LLInt by ensuring that the various platforms share as much
lowering code as possible.

  • offlineasm/armv7.rb:
  • offlineasm/risc.rb: Added.
Location:
trunk/Source/JavaScriptCore
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r131982 r131989  
     12012-10-20  Filip Pizlo  <fpizlo@apple.com>
     2
     3        LLInt backends of non-ARM RISC platforms should be able to share code with the existing ARMv7 backend
     4        https://bugs.webkit.org/show_bug.cgi?id=99745
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This moves all of the things in armv7.rb that I thought are generally useful out
     9        into risc.rb. It also separates some phases (branch ops is separated into one
     10        phase that does sensible things, and another that does things that are painfully
     11        ARM-specific), and removes ARM assumptions from others by using a callback to
     12        drive exactly what lowering must happen. The goal here is to minimize the future
     13        maintenance burden of LLInt by ensuring that the various platforms share as much
     14        lowering code as possible.
     15
     16        * offlineasm/armv7.rb:
     17        * offlineasm/risc.rb: Added.
     18
    1192012-10-19  Filip Pizlo  <fpizlo@apple.com>
    220
  • trunk/Source/JavaScriptCore/offlineasm/armv7.rb

    r130826 r131989  
    1 # Copyright (C) 2011 Apple Inc. All rights reserved.
     1# Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
    22#
    33# Redistribution and use in source and binary forms, with or without
     
    2525require "ast"
    2626require "opt"
     27require "risc"
    2728
    2829class Node
     
    3435end
    3536
    36 class SpecialRegister < NoChildren
     37class SpecialRegister
    3738    def armV7Operand
    3839        @name
     
    134135
    135136#
    136 # Lowering of branch ops. For example:
    137 #
    138 # baddiz foo, bar, baz
    139 #
    140 # will become:
    141 #
    142 # addi foo, bar
    143 # bz baz
    144 #
    145 
    146 def armV7LowerBranchOps(list)
    147     newList = []
    148     list.each {
    149         | node |
    150         if node.is_a? Instruction
    151             annotation = node.annotation
    152             case node.opcode
    153             when /^b(addi|subi|ori|addp)/
    154                 op = $1
    155                 branch = "b" + $~.post_match
    156                
    157                 case op
    158                 when "addi", "addp"
    159                     op = "addis"
    160                 when "subi"
    161                     op = "subis"
    162                 when "ori"
    163                     op = "oris"
    164                 end
    165                
    166                 newList << Instruction.new(node.codeOrigin, op, node.operands[0..-2], annotation)
    167                 newList << Instruction.new(node.codeOrigin, branch, [node.operands[-1]])
    168             when "bmulio"
    169                 tmp1 = Tmp.new(node.codeOrigin, :gpr)
    170                 tmp2 = Tmp.new(node.codeOrigin, :gpr)
    171                 newList << Instruction.new(node.codeOrigin, "smulli", [node.operands[0], node.operands[1], node.operands[1], tmp1], annotation)
    172                 newList << Instruction.new(node.codeOrigin, "rshifti", [node.operands[-2], Immediate.new(node.codeOrigin, 31), tmp2])
    173                 newList << Instruction.new(node.codeOrigin, "bineq", [tmp1, tmp2, node.operands[-1]])
    174             when /^bmuli/
    175                 condition = $~.post_match
    176                 newList << Instruction.new(node.codeOrigin, "muli", node.operands[0..-2], annotation)
    177                 newList << Instruction.new(node.codeOrigin, "bti" + condition, [node.operands[-2], node.operands[-1]])
    178             else
    179                 newList << node
    180             end
    181         else
    182             newList << node
    183         end
    184     }
    185     newList
    186 end
    187 
    188 #
    189 # Lowering of shift ops. For example:
    190 #
    191 # lshifti foo, bar
    192 #
    193 # will become:
    194 #
    195 # andi foo, 31, tmp
    196 # lshifti tmp, bar
    197 #
    198 
    199 def armV7SanitizeShift(operand, list)
    200     return operand if operand.immediate?
    201    
    202     tmp = Tmp.new(operand.codeOrigin, :gpr)
    203     list << Instruction.new(operand.codeOrigin, "andi", [operand, Immediate.new(operand.codeOrigin, 31), tmp])
    204     tmp
    205 end
    206 
    207 def armV7LowerShiftOps(list)
    208     newList = []
    209     list.each {
    210         | node |
    211         if node.is_a? Instruction
    212             case node.opcode
    213             when "lshifti", "rshifti", "urshifti", "lshiftp", "rshiftp", "urshiftp"
    214                 if node.operands.size == 2
    215                     newList << Instruction.new(node.codeOrigin, node.opcode, [armV7SanitizeShift(node.operands[0], newList), node.operands[1]], node.annotation)
    216                 else
    217                     newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], armV7SanitizeShift(node.operands[1], newList), node.operands[2]], node.annotation)
    218                     raise "Wrong number of operands for shift at #{node.codeOriginString}" unless node.operands.size == 3
    219                 end
    220             else
    221                 newList << node
    222             end
    223         else
    224             newList << node
    225         end
    226     }
    227     newList
    228 end
    229 
    230 #
    231 # Lowering of malformed addresses. For example:
    232 #
    233 # loadp 10000[foo], bar
    234 #
    235 # will become:
    236 #
    237 # move 10000, tmp
    238 # addp foo, tmp
    239 # loadp 0[tmp], bar
    240 #
    241 
    242 class Node
    243     def armV7LowerMalformedAddressesRecurse(list)
    244         mapChildren {
    245             | node |
    246             node.armV7LowerMalformedAddressesRecurse(list)
    247         }
    248     end
    249 end
    250 
    251 class Address
    252     def armV7LowerMalformedAddressesRecurse(list)
    253         if offset.value < -0xff or offset.value > 0xfff
    254             tmp = Tmp.new(codeOrigin, :gpr)
    255             list << Instruction.new(codeOrigin, "move", [offset, tmp])
    256             list << Instruction.new(codeOrigin, "addp", [base, tmp])
    257             Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
    258         else
    259             self
    260         end
    261     end
    262 end
    263 
    264 class BaseIndex
    265     def armV7LowerMalformedAddressesRecurse(list)
    266         if offset.value != 0
    267             tmp = Tmp.new(codeOrigin, :gpr)
    268             list << Instruction.new(codeOrigin, "move", [offset, tmp])
    269             list << Instruction.new(codeOrigin, "addp", [base, tmp])
    270             BaseIndex.new(codeOrigin, tmp, index, scale, Immediate.new(codeOrigin, 0))
    271         else
    272             self
    273         end
    274     end
    275 end
    276 
    277 class AbsoluteAddress
    278     def armV7LowerMalformedAddressesRecurse(list)
    279         tmp = Tmp.new(codeOrigin, :gpr)
    280         list << Instruction.new(codeOrigin, "move", [address, tmp])
    281         Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
    282     end
    283 end
    284 
    285 def armV7LowerMalformedAddresses(list)
    286     newList = []
    287     list.each {
    288         | node |
    289         newList << node.armV7LowerMalformedAddressesRecurse(newList)
    290     }
    291     newList
    292 end
    293 
    294 #
    295 # Lowering of malformed addresses in double loads and stores. For example:
    296 #
    297 # loadd [foo, bar, 8], baz
    298 #
    299 # becomes:
    300 #
    301 # leap [foo, bar, 8], tmp
    302 # loadd [tmp], baz
    303 #
    304 
    305 class Node
    306     def armV7DoubleAddress(list)
    307         self
    308     end
    309 end
    310 
    311 class BaseIndex
    312     def armV7DoubleAddress(list)
    313         tmp = Tmp.new(codeOrigin, :gpr)
    314         list << Instruction.new(codeOrigin, "leap", [self, tmp])
    315         Address.new(codeOrigin, tmp, Immediate.new(codeOrigin, 0))
    316     end
    317 end
    318 
    319 def armV7LowerMalformedAddressesDouble(list)
    320     newList = []
    321     list.each {
    322         | node |
    323         if node.is_a? Instruction
    324             case node.opcode
    325             when "loadd"
    326                 newList << Instruction.new(node.codeOrigin, "loadd", [node.operands[0].armV7DoubleAddress(newList), node.operands[1]], node.annotation)
    327             when "stored"
    328                 newList << Instruction.new(node.codeOrigin, "stored", [node.operands[0], node.operands[1].armV7DoubleAddress(newList)], node.annotation)
    329             else
    330                 newList << node
    331             end
    332         else
    333             newList << node
    334         end
    335     }
    336     newList
    337 end
    338 
    339 #
    340 # Lowering of misplaced immediates. For example:
    341 #
    342 # storei 0, [foo]
    343 #
    344 # will become:
    345 #
    346 # move 0, tmp
    347 # storei tmp, [foo]
    348 #
    349 
    350 def armV7LowerMisplacedImmediates(list)
    351     newList = []
    352     list.each {
    353         | node |
    354         if node.is_a? Instruction
    355             case node.opcode
    356             when "storeb", "storei", "storep"
    357                 operands = node.operands
    358                 newOperands = []
    359                 operands.each {
    360                     | operand |
    361                     if operand.is_a? Immediate
    362                         tmp = Tmp.new(operand.codeOrigin, :gpr)
    363                         newList << Instruction.new(operand.codeOrigin, "move", [operand, tmp])
    364                         newOperands << tmp
    365                     else
    366                         newOperands << operand
    367                     end
    368                 }
    369                 newList << Instruction.new(node.codeOrigin, node.opcode, newOperands, node.annotation)
    370             else
    371                 newList << node
    372             end
    373         else
    374             newList << node
    375         end
    376     }
    377     newList
    378 end
    379 
    380 #
    381 # Lowering of malformed immediates except when used in a "move" instruction.
    382 # For example:
    383 #
    384 # addp 642641, foo
    385 #
    386 # will become:
    387 #
    388 # move 642641, tmp
    389 # addp tmp, foo
    390 #
    391 
    392 class Node
    393     def armV7LowerMalformedImmediatesRecurse(list)
    394         mapChildren {
    395             | node |
    396             node.armV7LowerMalformedImmediatesRecurse(list)
    397         }
    398     end
    399 end
    400 
    401 class Address
    402     def armV7LowerMalformedImmediatesRecurse(list)
    403         self
    404     end
    405 end
    406 
    407 class BaseIndex
    408     def armV7LowerMalformedImmediatesRecurse(list)
    409         self
    410     end
    411 end
    412 
    413 class AbsoluteAddress
    414     def armV7LowerMalformedImmediatesRecurse(list)
    415         self
    416     end
    417 end
    418 
    419 class Immediate
    420     def armV7LowerMalformedImmediatesRecurse(list)
    421         if value < 0 or value > 255
    422             tmp = Tmp.new(codeOrigin, :gpr)
    423             list << Instruction.new(codeOrigin, "move", [self, tmp])
    424             tmp
    425         else
    426             self
    427         end
    428     end
    429 end
    430 
    431 def armV7LowerMalformedImmediates(list)
    432     newList = []
    433     list.each {
    434         | node |
    435         if node.is_a? Instruction
    436             annotation = node.annotation
    437             case node.opcode
    438             when "move"
    439                 newList << node
    440             when "addi", "addp", "addis", "subi", "subp", "subis"
    441                 if node.operands[0].is_a? Immediate and
    442                         node.operands[0].value < 0 and
    443                         node.operands[0].value >= 255 and
    444                         node.operands.size == 2
    445                     if node.opcode =~ /add/
    446                         newOpcode = "sub" + node.opcode[-1..-1]
    447                     else
    448                         newOpcode = "add" + node.opcode[-1..-1]
    449                     end
    450                     newList << Instruction.new(node.codeOrigin, newOpcode,
    451                                                [Immediate.new(-node.operands[0].value)] + node.operands[1..-1],
    452                                                annotation)
    453                 else
    454                     newList << node.armV7LowerMalformedImmediatesRecurse(newList)
    455                 end
    456             when "muli", "mulp"
    457                 if node.operands[0].is_a? Immediate
    458                     tmp = Tmp.new(codeOrigin, :gpr)
    459                     newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
    460                     newList << Instruction.new(node.codeOrigin, "muli", [tmp] + node.operands[1..-1])
    461                 else
    462                     newList << node.armV7LowerMalformedImmediatesRecurse(newList)
    463                 end
    464             else
    465                 newList << node.armV7LowerMalformedImmediatesRecurse(newList)
    466             end
    467         else
    468             newList << node
    469         end
    470     }
    471     newList
    472 end
    473 
    474 #
    475 # Lowering of misplaced addresses. For example:
    476 #
    477 # addi foo, [bar]
    478 #
    479 # will become:
    480 #
    481 # loadi [bar], tmp
    482 # addi foo, tmp
    483 # storei tmp, [bar]
    484 #
    485 # Another example:
    486 #
    487 # addi [foo], bar
    488 #
    489 # will become:
    490 #
    491 # loadi [foo], tmp
    492 # addi tmp, bar
    493 #
    494 
    495 def armV7AsRegister(preList, postList, operand, suffix, needStore)
    496     return operand unless operand.address?
    497    
    498     tmp = Tmp.new(operand.codeOrigin, if suffix == "d" then :fpr else :gpr end)
    499     preList << Instruction.new(operand.codeOrigin, "load" + suffix, [operand, tmp])
    500     if needStore
    501         postList << Instruction.new(operand.codeOrigin, "store" + suffix, [tmp, operand])
    502     end
    503     tmp
    504 end
    505 
    506 def armV7AsRegisters(preList, postList, operands, suffix)
    507     newOperands = []
    508     operands.each_with_index {
    509         | operand, index |
    510         newOperands << armV7AsRegister(preList, postList, operand, suffix, index == operands.size - 1)
    511     }
    512     newOperands
    513 end
    514 
    515 def armV7LowerMisplacedAddresses(list)
    516     newList = []
    517     list.each {
    518         | node |
    519         if node.is_a? Instruction
    520             postInstructions = []
    521             annotation = node.annotation
    522             case node.opcode
    523             when "addi", "addp", "addis", "andi", "andp", "lshifti", "lshiftp", "muli", "mulp", "negi",
    524                 "negp", "noti", "ori", "oris", "orp", "rshifti", "urshifti", "rshiftp", "urshiftp", "subi",
    525                 "subp", "subis", "xori", "xorp", /^bi/, /^bp/, /^bti/, /^btp/, /^ci/, /^cp/, /^ti/
    526                 newList << Instruction.new(node.codeOrigin,
    527                                            node.opcode,
    528                                            armV7AsRegisters(newList, postInstructions, node.operands, "i"),
    529                                            annotation)
    530             when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbz", "btbnz", "tbz", "tbnz",
    531                 "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq"
    532                 newList << Instruction.new(node.codeOrigin,
    533                                            node.opcode,
    534                                            armV7AsRegisters(newList, postInstructions, node.operands, "b"),
    535                                            annotation)
    536             when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs", "cbgt", "cbgteq", "cblt", "cblteq"
    537                 newList << Instruction.new(node.codeOrigin,
    538                                            node.opcode,
    539                                            armV7AsRegisters(newList, postInstructions, node.operands, "bs"),
    540                                            annotation)
    541             when "addd", "divd", "subd", "muld", "sqrtd", /^bd/
    542                 newList << Instruction.new(node.codeOrigin,
    543                                            node.opcode,
    544                                            armV7AsRegisters(newList, postInstructions, node.operands, "d"),
    545                                            annotation)
    546             when "jmp", "call"
    547                 newList << Instruction.new(node.codeOrigin,
    548                                            node.opcode,
    549                                            [armV7AsRegister(newList, postInstructions, node.operands[0], "p", false)],
    550                                            annotation)
    551             else
    552                 newList << node
    553             end
    554             newList += postInstructions
    555         else
    556             newList << node
    557         end
    558     }
    559     newList
    560 end
    561 
    562 #
    563 # Lowering of register reuse in compare instructions. For example:
    564 #
    565 # cieq t0, t1, t0
    566 #
    567 # will become:
    568 #
    569 # mov tmp, t0
    570 # cieq tmp, t1, t0
    571 #
    572 
    573 def armV7LowerRegisterReuse(list)
    574     newList = []
    575     list.each {
    576         | node |
    577         if node.is_a? Instruction
    578             annotation = node.annotation
    579             case node.opcode
    580             when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq",
    581                 "cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq",
    582                 "tis", "tiz", "tinz", "tbs", "tbz", "tbnz", "tps", "tpz", "tpnz", "cbeq", "cbneq",
    583                 "cba", "cbaeq", "cbb", "cbbeq", "cbgt", "cbgteq", "cblt", "cblteq"
    584                 if node.operands.size == 2
    585                     if node.operands[0] == node.operands[1]
    586                         tmp = Tmp.new(node.codeOrigin, :gpr)
    587                         newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
    588                         newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1]])
    589                     else
    590                         newList << node
    591                     end
    592                 else
    593                     raise "Wrong number of arguments at #{node.codeOriginString}" unless node.operands.size == 3
    594                     if node.operands[0] == node.operands[2]
    595                         tmp = Tmp.new(node.codeOrigin, :gpr)
    596                         newList << Instruction.new(node.codeOrigin, "move", [node.operands[0], tmp], annotation)
    597                         newList << Instruction.new(node.codeOrigin, node.opcode, [tmp, node.operands[1], node.operands[2]])
    598                     elsif node.operands[1] == node.operands[2]
    599                         tmp = Tmp.new(node.codeOrigin, :gpr)
    600                         newList << Instruction.new(node.codeOrigin, "move", [node.operands[1], tmp], annotation)
    601                         newList << Instruction.new(node.codeOrigin, node.opcode, [node.operands[0], tmp, node.operands[2]])
    602                     else
    603                         newList << node
    604                     end
    605                 end
    606             else
    607                 newList << node
    608             end
    609         else
    610             newList << node
    611         end
    612     }
    613     newList
    614 end
    615 
    616 #
    617137# Lea support.
    618138#
     
    643163class Sequence
    644164    def getModifiedListARMv7
    645         myList = @list
    646        
    647         # Verify that we will only see instructions and labels.
    648         myList.each {
    649             | node |
    650             unless node.is_a? Instruction or
    651                     node.is_a? Label or
    652                     node.is_a? LocalLabel or
    653                     node.is_a? Skip
    654                 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
     165        result = @list
     166        result = riscLowerSimpleBranchOps(result)
     167        result = riscLowerHardBranchOps(result)
     168        result = riscLowerShiftOps(result)
     169        result = riscLowerMalformedAddresses(result) {
     170            | node, address |
     171            if address.is_a? BaseIndex
     172                address.offset.value == 0
     173            elsif address.is_a? Address
     174                (-0xff..0xfff).include? address.offset.value
     175            else
     176                false
    655177            end
    656178        }
    657        
    658         myList = armV7LowerBranchOps(myList)
    659         myList = armV7LowerShiftOps(myList)
    660         myList = armV7LowerMalformedAddresses(myList)
    661         myList = armV7LowerMalformedAddressesDouble(myList)
    662         myList = armV7LowerMisplacedImmediates(myList)
    663         myList = armV7LowerMalformedImmediates(myList)
    664         myList = armV7LowerMisplacedAddresses(myList)
    665         myList = armV7LowerRegisterReuse(myList)
    666         myList = assignRegistersToTemporaries(myList, :gpr, ARMv7_EXTRA_GPRS)
    667         myList = assignRegistersToTemporaries(myList, :fpr, ARMv7_EXTRA_FPRS)
    668        
    669         return myList
     179        result = riscLowerMalformedAddressesDouble(result)
     180        result = riscLowerMisplacedImmediates(result)
     181        result = riscLowerMalformedImmediates(result, 0..0xff)
     182        result = riscLowerMisplacedAddresses(result)
     183        result = riscLowerRegisterReuse(result)
     184        result = assignRegistersToTemporaries(result, :gpr, ARMv7_EXTRA_GPRS)
     185        result = assignRegistersToTemporaries(result, :fpr, ARMv7_EXTRA_FPRS)
     186        return result
    670187    end
    671188end
     
    748265
    749266        case opcode
    750         when "addi", "addp", "addis"
    751             if opcode == "addis"
     267        when "addi", "addp", "addis", "addps"
     268            if opcode == "addis" or opcode == "addps"
    752269                suffix = "s"
    753270            else
     
    838355            $asm.puts "vmrs apsr_nzcv, fpscr"
    839356            isUnordered = LocalLabel.unique("bdneq")
    840             $asm.puts "bvs #{LabelReference.new(codeOrigin, isUnordered).asmLabel}"
     357            $asm.puts "bvs #{LocalLabelReference.new(codeOrigin, isUnordered).asmLabel}"
    841358            $asm.puts "bne #{operands[2].asmLabel}"
    842359            isUnordered.lower("ARMv7")
Note: See TracChangeset for help on using the changeset viewer.