rubycc 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -0
  3. data/README.md +26 -14
  4. data/data/verified_gems.json +85 -63
  5. data/exe/rubycc-ar +11 -3
  6. data/include/libc/sys/cdefs.h +12 -0
  7. data/lib/rubycc/backend/aarch64.rb +705 -117
  8. data/lib/rubycc/backend/slot_residency.rb +169 -0
  9. data/lib/rubycc/backend/x86_64.rb +924 -137
  10. data/lib/rubycc/command_line.rb +339 -0
  11. data/lib/rubycc/compile_error.rb +6 -3
  12. data/lib/rubycc/compiler.rb +17 -2
  13. data/lib/rubycc/diagnostics.rb +105 -0
  14. data/lib/rubycc/doctor/gemfile.rb +12 -3
  15. data/lib/rubycc/doctor/verified_gems.rb +5 -1
  16. data/lib/rubycc/driver.rb +66 -10
  17. data/lib/rubycc/front/ast.rb +18 -7
  18. data/lib/rubycc/front/constant_evaluator.rb +12 -0
  19. data/lib/rubycc/front/lexeme_reader.rb +3 -1
  20. data/lib/rubycc/front/parser.rb +51 -18
  21. data/lib/rubycc/ir/analysis.rb +82 -0
  22. data/lib/rubycc/ir/call_convention.rb +74 -7
  23. data/lib/rubycc/ir/generator.rb +319 -9
  24. data/lib/rubycc/ir/ir.rb +39 -1
  25. data/lib/rubycc/ir/promotion.rb +255 -0
  26. data/lib/rubycc/ir/simplify.rb +570 -0
  27. data/lib/rubycc/link/library_resolver.rb +17 -5
  28. data/lib/rubycc/link/partial_linker.rb +8 -1
  29. data/lib/rubycc/link/shared_linker.rb +2 -2
  30. data/lib/rubycc/mkmf_shim.rb +178 -12
  31. data/lib/rubycc/objfile/ar_archive.rb +13 -2
  32. data/lib/rubycc/objfile/elf_reader.rb +13 -2
  33. data/lib/rubycc/pkgconf/parser.rb +4 -0
  34. data/lib/rubycc/pkgconf/resolver.rb +3 -1
  35. data/lib/rubycc/pkgconf/system_path_filter.rb +8 -2
  36. data/lib/rubycc/preprocess/preprocessor.rb +161 -37
  37. data/lib/rubycc/preprocess/scanner.rb +69 -14
  38. data/lib/rubycc/preprocess/token_converter.rb +11 -1
  39. data/lib/rubycc/rmake/cli.rb +32 -4
  40. data/lib/rubycc/rmake/executor.rb +157 -226
  41. data/lib/rubycc/rmake/makefile.rb +35 -13
  42. data/lib/rubycc/rmake/parser.rb +8 -2
  43. data/lib/rubycc/rmake/rmake.rb +1 -0
  44. data/lib/rubycc/rmake/tool_command.rb +69 -0
  45. data/lib/rubycc/shell.rb +510 -0
  46. data/lib/rubycc/type.rb +23 -7
  47. data/lib/rubycc/version.rb +1 -1
  48. data/lib/rubycc.rb +12 -0
  49. data/lib/rubygems_plugin.rb +31 -3
  50. metadata +14 -3
@@ -1,13 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "../ir/ir"
4
+ require_relative "../ir/analysis"
5
+ require_relative "../ir/promotion"
6
+ require_relative "../ir/simplify"
7
+ require_relative "slot_residency"
4
8
 
5
9
  module Rubycc
6
10
  module Backend
7
11
  # x86_64 code generator using a spill-everything strategy: every virtual
8
12
  # register lives in its own 8-byte stack slot at [rbp - 8*(n+1)], and each
9
13
  # IR instruction loads its operands into eax/ecx, computes, and stores the
10
- # result back. Arithmetic on a 4-byte-or-narrower type stays 32-bit (using
14
+ # result back. Two kinds of value are exempt: a transient, which stays in
15
+ # the register its producer left it in (IR::Simplify#transient_vregs), and a
16
+ # promoted one, which owns a callee-saved register for the whole function
17
+ # and so has no slot at all (IR::Promotion, #promotion_assignment).
18
+ #
19
+ # Arithmetic on a 4-byte-or-narrower type stays 32-bit (using
11
20
  # eax/ecx), whose natural wrap-around reproduces C's semantics for free;
12
21
  # `long`/`unsigned long`/pointer arithmetic is 64-bit (a REX.W prefix,
13
22
  # selected by an IR op's size == 8). Slots are always read and written 64
@@ -47,6 +56,13 @@ module Rubycc
47
56
  # argument registers into a 176-byte register-save area so __builtin_va_arg
48
57
  # can reach the variable part.
49
58
  class X86_64
59
+ # Every slot access goes through #load_reg / #store_reg, which use this to
60
+ # skip a reload of a value the previous instruction has just left in a
61
+ # register. See slot_residency.rb for why "nothing has been emitted since"
62
+ # is a sufficient safety condition, and #emit_instruction's :label case
63
+ # for the one state change it cannot see.
64
+ include SlotResidency
65
+
50
66
  # Result of compiling one function: `bytes` is the machine code (an
51
67
  # ASCII-8BIT String), `symbols` is an array of
52
68
  # { name:, offset:, size: } describing the emitted function symbols, and
@@ -90,6 +106,32 @@ module Rubycc
90
106
  # post-alloca rsp as the block's base address.
91
107
  RSP = 4
92
108
 
109
+ # The registers whole-function promotion hands out, in the order it hands
110
+ # them out (see IR::Promotion and #promotion_assignment). All five are
111
+ # callee-saved under System V AMD64 (psABI 3.2.1: rbx, rbp and r12..r15
112
+ # are preserved across a call), which is what lets a promoted value stay
113
+ # put across one — and none of them is used for anything else here, the
114
+ # scratch, argument and return registers all being caller-saved. rbp is
115
+ # excluded, being the frame pointer every slot is addressed from.
116
+ #
117
+ # rbx is register 3 and needs no REX extension; r12..r15 have their high
118
+ # bit carried by REX.R when they land in a ModR/M reg field, by REX.B when
119
+ # they land in an rm field (or a SIB base, or an opcode's low three bits)
120
+ # and by REX.X in a SIB index — every one of which they do land in, since
121
+ # a promoted value is named where it lives rather than moved to a scratch
122
+ # register first. #emit_rex is where all four bits are decided.
123
+ #
124
+ # None of these is a scratch, argument or return register, so no residency
125
+ # the SlotResidency table keeps is ever keyed by one; that is what lets an
126
+ # instruction writing a promoted register leave the table standing (see
127
+ # SlotResidency#note_register_clobbered).
128
+ RBX = 3
129
+ R12 = 12
130
+ R13 = 13
131
+ R14 = 14
132
+ R15 = 15
133
+ PROMOTION_REGISTERS = [RBX, R12, R13, R14, R15].freeze
134
+
93
135
  # The two vector (xmm) scratch registers the floating ops use. Their
94
136
  # numbers 0/1 double as the ModR/M reg/rm fields, so no REX.R is ever
95
137
  # needed to name them. Every floating value round-trips through a GP stack
@@ -108,6 +150,11 @@ module Rubycc
108
150
  GP_RETURN_REGISTERS = [EAX, EDX].freeze
109
151
  SSE_RETURN_REGISTERS = [XMM0, XMM1].freeze
110
152
 
153
+ # :scaled_add's element size -> the SIB byte's two-bit scale field. The
154
+ # four sizes are the only ones the encoding can name, which is exactly the
155
+ # set IR::Simplify fuses a subscript for.
156
+ SIB_SCALES = { 1 => 0, 2 => 1, 4 => 2, 8 => 3 }.freeze
157
+
111
158
  # IR comparison op -> setcc opcode (second byte of the 0F 9x encoding).
112
159
  # The result is materialized into eax as an int 0/1 by movzx. The signed
113
160
  # forms (setl/setle/setg/setge) test the sign/overflow flags; the unsigned
@@ -126,8 +173,28 @@ module Rubycc
126
173
  uge: 0x93 # setae (above or equal, unsigned >=)
127
174
  }.freeze
128
175
 
129
- def compile(ir_func)
176
+ # `analysis` is the census of `ir_func`'s instruction list (IR::Analysis).
177
+ # The compiler passes the one IR::Simplify already took on its way
178
+ # through; a caller that hands over a function directly gets it taken
179
+ # here.
180
+ def compile(ir_func, analysis = IR::Analysis.of(ir_func))
130
181
  @code = +"".b
182
+ reset_slot_residency
183
+ # Slots this function never has to write: an expression temporary whose
184
+ # one reader is the instruction right behind its producer stays in the
185
+ # register it was computed in (see IR::Simplify#transient_flags and
186
+ # #store_reg). The answer is a property of the instruction list, so it
187
+ # is taken once here rather than rediscovered per instruction, and it
188
+ # arrives as an array indexed by vreg number — the numbers are dense and
189
+ # small, and this is asked on every store the backend emits.
190
+ @transient = analysis.transient
191
+ # Slots this function does not have at all: a promoted value lives in
192
+ # one callee-saved register from the prologue to every ret, so its slot
193
+ # is never read, written or named (see #promotion_assignment, #load_reg
194
+ # and #store_reg). Like @transient this is a property of the instruction
195
+ # list, decided once here, and indexed by vreg number for the same
196
+ # reason.
197
+ @promoted = promotion_assignment(ir_func, analysis)
131
198
  # Control-flow bookkeeping: `@labels` maps a label id to its resolved
132
199
  # code offset; `@fixups` collects [patch_offset, label_id] pairs whose
133
200
  # rel32 field is overwritten once every label offset is known.
@@ -154,12 +221,31 @@ module Rubycc
154
221
 
155
222
  private
156
223
 
224
+ # Binds the best promotion candidates to PROMOTION_REGISTERS in order,
225
+ # returning the vreg -> register table the whole backend consults (an
226
+ # array; a vreg that owns no register indexes nil). Taking the first few
227
+ # of an ordered list is the entire allocation: one register each, held for
228
+ # the function's length, so there is no interference to resolve and
229
+ # nothing to undo when the registers run out — the candidates past the
230
+ # fifth simply keep their slots.
231
+ #
232
+ # @promoted_registers is the same binding in assignment order, which is
233
+ # the order the save slots are laid out in (#emit_prologue).
234
+ def promotion_assignment(ir_func, analysis)
235
+ vregs = IR::Promotion.candidates(ir_func, analysis).first(PROMOTION_REGISTERS.size)
236
+ @promoted_registers = PROMOTION_REGISTERS.first(vregs.size)
237
+ promoted = Array.new(ir_func.vreg_count)
238
+ vregs.each_with_index { |vreg, index| promoted[vreg] = PROMOTION_REGISTERS[index] }
239
+ promoted
240
+ end
241
+
157
242
  # Frame layout, from rbp downward: first the virtual-register slots
158
243
  # (8 bytes each, rounded up to a 16-byte region), then the stack objects,
159
- # and last for a variadic function a 176-byte register-save area below
160
- # everything else. Each object is placed at a 16-byte-aligned size below
161
- # the previous one, and @object_offsets[id] records the rbp-relative
162
- # displacement of the object's base (its lowest address, i.e. element 0).
244
+ # then one 8-byte save slot per promoted register, and last for a
245
+ # variadic function a 176-byte register-save area below everything else.
246
+ # Each object is placed at a 16-byte-aligned size below the previous one,
247
+ # and @object_offsets[id] records the rbp-relative displacement of the
248
+ # object's base (its lowest address, i.e. element 0).
163
249
  def emit_prologue(vreg_count, param_count, param_kinds, stack_objects, variadic)
164
250
  vreg_region = align16(vreg_count * 8)
165
251
  @object_offsets = []
@@ -168,6 +254,17 @@ module Rubycc
168
254
  running += align16(object_size)
169
255
  @object_offsets << -running
170
256
  end
257
+ # One save slot per promoted register. The registers are callee-saved,
258
+ # so a function that uses one has to give it back exactly as it found
259
+ # it; saving them into the frame with mov rather than with push keeps
260
+ # rsp's 16-byte alignment — which every call depends on — a property of
261
+ # the single `sub` below instead of the parity of the register count.
262
+ # They are laid out in assignment order, and their number is a function
263
+ # of the instruction list, so the frame stays deterministic (N4).
264
+ @promoted_saves = @promoted_registers.map do |reg|
265
+ running += 8
266
+ [reg, -running]
267
+ end
171
268
  # A variadic function reserves a 176-byte register-save area at the very
172
269
  # bottom of the frame; :va_start points reg_save_area here and the
173
270
  # prologue spills the six integer argument registers (48 bytes) followed
@@ -184,6 +281,10 @@ module Rubycc
184
281
  emit(0x48, 0x89, 0xE5) # mov rbp, rsp
185
282
  emit(0x48, 0x81, 0xEC) # sub rsp, imm32
186
283
  emit_bytes([frame_size].pack("L<"))
284
+ # Before anything writes a promoted register — which the parameter
285
+ # spilling right below is the first thing to do, a promoted parameter
286
+ # being moved straight from its incoming argument register.
287
+ emit_save_promoted_registers
187
288
  spill_parameters(param_kinds)
188
289
  if variadic
189
290
  emit_save_gp_registers
@@ -191,6 +292,31 @@ module Rubycc
191
292
  end
192
293
  end
193
294
 
295
+ # Saves the promoted registers into their frame slots, "mov [rbp+disp],
296
+ # r64" apiece. REX.W widens the move and REX.R extends r12..r15, whose low
297
+ # three bits go into the ModR/M reg field; the rm field is rbp's, so no SIB
298
+ # byte is involved on either side.
299
+ def emit_save_promoted_registers
300
+ @promoted_saves.each do |reg, disp|
301
+ emit(0x48 | (reg >= 8 ? 0x04 : 0)) # REX.W (+ REX.R for r12..r15)
302
+ emit(0x89) # mov [rbp + disp], r64
303
+ emit_modrm_rbp_disp(reg & 7, disp)
304
+ end
305
+ end
306
+
307
+ # Puts the caller's values back, the exact inverse of
308
+ # #emit_save_promoted_registers (8B reads memory into the register). Every
309
+ # :ret emits this immediately before its "leave", and a :ret is the only
310
+ # way out of a function, so no path returns with a callee-saved register
311
+ # holding this function's value.
312
+ def emit_restore_promoted_registers
313
+ @promoted_saves.each do |reg, disp|
314
+ emit(0x48 | (reg >= 8 ? 0x04 : 0)) # REX.W (+ REX.R for r12..r15)
315
+ emit(0x8B) # mov r64, [rbp + disp]
316
+ emit_modrm_rbp_disp(reg & 7, disp)
317
+ end
318
+ end
319
+
194
320
  # Brings each incoming argument into its parameter slot (the first
195
321
  # `param_count` vregs, one per param_kinds entry) so it reads back like any
196
322
  # other vreg. The generator has already fixed where each parameter arrives:
@@ -269,11 +395,21 @@ module Rubycc
269
395
  load_reg(EAX, inst.a)
270
396
  store_reg(EAX, inst.dst)
271
397
  when :add
272
- emit_binary(inst.dst, inst.a, inst.b, [0x01, 0xC8], inst.size) # add eax, ecx
398
+ # 03 /r is "add r32, r/m32" the same addition as 01 /r's "add
399
+ # r/m32, r32" with the operands the other way round, which is what
400
+ # lets the second one be a slot. Every entry below pairs the two
401
+ # directions the same way (the group's low opcode plus two).
402
+ emit_binary(inst.dst, inst.a, inst.b, [0x01, 0xC8], inst.size,
403
+ memory_bytes: [0x03], commutative: true)
404
+ when :scaled_add
405
+ emit_scaled_add(inst.dst, inst.a, inst.b, inst.size)
273
406
  when :sub
274
- emit_binary(inst.dst, inst.a, inst.b, [0x29, 0xC8], inst.size) # sub eax, ecx
407
+ emit_binary(inst.dst, inst.a, inst.b, [0x29, 0xC8], inst.size, memory_bytes: [0x2B])
275
408
  when :mul
276
- emit_binary(inst.dst, inst.a, inst.b, [0x0F, 0xAF, 0xC1], inst.size) # imul eax, ecx
409
+ # imul (0F AF /r) is already a "r32, r/m32" form, so its register and
410
+ # memory encodings share the same opcode.
411
+ emit_binary(inst.dst, inst.a, inst.b, [0x0F, 0xAF, 0xC1], inst.size,
412
+ memory_bytes: [0x0F, 0xAF], commutative: true)
277
413
  when :mulhi
278
414
  emit_mulhi(inst.dst, inst.a, inst.b) # high 64 bits of an unsigned 64x64 product
279
415
  when :div
@@ -285,11 +421,14 @@ module Rubycc
285
421
  when :umod
286
422
  emit_udivmod(inst.dst, inst.a, inst.b, EDX, inst.size) # remainder in edx
287
423
  when :and
288
- emit_binary(inst.dst, inst.a, inst.b, [0x21, 0xC8], inst.size) # and eax, ecx
424
+ emit_binary(inst.dst, inst.a, inst.b, [0x21, 0xC8], inst.size,
425
+ memory_bytes: [0x23], commutative: true)
289
426
  when :or
290
- emit_binary(inst.dst, inst.a, inst.b, [0x09, 0xC8], inst.size) # or eax, ecx
427
+ emit_binary(inst.dst, inst.a, inst.b, [0x09, 0xC8], inst.size,
428
+ memory_bytes: [0x0B], commutative: true)
291
429
  when :xor
292
- emit_binary(inst.dst, inst.a, inst.b, [0x31, 0xC8], inst.size) # xor eax, ecx
430
+ emit_binary(inst.dst, inst.a, inst.b, [0x31, 0xC8], inst.size,
431
+ memory_bytes: [0x33], commutative: true)
293
432
  when :shl
294
433
  # shl eax, cl (D3 /4): the count comes from cl, which #emit_binary
295
434
  # loads into ecx alongside the value in eax. A size-8 operand takes a
@@ -306,7 +445,8 @@ module Rubycc
306
445
  # unsigned counterpart of :sar.
307
446
  emit_binary(inst.dst, inst.a, inst.b, [0xD3, 0xE8], inst.size)
308
447
  when :eq, :ne, :lt, :le, :gt, :ge, :ult, :ule, :ugt, :uge
309
- emit_comparison(inst.dst, inst.a, inst.b, SETCC_OPCODES.fetch(inst.op), inst.size)
448
+ emit_comparison(inst.dst, inst.a, inst.b, SETCC_OPCODES.fetch(inst.op), inst.size,
449
+ commutative: inst.op == :eq || inst.op == :ne)
310
450
  when :fadd
311
451
  emit_float_binary(inst.dst, inst.a, inst.b, inst.size, 0x58) # addss/addsd
312
452
  when :fsub
@@ -339,6 +479,11 @@ module Rubycc
339
479
  when :got_addr
340
480
  emit_got_addr(inst.dst, inst.a)
341
481
  when :label
482
+ # The one place a register's meaning changes without an instruction
483
+ # being emitted: control may arrive here from a branch whose registers
484
+ # hold something else entirely, so nothing may be assumed resident
485
+ # past a label (see SlotResidency).
486
+ forget_slot_residency
342
487
  @labels[inst.a] = @code.bytesize
343
488
  when :jump
344
489
  emit_jump(inst.a)
@@ -368,6 +513,8 @@ module Rubycc
368
513
  emit_alloca(inst.dst, inst.a)
369
514
  when :bit_scan
370
515
  emit_bit_scan(inst.dst, inst.a, inst.b, inst.size)
516
+ when :popcount
517
+ emit_popcount(inst.dst, inst.a, inst.size)
371
518
  when :atomic_load
372
519
  emit_atomic_load(inst.dst, inst.a, inst.size)
373
520
  when :atomic_store
@@ -591,6 +738,9 @@ module Rubycc
591
738
  else
592
739
  load_reg(EAX, value_vreg)
593
740
  end
741
+ # After the value is loaded, since it may itself come out of a promoted
742
+ # register, and before "leave" while rbp still addresses the frame.
743
+ emit_restore_promoted_registers
594
744
  emit(0xC9) # leave
595
745
  emit(0xC3) # ret
596
746
  end
@@ -683,39 +833,53 @@ module Rubycc
683
833
  end
684
834
 
685
835
  # :sext — sign-extend a's low `size` bytes to the full 64-bit register.
686
- # size 4 is a movsxd rax, eax (the classic int -> long widening, so
687
- # pointer-offset scaling sees a correct, possibly negative index); size 2
688
- # a movsx rax, ax and size 1 a movsx rax, al, which re-derive a signed
689
- # short/char value from just its stored low bytes. The 64-bit store writes
690
- # the widened value back.
836
+ # size 4 is a movsxd (the classic int -> long widening, so pointer-offset
837
+ # scaling sees a correct, possibly negative index); size 2 a movsx r64,
838
+ # r/m16 and size 1 a movsx r64, r/m8, which re-derive a signed
839
+ # short/char value from just its stored low bytes.
840
+ #
841
+ # Both halves of the instruction are free of a fixed register: the source
842
+ # is an r/m field, so a promoted operand is read in place, and the
843
+ # destination a reg field, so a promoted result is written in place
844
+ # (#widen_in_registers).
691
845
  def emit_sext(dst, src_vreg, size)
692
- load_reg(EAX, src_vreg) # rax = value
693
846
  case size
694
- when 1
695
- emit(0x48, 0x0F, 0xBE, 0xC0) # REX.W movsx rax, al
696
- when 2
697
- emit(0x48, 0x0F, 0xBF, 0xC0) # REX.W movsx rax, ax
698
- else # 4
699
- emit(0x48, 0x63, 0xC0) # REX.W movsxd rax, eax
847
+ when 1 then widen_in_registers(dst, src_vreg, [0x0F, 0xBE], rex_w: true) # movsx r64, r/m8
848
+ when 2 then widen_in_registers(dst, src_vreg, [0x0F, 0xBF], rex_w: true) # movsx r64, r/m16
849
+ else widen_in_registers(dst, src_vreg, [0x63], rex_w: true) # movsxd r64, r/m32
700
850
  end
701
- store_reg(EAX, dst)
702
851
  end
703
852
 
704
853
  # :zext — zero-extend a's low `size` bytes to the full 64-bit register.
705
- # size 1/2 are a movzx eax, al / movzx eax, ax; size 4 a plain mov eax,
706
- # eax. Each writes eax, which x86-64 defines to clear the upper 32 bits of
707
- # rax, so all three leave a clean 64-bit zero-extended value.
854
+ # size 1/2 are a movzx r32, r/m8 / movzx r32, r/m16; size 4 a plain 32-bit
855
+ # mov. Each writes a 32-bit register, which x86-64 defines to clear the
856
+ # upper 32 bits of its 64-bit whole, so all three leave a clean
857
+ # zero-extended value.
708
858
  def emit_zext(dst, src_vreg, size)
709
- load_reg(EAX, src_vreg) # rax = value
710
859
  case size
711
- when 1
712
- emit(0x0F, 0xB6, 0xC0) # movzx eax, al
713
- when 2
714
- emit(0x0F, 0xB7, 0xC0) # movzx eax, ax
715
- else # 4
716
- emit(0x89, 0xC0) # mov eax, eax
860
+ when 1 then widen_in_registers(dst, src_vreg, [0x0F, 0xB6]) # movzx r32, r/m8
861
+ when 2 then widen_in_registers(dst, src_vreg, [0x0F, 0xB7]) # movzx r32, r/m16
862
+ else widen_in_registers(dst, src_vreg, [0x8B]) # mov r32, r/m32
717
863
  end
718
- store_reg(EAX, dst)
864
+ end
865
+
866
+ # The shared shape of :sext and :zext: one "reg, r/m" instruction from
867
+ # wherever the source lives to wherever the destination lives. A promoted
868
+ # source is the r/m operand outright; any other source goes through eax
869
+ # first, as before, since a slot holds eight bytes and these opcodes'
870
+ # 1/2-byte forms would read the wrong count of them. A promoted
871
+ # destination is the reg field, so no move follows either.
872
+ def widen_in_registers(dst, src_vreg, opcode_bytes, rex_w: false)
873
+ refresh_slot_residency
874
+ source = @promoted[src_vreg]
875
+ unless source
876
+ load_reg(EAX, src_vreg) # rax = value
877
+ source = EAX
878
+ end
879
+ target = result_register(dst)
880
+ emit_register_rm(opcode_bytes, source, reg: target, rex_w: rex_w)
881
+ # One "reg, r/m" instruction: its reg field is the only thing written.
882
+ store_result(target, dst, only_wrote: target)
719
883
  end
720
884
 
721
885
  # :bit_scan — count the zero bits of a's value (__builtin_ctz/clz). The
@@ -740,6 +904,141 @@ module Rubycc
740
904
  store_reg(EAX, dst)
741
905
  end
742
906
 
907
+ # The bit-field patterns :popcount folds over, in their 8-byte form; a
908
+ # 4-byte count uses the low half of each. The first three keep the partial
909
+ # counts of one width from spilling into their neighbours, and the last is
910
+ # the one-per-byte multiplier that sums the eight byte counts at once.
911
+ POPCOUNT_PAIR_MASK = 0x5555_5555_5555_5555
912
+ POPCOUNT_NIBBLE_MASK = 0x3333_3333_3333_3333
913
+ POPCOUNT_BYTE_MASK = 0x0F0F_0F0F_0F0F_0F0F
914
+ POPCOUNT_BYTE_ONES = 0x0101_0101_0101_0101
915
+
916
+ # :popcount — how many bits of a's value are set (__builtin_popcount and
917
+ # its "l"/"ll" forms). x86-64 does have an instruction for exactly this,
918
+ # `popcnt`, but it arrived with SSE4.2 and is not part of the baseline
919
+ # architecture rubycc emits for: using it would make the output fault on
920
+ # an older CPU, and make it depend on the CPU that happened to build it.
921
+ # The count is expanded instead, in the same shape the aarch64 backend
922
+ # uses (whose `cnt` is an extension too — an AdvSIMD one, reached only
923
+ # through a vector register).
924
+ #
925
+ # The expansion is a divide-and-conquer sum over the register's own bits
926
+ # ("SWAR"): a register is read as many independent counts side by side,
927
+ # which are added pairwise until one of them spans it. Start from 2-bit
928
+ # fields, where the count is already there to be read — a field holding
929
+ # hi:lo has hi + lo bits set — and each step halves the number of fields
930
+ # while doubling their width: 32 counts become 16, then 8, 4, 2 and 1 in a
931
+ # 64-bit register, half that in a 32-bit one. What every step needs is a
932
+ # shift to bring one field's partner onto it, an add, and enough masking
933
+ # that no field's sum reaches its neighbour. Three steps are written out
934
+ # below and the remaining ones — three of them at 64 bits, two at 32 —
935
+ # are what the closing multiply performs in a single instruction:
936
+ #
937
+ # pairs x -= (x >> 1) & 0x5555... each 2-bit field v = 2*hi + lo
938
+ # becomes v - hi = hi + lo. The
939
+ # subtraction never borrows across
940
+ # a field (the result is at most
941
+ # the field's own value), so the
942
+ # one mask on the shift is all it
943
+ # takes
944
+ # nibbles x = (x & 0x3333...) + ((x >> 2) & 0x3333...)
945
+ # two counts of at most 2 sum to 4,
946
+ # which no longer fits a 2-bit
947
+ # field: both sides are masked
948
+ # before adding, into the 4-bit
949
+ # fields that do hold it
950
+ # bytes x = (x + (x >> 4)) & 0x0F0F...
951
+ # two counts of at most 4 sum to 8,
952
+ # which still fits a nibble, so the
953
+ # add can run unmasked and one mask
954
+ # afterwards clears the odd nibbles
955
+ # it dirtied
956
+ # total (x * 0x0101...) >> (bits - 8)
957
+ # every byte now holds its own
958
+ # count. Multiplying by one-per-byte
959
+ # adds each byte into every byte
960
+ # above it, so the top byte receives
961
+ # all of them; the column sums are
962
+ # at most 64 and never carry out of
963
+ # a byte, and the shift brings that
964
+ # top byte down
965
+ #
966
+ # rcx carries the running value, rax the copy each stage shifts and adds
967
+ # back in (and, from the third stage on, the result), and rdx a mask —
968
+ # which only the 8-byte form needs, x86-64 having no 64-bit immediate for
969
+ # a logical op. The 4-byte form is the same sequence in 32-bit registers,
970
+ # whose writes zero the upper half, so the indeterminate high bits of a
971
+ # slot that was moved 64 bits at a time never enter the count.
972
+ def emit_popcount(dst, src_vreg, size)
973
+ load_reg(ECX, src_vreg) # rcx = value to count
974
+ emit_popcount_reg(0x89, EAX, ECX, size) # mov rax, rcx
975
+ emit_popcount_shr(EAX, 1, size) # rax = x >> 1
976
+ emit_popcount_mask([EAX], POPCOUNT_PAIR_MASK, size)
977
+ emit_popcount_reg(0x29, ECX, EAX, size) # sub rcx, rax (pair counts)
978
+ emit_popcount_reg(0x89, EAX, ECX, size) # mov rax, rcx
979
+ emit_popcount_shr(ECX, 2, size) # rcx = x >> 2
980
+ emit_popcount_mask([EAX, ECX], POPCOUNT_NIBBLE_MASK, size)
981
+ emit_popcount_reg(0x01, ECX, EAX, size) # add rcx, rax (nibble counts)
982
+ emit_popcount_reg(0x89, EAX, ECX, size) # mov rax, rcx
983
+ emit_popcount_shr(EAX, 4, size) # rax = x >> 4
984
+ emit_popcount_reg(0x01, EAX, ECX, size) # add rax, rcx
985
+ emit_popcount_mask([EAX], POPCOUNT_BYTE_MASK, size) # byte counts
986
+ emit_popcount_byte_sum(size) # rax = sum of the bytes
987
+ store_reg(EAX, dst)
988
+ end
989
+
990
+ # One two-register instruction of the expansion, in the "r/m, reg"
991
+ # direction: `opcode` applies `reg` to `rm`. An 8-byte count takes a REX.W
992
+ # prefix and a 4-byte one no prefix at all — every register here is one of
993
+ # rax/rcx/rdx, so no REX bit is needed to name them.
994
+ def emit_popcount_reg(opcode, rm, reg, size)
995
+ emit(0x48) if size == 8 # REX.W: the 64-bit form
996
+ emit(opcode, 0xC0 | (reg << 3) | rm)
997
+ end
998
+
999
+ # `shr rm, count` (C1 /5 ib) at the count's width.
1000
+ def emit_popcount_shr(rm, count, size)
1001
+ emit(0x48) if size == 8 # REX.W: a 64-bit shift
1002
+ emit(0xC1, 0xE8 | rm, count)
1003
+ end
1004
+
1005
+ # Masks each of `regs` with one of the expansion's field patterns. A
1006
+ # 4-byte count names it as an immediate ("and r/m32, imm32", 81 /4 id); an
1007
+ # 8-byte one cannot, x86-64's logical ops taking at most a sign-extended
1008
+ # imm32, so the mask is materialized in rdx once (movabs) and applied from
1009
+ # there ("and r/m64, r64", 21 /r) — which is why the registers to mask
1010
+ # arrive together rather than one call at a time: the nibble stage masks
1011
+ # two of them with the same pattern.
1012
+ def emit_popcount_mask(regs, mask, size)
1013
+ if size == 8
1014
+ emit(0x48, 0xBA) # movabs rdx, imm64
1015
+ emit_bytes([mask].pack("Q<"))
1016
+ regs.each { |reg| emit_popcount_reg(0x21, reg, EDX, size) } # and reg, rdx
1017
+ else
1018
+ regs.each do |reg|
1019
+ emit(0x81, 0xE0 | reg) # and r/m32, imm32
1020
+ emit_bytes([mask & 0xFFFFFFFF].pack("L<"))
1021
+ end
1022
+ end
1023
+ end
1024
+
1025
+ # The expansion's last stage: rax holds one count per byte, and the
1026
+ # multiply by one-per-byte gathers them into the top byte, which the shift
1027
+ # brings down. The 4-byte form takes its multiplier as an immediate
1028
+ # ("imul r32, r/m32, imm32", 69 /r id); the 8-byte one has no imm64 form
1029
+ # either, so the multiplier goes through rdx ("imul r64, r/m64", 0F AF /r).
1030
+ def emit_popcount_byte_sum(size)
1031
+ if size == 8
1032
+ emit(0x48, 0xBA) # movabs rdx, 0x0101010101010101
1033
+ emit_bytes([POPCOUNT_BYTE_ONES].pack("Q<"))
1034
+ emit(0x48, 0x0F, 0xAF, 0xC2) # imul rax, rdx
1035
+ else
1036
+ emit(0x69, 0xC0) # imul eax, eax, imm32
1037
+ emit_bytes([POPCOUNT_BYTE_ONES & 0xFFFFFFFF].pack("L<"))
1038
+ end
1039
+ emit_popcount_shr(EAX, size * 8 - 8, size) # rax = the top byte
1040
+ end
1041
+
743
1042
  # --- atomics -----------------------------------------------------------
744
1043
  #
745
1044
  # The four atomic ops all lower at sequential consistency, the strongest
@@ -782,8 +1081,7 @@ module Rubycc
782
1081
  # implicitly locked, is also the full barrier a seq_cst store needs; a mov
783
1082
  # followed by an mfence would be equivalent and longer.
784
1083
  def emit_atomic_store(ptr_vreg, value_vreg, size)
785
- load_reg(EAX, ptr_vreg) # rax = destination address
786
- load_reg(ECX, value_vreg) # rcx = value
1084
+ load_binary_operands(ptr_vreg, value_vreg) # rax = destination address, rcx = value
787
1085
  emit(0x48) if size == 8 # REX.W
788
1086
  emit(0x87, 0x08) # xchg [rax], ecx/rcx
789
1087
  end
@@ -805,8 +1103,7 @@ module Rubycc
805
1103
  def emit_atomic_rmw(dst, ptr_vreg, value_vreg, kind, size)
806
1104
  return emit_atomic_or_fetch(dst, ptr_vreg, value_vreg, size) if kind == :or_fetch
807
1105
 
808
- load_reg(EAX, ptr_vreg) # rax = address
809
- load_reg(ECX, value_vreg) # rcx = operand
1106
+ load_binary_operands(ptr_vreg, value_vreg) # rax = address, rcx = operand
810
1107
  negate = kind == :fetch_sub || kind == :sub_fetch
811
1108
  keep = kind == :add_fetch || kind == :sub_fetch
812
1109
  if negate
@@ -906,24 +1203,21 @@ module Rubycc
906
1203
  store_reg(EAX, dst)
907
1204
  end
908
1205
 
909
- # "*p" read, sign-extending: load the pointer from its slot into rax, then
910
- # read through it. An 8-byte load moves a full pointer/long (mov rax,
911
- # [rax]); a 4-byte load reads an int (mov eax, [rax]), whose upper bits the
912
- # write to eax zeroes; a 2/1-byte load reads a short/char and sign-extends
913
- # it to the register (movsx), so the slot holds a promoted signed value.
1206
+ # "*p" read, sign-extending: load the pointer into rax, then read through
1207
+ # it. An 8-byte load moves a full pointer/long (mov r64, [rax]); a 4-byte
1208
+ # load reads an int (mov r32, [rax]), whose upper bits the 32-bit write
1209
+ # zeroes; a 2/1-byte load reads a short/char and sign-extends it to the
1210
+ # register (movsx), so the slot holds a promoted signed value.
1211
+ #
1212
+ # The destination is a reg field in every one of the four, so a promoted
1213
+ # one is written directly (#emit_deref).
914
1214
  def emit_load(dst, ptr_vreg, size)
915
- load_reg(EAX, ptr_vreg) # rax = pointer value
916
1215
  case size
917
- when 8
918
- emit(0x48, 0x8B, 0x00) # mov rax, [rax]
919
- when 2
920
- emit(0x0F, 0xBF, 0x00) # movsx eax, word [rax]
921
- when 1
922
- emit(0x0F, 0xBE, 0x00) # movsx eax, byte [rax]
923
- else # 4
924
- emit(0x8B, 0x00) # mov eax, [rax]
1216
+ when 8 then emit_deref(dst, ptr_vreg, [0x8B], rex_w: true) # mov r64, [rax]
1217
+ when 2 then emit_deref(dst, ptr_vreg, [0x0F, 0xBF]) # movsx r32, word [rax]
1218
+ when 1 then emit_deref(dst, ptr_vreg, [0x0F, 0xBE]) # movsx r32, byte [rax]
1219
+ else emit_deref(dst, ptr_vreg, [0x8B]) # mov r32, [rax]
925
1220
  end
926
- store_reg(EAX, dst)
927
1221
  end
928
1222
 
929
1223
  # "*p" read, zero-extending: the unsigned counterpart of #emit_load for an
@@ -931,18 +1225,28 @@ module Rubycc
931
1225
  # forms are identical to a signed load (a plain mov already zero-extends a
932
1226
  # 32-bit read, and an 8-byte value has no spare bits).
933
1227
  def emit_uload(dst, ptr_vreg, size)
934
- load_reg(EAX, ptr_vreg) # rax = pointer value
935
1228
  case size
936
- when 8
937
- emit(0x48, 0x8B, 0x00) # mov rax, [rax]
938
- when 2
939
- emit(0x0F, 0xB7, 0x00) # movzx eax, word [rax]
940
- when 1
941
- emit(0x0F, 0xB6, 0x00) # movzx eax, byte [rax]
942
- else # 4
943
- emit(0x8B, 0x00) # mov eax, [rax]
1229
+ when 8 then emit_deref(dst, ptr_vreg, [0x8B], rex_w: true) # mov r64, [rax]
1230
+ when 2 then emit_deref(dst, ptr_vreg, [0x0F, 0xB7]) # movzx r32, word [rax]
1231
+ when 1 then emit_deref(dst, ptr_vreg, [0x0F, 0xB6]) # movzx r32, byte [rax]
1232
+ else emit_deref(dst, ptr_vreg, [0x8B]) # mov r32, [rax]
944
1233
  end
945
- store_reg(EAX, dst)
1234
+ end
1235
+
1236
+ # The shared shape of :load and :uload: the pointer into rax and one read
1237
+ # through [rax] into wherever the destination lives. The ModR/M is mod =
1238
+ # 00 with rm = 000, the plain "[rax]" form — no SIB byte and no
1239
+ # displacement — so only the reg field varies, and REX.R is all a promoted
1240
+ # destination costs.
1241
+ def emit_deref(dst, ptr_vreg, opcode_bytes, rex_w: false)
1242
+ load_reg(EAX, ptr_vreg) # rax = pointer value
1243
+ target = result_register(dst)
1244
+ emit_rex(rex_w: rex_w, reg: target)
1245
+ opcode_bytes.each { |byte| emit(byte) }
1246
+ emit((target & 7) << 3) # mod=00, rm=000: [rax]
1247
+ # The read through [rax] writes its reg field and nothing else; rax
1248
+ # itself was written by the load above, which accounted for itself.
1249
+ store_result(target, dst, only_wrote: target)
946
1250
  end
947
1251
 
948
1252
  # "*p = v": rax holds the destination address, rcx the value, then rcx is
@@ -952,8 +1256,7 @@ module Rubycc
952
1256
  # a 1-byte store writes just the low byte (mov [rax], cl). The narrower
953
1257
  # writes are exactly the truncation a narrow lvalue needs.
954
1258
  def emit_store(ptr_vreg, value_vreg, size)
955
- load_reg(EAX, ptr_vreg) # rax = destination address
956
- load_reg(ECX, value_vreg) # rcx = value
1259
+ load_binary_operands(ptr_vreg, value_vreg) # rax = destination address, rcx = value
957
1260
  case size
958
1261
  when 8
959
1262
  emit(0x48, 0x89, 0x08) # mov [rax], rcx
@@ -1038,33 +1341,83 @@ module Rubycc
1038
1341
  store_reg(RSP, dst) # dst = rsp (block base address)
1039
1342
  end
1040
1343
 
1041
- # A size of 8 compares full 64-bit pointer values (REX.W cmp rax, rcx);
1042
- # otherwise the 32-bit int compare is used. The signed setcc still suits
1043
- # pointer ordering here, since stack addresses stay within the positive
1044
- # half of the 64-bit range.
1045
- def emit_comparison(dst, a, b, setcc_opcode, size = nil)
1046
- load_reg(EAX, a)
1047
- load_reg(ECX, b)
1048
- emit(0x48) if size == 8 # REX.W widens the following cmp
1049
- emit(0x39, 0xC8) # cmp eax, ecx (rax, rcx when REX.W)
1344
+ # A size of 8 compares full 64-bit pointer values (REX.W); otherwise the
1345
+ # 32-bit int compare is used. The signed setcc still suits pointer
1346
+ # ordering here, since stack addresses stay within the positive half of
1347
+ # the 64-bit range. The second operand is named where it lives (3B /r,
1348
+ # "cmp r32, r/m32") wherever it can be, as in #emit_binary.
1349
+ #
1350
+ # `cmp` reads both of its operands and writes neither, which the first one
1351
+ # takes advantage of too: a promoted `a` is named in the reg field
1352
+ # directly rather than moved into eax to be looked at. The result still
1353
+ # goes through eax, `setcc` writing al and nothing else — one of the fixed
1354
+ # registers this file does not try to talk out of its choice.
1355
+ #
1356
+ # An equality test is the one comparison whose operands may be exchanged
1357
+ # without changing its setcc: "a == b" and "b == a" leave the same ZF,
1358
+ # while every ordering test would need its condition mirrored as well.
1359
+ def emit_comparison(dst, a, b, setcc_opcode, size = nil, commutative: false)
1360
+ refresh_slot_residency
1361
+ a, b = b, a if commutative && prefer_swapped_operands?(a, b)
1362
+ if rm_operand?(b)
1363
+ left = @promoted[a]
1364
+ unless left
1365
+ load_reg(EAX, a)
1366
+ left = EAX
1367
+ end
1368
+ emit_vreg_rm([0x3B], b, reg: left, rex_w: size == 8) # cmp r32, r/m32
1369
+ else
1370
+ load_binary_operands(a, b, commutative: commutative)
1371
+ emit(0x48) if size == 8 # REX.W widens the following cmp
1372
+ emit(0x39, 0xC8) # cmp eax, ecx (rax, rcx when REX.W)
1373
+ end
1050
1374
  emit(0x0F, setcc_opcode, 0xC0) # setcc al
1051
1375
  emit(0x0F, 0xB6, 0xC0) # movzx eax, al
1052
1376
  store_reg(EAX, dst)
1053
1377
  end
1054
1378
 
1055
- # A floating binary op (:fadd/:fsub/:fmul/:fdiv). The operands are loaded
1056
- # into xmm0/xmm1 from their slots, combined in place, and stored back. The
1057
- # mandatory prefix selects the scalar-single (F3, size 4) or scalar-double
1058
- # (F2, size 8) form of the shared 0F <opcode> encoding.
1379
+ # A floating binary op (:fadd/:fsub/:fmul/:fdiv). The first operand is
1380
+ # loaded into xmm0, the second read straight out of its slot, and the
1381
+ # result stored back. The mandatory prefix selects the scalar-single (F3,
1382
+ # size 4) or scalar-double (F2, size 8) form of the shared 0F <opcode>
1383
+ # encoding, and all four take an "xmm, xmm/m" operand pair — so the memory
1384
+ # form is the same instruction with a different ModR/M, one shorter than
1385
+ # staging the operand through xmm1 would be.
1386
+ #
1387
+ # The operands are never exchanged the way a commutative integer op's are:
1388
+ # SSE arithmetic takes a NaN result's payload from a particular source
1389
+ # operand, so the two orders are not interchangeable even where the
1390
+ # arithmetic itself is.
1059
1391
  def emit_float_binary(dst, a, b, size, opcode)
1060
- load_xmm(XMM0, a, size)
1061
- load_xmm(XMM1, b, size)
1392
+ load_float_operands(a, b, size)
1062
1393
  emit(size == 8 ? 0xF2 : 0xF3)
1063
1394
  emit(0x0F, opcode)
1064
- emit(modrm_reg(XMM0, XMM1)) # op xmm0, xmm1
1395
+ emit_float_rm(b)
1065
1396
  store_xmm(XMM0, dst, size)
1066
1397
  end
1067
1398
 
1399
+ # Stages a floating instruction's operands: the first into xmm0, and the
1400
+ # second into xmm1 only when its slot was never written (a transient left
1401
+ # in a register, which no memory operand can name). The rescue happens
1402
+ # *before* xmm0 is filled, because the value being rescued is the one
1403
+ # sitting in xmm0 — this is the vector-file version of the ordering rule
1404
+ # #load_binary_operands follows.
1405
+ def load_float_operands(a, b, size)
1406
+ refresh_slot_residency
1407
+ load_xmm(XMM1, b, size) unless slot_written?(b)
1408
+ load_xmm(XMM0, a, size)
1409
+ end
1410
+
1411
+ # The r/m half of a floating instruction whose reg half is xmm0: b's slot
1412
+ # when it was written, xmm1 when #load_float_operands had to stage it.
1413
+ def emit_float_rm(b)
1414
+ if slot_written?(b)
1415
+ emit_modrm_rbp_disp(XMM0, slot_disp(b))
1416
+ else
1417
+ emit(modrm_reg(XMM0, XMM1))
1418
+ end
1419
+ end
1420
+
1068
1421
  # A floating comparison (:feq..:fge), materialized into eax as an int 0/1
1069
1422
  # like an integer comparison but through ucomiss/ucomisd, whose result is
1070
1423
  # read from the flags with NaN awareness. The ordering ops reduce to a
@@ -1109,15 +1462,15 @@ module Rubycc
1109
1462
  store_reg(EAX, dst)
1110
1463
  end
1111
1464
 
1112
- # ucomiss xmm0, xmm1 (size 4) / ucomisd (size 8, a 66 prefix), the ordered
1113
- # scalar compare that sets ZF/PF/CF for the setcc that follows. The two
1114
- # operands are loaded into xmm0/xmm1 from their slots first.
1465
+ # ucomiss xmm0, xmm/m32 (size 4) / ucomisd (size 8, a 66 prefix), the
1466
+ # ordered scalar compare that sets ZF/PF/CF for the setcc that follows.
1467
+ # The first operand is loaded into xmm0 and the second named where it
1468
+ # lives, exactly as #emit_float_binary does.
1115
1469
  def emit_ucomis(a, b, size)
1116
- load_xmm(XMM0, a, size)
1117
- load_xmm(XMM1, b, size)
1470
+ load_float_operands(a, b, size)
1118
1471
  emit(0x66) if size == 8 # ucomisd operand-size prefix
1119
1472
  emit(0x0F, 0x2E) # ucomiss/ucomisd
1120
- emit(modrm_reg(XMM0, XMM1))
1473
+ emit_float_rm(b)
1121
1474
  end
1122
1475
 
1123
1476
  # :itof — cvtsi2ss/cvtsi2sd converts a signed integer in a GP register to
@@ -1177,18 +1530,41 @@ module Rubycc
1177
1530
  # single/double form; the rbp-relative ModR/M reuses the integer helper,
1178
1531
  # the xmm number sitting in its reg field (0..7 for the scratch pair and the
1179
1532
  # eight argument registers alike, all within the 3-bit field, so no REX.R).
1533
+ #
1534
+ # As with #load_reg, the move disappears when `xmm` already holds this
1535
+ # slot at this width and becomes a register-to-register move when another
1536
+ # vector register does. The register form is `movaps` (0F 28 /r), which
1537
+ # copies all 128 bits: that is exactly what a reload would have produced,
1538
+ # since a movss/movsd *from memory* zeroes the bits above the value it
1539
+ # loads, so the source register's upper half is already what the
1540
+ # destination's would be.
1180
1541
  def load_xmm(xmm, vreg, size)
1181
- emit(size == 8 ? 0xF2 : 0xF3)
1182
- emit(0x0F, 0x10)
1183
- emit_modrm_rbp_disp(xmm, slot_disp(vreg))
1542
+ refresh_slot_residency
1543
+ return if slot_resident_in_vector?(xmm, vreg, size)
1544
+
1545
+ source = vector_register_holding_slot(vreg, size)
1546
+ if source
1547
+ emit(0x0F, 0x28, modrm_reg(xmm, source)) # movaps xmm, xmm_source
1548
+ else
1549
+ emit(size == 8 ? 0xF2 : 0xF3)
1550
+ emit(0x0F, 0x10)
1551
+ emit_modrm_rbp_disp(xmm, slot_disp(vreg))
1552
+ end
1553
+ note_slot_loaded_to_vector(xmm, vreg, size)
1184
1554
  end
1185
1555
 
1186
1556
  # movss/movsd [rbp + disp], xmm: stores an xmm register into a slot, the
1187
1557
  # counterpart of #load_xmm (opcode 0x11 writes memory from the register).
1188
1558
  def store_xmm(xmm, vreg, size)
1559
+ refresh_slot_residency
1560
+ if @transient[vreg]
1561
+ note_slot_loaded_to_vector(xmm, vreg, size)
1562
+ return
1563
+ end
1189
1564
  emit(size == 8 ? 0xF2 : 0xF3)
1190
1565
  emit(0x0F, 0x11)
1191
1566
  emit_modrm_rbp_disp(xmm, slot_disp(vreg))
1567
+ note_slot_stored_from_vector(xmm, vreg, size)
1192
1568
  end
1193
1569
 
1194
1570
  # Emits "jmp rel32" with a zero placeholder and records a fixup so the
@@ -1198,9 +1574,20 @@ module Rubycc
1198
1574
  record_fixup(label_id)
1199
1575
  end
1200
1576
 
1577
+ # The condition is tested where it lives unless it is already in eax: a
1578
+ # "cmp dword [rbp+disp], 0" — or "cmp r32, 0" for a promoted condition —
1579
+ # reads the same low four bytes "test eax, eax" would have, and saves the
1580
+ # load. (The 83 /7 form takes a sign-extended imm8, which is all a
1581
+ # comparison against zero needs.)
1201
1582
  def emit_jump_if_zero(cond, label_id)
1202
- load_reg(EAX, cond)
1203
- emit(0x85, 0xC0) # test eax, eax
1583
+ refresh_slot_residency
1584
+ if rm_operand?(cond) && !slot_resident_in?(EAX, cond)
1585
+ emit_vreg_rm([0x83], cond, reg: 7)
1586
+ emit(0x00) # cmp r/m32, 0
1587
+ else
1588
+ load_reg(EAX, cond)
1589
+ emit(0x85, 0xC0) # test eax, eax
1590
+ end
1204
1591
  emit(0x0F, 0x84) # je rel32
1205
1592
  record_fixup(label_id)
1206
1593
  end
@@ -1227,74 +1614,345 @@ module Rubycc
1227
1614
  # A size of 8 materializes a full 64-bit immediate (movabs rax, imm64),
1228
1615
  # needed for a `long`/`unsigned long` constant that does not fit — or
1229
1616
  # would not sign-extend correctly — in 32 bits. Otherwise a 32-bit
1230
- # "mov eax, imm32" suffices: it fills the low 32 bits (the whole value of
1231
- # a 4-byte-or-narrower type) and zeroes the upper half of rax.
1617
+ # "mov r32, imm32" suffices: it fills the low 32 bits (the whole value of
1618
+ # a 4-byte-or-narrower type) and zeroes the register's upper half.
1619
+ #
1620
+ # "mov r64/r32, imm" (B8+rd) names its destination in the opcode's low
1621
+ # three bits, extended by REX.B, so a promoted destination is written
1622
+ # directly and no move follows (#result_register).
1232
1623
  def emit_const(dst, value, size = nil)
1624
+ refresh_slot_residency
1625
+ target = result_register(dst)
1233
1626
  if size == 8
1234
- emit(0x48, 0xB8) # movabs rax, imm64
1627
+ emit_rex(rex_w: true, rm: target) # REX.W (+ REX.B)
1628
+ emit(0xB8 | (target & 7)) # movabs r64, imm64
1235
1629
  emit_bytes([value & 0xFFFFFFFFFFFFFFFF].pack("Q<"))
1236
1630
  else
1237
- emit(0xB8) # mov eax, imm32
1631
+ emit_rex(rm: target) # REX.B for r12..r15
1632
+ emit(0xB8 | (target & 7)) # mov r32, imm32
1238
1633
  emit_bytes([value & 0xFFFFFFFF].pack("L<"))
1239
1634
  end
1240
- store_reg(EAX, dst)
1635
+ # Either form is one "mov r, imm" writing the opcode's own register.
1636
+ store_result(target, dst, only_wrote: target)
1241
1637
  end
1242
1638
 
1243
1639
  # A size of 8 prefixes REX.W so the operation runs on the full 64-bit
1244
- # rax/rcx (pointer arithmetic and index scaling); otherwise it stays a
1245
- # 32-bit int operation. The opcode bytes are identical either way.
1246
- def emit_binary(dst, a, b, opcode_bytes, size = nil)
1247
- load_reg(EAX, a)
1248
- load_reg(ECX, b)
1249
- emit(0x48) if size == 8
1640
+ # rax (pointer arithmetic and index scaling); otherwise it stays a 32-bit
1641
+ # int operation. The opcode bytes are identical either way.
1642
+ #
1643
+ # `memory_bytes`, when the op has such a form, is the opcode of its
1644
+ # "register, r/m" direction, which #emit_vreg_rm then points at b's own
1645
+ # slot or promoted register — so only `a` is ever loaded and the whole
1646
+ # instruction costs one load plus itself. `opcode_bytes` is the fallback
1647
+ # "eax, ecx" encoding, used by the shifts, whose count has to reach cl and
1648
+ # cannot be a memory operand at all. `commutative` lets the two be
1649
+ # exchanged, which is worth doing when it makes the one remaining load
1650
+ # free — or when it puts a promoted destination on the left, where the
1651
+ # result can be accumulated in place (#emit_promoted_binary).
1652
+ def emit_binary(dst, a, b, opcode_bytes, size = nil, memory_bytes: nil, commutative: false)
1653
+ refresh_slot_residency
1654
+ a, b = b, a if commutative && swap_binary_operands?(dst, a, b)
1655
+ if memory_bytes && @promoted[dst] && (dst == a || dst != b)
1656
+ emit_promoted_binary(dst, a, b, memory_bytes, size)
1657
+ elsif memory_bytes && rm_operand?(b)
1658
+ load_reg(EAX, a)
1659
+ emit_vreg_rm(memory_bytes, b, rex_w: size == 8)
1660
+ store_reg(EAX, dst)
1661
+ else
1662
+ load_binary_operands(a, b, commutative: commutative)
1663
+ emit(0x48) if size == 8
1664
+ opcode_bytes.each { |byte| emit(byte) }
1665
+ store_reg(EAX, dst)
1666
+ end
1667
+ end
1668
+
1669
+ # The "register, r/m" direction of a binary op with its reg field aimed
1670
+ # straight at the callee-saved register `dst` was promoted into, so the
1671
+ # result is written where it lives and no move follows.
1672
+ #
1673
+ # `a` is brought into that register first, a move that disappears when
1674
+ # `dst` and `a` are the same value — the shape "i = i + 1" and "sum += x"
1675
+ # take once the single-use copies are forwarded, and the reason this path
1676
+ # exists. The caller has ruled out the one arrangement the move would
1677
+ # break: dst == b with dst != a, whose b it would overwrite before the
1678
+ # arithmetic could read it.
1679
+ #
1680
+ # Only the promoted register is written, and the residency table can name
1681
+ # none of them (PROMOTION_REGISTERS is disjoint from the scratch,
1682
+ # argument and return registers every entry is keyed by), so every
1683
+ # residency in flight survives; #note_register_clobbered still drops the
1684
+ # one the `load_reg` above may have recorded against the target itself.
1685
+ def emit_promoted_binary(dst, a, b, memory_bytes, size)
1686
+ target = @promoted[dst]
1687
+ load_reg(target, a) unless dst == a
1688
+ if rm_operand?(b)
1689
+ emit_vreg_rm(memory_bytes, b, reg: target, rex_w: size == 8)
1690
+ else
1691
+ # A transient has neither slot nor register of its own; it is still
1692
+ # in whichever scratch register its producer computed it in.
1693
+ source = register_holding_slot(b)
1694
+ unless source
1695
+ load_reg(ECX, b)
1696
+ source = ECX
1697
+ end
1698
+ emit_register_rm(memory_bytes, source, reg: target, rex_w: size == 8)
1699
+ end
1700
+ note_register_clobbered(target)
1701
+ end
1702
+
1703
+ # Whether `vreg` may be named as an instruction's r/m operand, and so
1704
+ # read without being loaded first. A value in a slot is named [rbp +
1705
+ # disp] and a promoted one register-direct; only a transient is neither,
1706
+ # its value never having reached a slot and its register being whichever
1707
+ # one its producer happened to use.
1708
+ def rm_operand?(vreg)
1709
+ !@transient[vreg]
1710
+ end
1711
+
1712
+ # Emits an instruction whose r/m operand is wherever `vreg` lives: its
1713
+ # stack slot, or — for a promoted value, which has no slot at all — the
1714
+ # callee-saved register it owns, named register-direct (mod = 11). `reg`
1715
+ # is the ModR/M reg field, a register number in a two-operand form and an
1716
+ # opcode extension in a group instruction. The caller must have asked
1717
+ # #rm_operand? first.
1718
+ def emit_vreg_rm(opcode_bytes, vreg, reg: EAX, rex_w: false)
1719
+ promoted = @promoted[vreg]
1720
+ if promoted
1721
+ emit_register_rm(opcode_bytes, promoted, reg: reg, rex_w: rex_w)
1722
+ else
1723
+ emit_slot_rm(opcode_bytes, vreg, reg: reg, rex_w: rex_w)
1724
+ end
1725
+ end
1726
+
1727
+ # Emits an instruction whose r/m operand is `vreg`'s stack slot: the REX
1728
+ # prefix the operand width and register numbers call for, the opcode
1729
+ # bytes, then a ModR/M whose reg field is `reg` and whose r/m field
1730
+ # addresses [rbp + slot].
1731
+ #
1732
+ # Reading an operand straight out of its slot is as correct as loading it
1733
+ # into a register first and is one instruction shorter. The slot is where
1734
+ # the spill-everything discipline keeps the value; nothing is emitted
1735
+ # between the load of the first operand and this that could write memory;
1736
+ # and the width the instruction reads (4 bytes, or 8 under REX.W) is
1737
+ # exactly the width the register form's arithmetic would have used, so the
1738
+ # value representation is honored unchanged — a narrow value's
1739
+ # indeterminate high half is never looked at either way.
1740
+ def emit_slot_rm(opcode_bytes, vreg, reg: EAX, rex_w: false)
1741
+ emit_rex(rex_w: rex_w, reg: reg)
1250
1742
  opcode_bytes.each { |byte| emit(byte) }
1251
- store_reg(EAX, dst)
1743
+ emit_modrm_rbp_disp(reg & 7, slot_disp(vreg))
1744
+ end
1745
+
1746
+ # The register-direct counterpart of #emit_slot_rm: the same reg field
1747
+ # against an rm field that names register `rm` (mod = 11) rather than a
1748
+ # memory operand. This is how a promoted value is read in place. Two
1749
+ # encoding traps a memory operand has do not exist here — an rm of 100
1750
+ # names r12/rsp instead of introducing a SIB byte, and an rm of 101 names
1751
+ # r13/rbp instead of meaning "no base" — so REX.B is all r12..r15 need.
1752
+ def emit_register_rm(opcode_bytes, rm, reg: EAX, rex_w: false)
1753
+ emit_rex(rex_w: rex_w, reg: reg, rm: rm)
1754
+ opcode_bytes.each { |byte| emit(byte) }
1755
+ emit(0xC0 | ((reg & 7) << 3) | (rm & 7))
1756
+ end
1757
+
1758
+ # The REX prefix an instruction needs, emitted only when some field asks
1759
+ # for one. W widens the operation to 64 bits; R extends the ModR/M reg
1760
+ # field, X the SIB index field and B the ModR/M r/m (or SIB base, or
1761
+ # opcode-embedded) register — each supplying the high bit of a register
1762
+ # number 8..15 whose low three bits stay in the field itself.
1763
+ def emit_rex(rex_w: false, reg: 0, rm: 0, index: 0)
1764
+ rex = 0x40 | (rex_w ? 0x08 : 0) | (reg >= 8 ? 0x04 : 0) |
1765
+ (index >= 8 ? 0x02 : 0) | (rm >= 8 ? 0x01 : 0)
1766
+ emit(rex) unless rex == 0x40
1767
+ end
1768
+
1769
+ # Where an instruction that computes a general-register result should put
1770
+ # it: the callee-saved register `dst` was promoted into, so the value is
1771
+ # written home directly, or eax for a value that lives in a slot.
1772
+ def result_register(dst)
1773
+ @promoted[dst] || EAX
1774
+ end
1775
+
1776
+ # Completes such an instruction. A destination that lives in a slot still
1777
+ # needs the store; a promoted `dst` *is* `reg`, so the value is already
1778
+ # home and all that is left is telling the residency table what the bytes
1779
+ # just emitted did to it.
1780
+ #
1781
+ # **The default answer is to throw the table away.** Bytes have been
1782
+ # emitted since it was last known true — the caller's own instruction —
1783
+ # and nothing here can see which registers they wrote. Keeping the table
1784
+ # alive across them is #note_register_clobbered's exception, sound only
1785
+ # when those bytes wrote `reg` and nothing else the table can name; that
1786
+ # is a fact about one lowering's encoding, so the lowering is what states
1787
+ # it, by passing `only_wrote: reg`. Anything that says nothing gets the
1788
+ # safe reading, which costs an optimization and never correctness — and a
1789
+ # lowering that later grows a second scratch write has to come back to its
1790
+ # own claim rather than silently reviving a stale residency. All four
1791
+ # callers here claim the fast path today; the aarch64 backend, whose
1792
+ # #emit_alloca rounds its size in rax's counterpart and whose remainder
1793
+ # takes a scratch for the quotient, has two that cannot.
1794
+ #
1795
+ # "Nothing else the table can name" means none of rax, rcx, rdx, rsi, rdi,
1796
+ # r10, the argument registers or a promoted one — the registers #load_reg
1797
+ # is ever asked to fill, and so the only ones an entry can be keyed by.
1798
+ def store_result(reg, dst, only_wrote: nil)
1799
+ unless @promoted[dst]
1800
+ store_reg(reg, dst) # which discards a stale table itself, before anything else
1801
+ return
1802
+ end
1803
+
1804
+ if only_wrote == reg
1805
+ note_register_clobbered(reg)
1806
+ else
1807
+ refresh_slot_residency
1808
+ end
1809
+ end
1810
+
1811
+ # :scaled_add — dst <- base + index * element_size, the address a
1812
+ # subscript forms. `lea` (8D /r) computes an address rather than loading
1813
+ # from it, and its SIB byte carries the scale as a two-bit shift, so the
1814
+ # element-size multiply and the add to the base become one instruction
1815
+ # that touches no flags. REX.W makes it a 64-bit computation, which is
1816
+ # what a pointer needs.
1817
+ #
1818
+ # All three of the instruction's registers are free — base and index are
1819
+ # named independently in the SIB byte and the destination in the ModR/M
1820
+ # reg field — so a promoted value may be any of them and the whole address
1821
+ # is formed without a move. That freedom is what brings the three encoding
1822
+ # traps of the SIB byte into reach, none of which a pair of scratch
1823
+ # registers could ever have hit (Intel SDM Vol. 2A, Tables 2-5 and 2-3;
1824
+ # REX.B extends the base, REX.X the index and REX.R the destination):
1825
+ #
1826
+ # * a SIB **base** field of 101 with mod = 00 does not name rbp/r13 but
1827
+ # "no base register, disp32 follows", so those two take mod = 01 with
1828
+ # a zero disp8 instead — one byte for the register the encoding's
1829
+ # shorter form has spent on something else;
1830
+ # * a SIB base field of 100 does name rsp/r12 (it is the *ModR/M* rm
1831
+ # field where 100 means "a SIB byte follows"), so r12 as a base needs
1832
+ # nothing beyond its REX.B;
1833
+ # * a SIB **index** field of 100 means "no index" — but only at REX.X =
1834
+ # 0. With REX.X set it is r12, which is why r12 works as an index and
1835
+ # rsp, whose REX.X is 0 by construction, is the register that cannot.
1836
+ def emit_scaled_add(dst, base_vreg, index_vreg, element_size)
1837
+ base, index = address_operands(base_vreg, index_vreg)
1838
+ target = result_register(dst)
1839
+ emit_rex(rex_w: true, reg: target, index: index, rm: base)
1840
+ emit(0x8D) # lea r64, [base + index*scale]
1841
+ sib = (SIB_SCALES.fetch(element_size) << 6) | ((index & 7) << 3) | (base & 7)
1842
+ if (base & 7) == 5
1843
+ emit(0x44 | ((target & 7) << 3), sib, 0x00) # mod=01, rm=100 (SIB), disp8 = 0
1844
+ else
1845
+ emit(0x04 | ((target & 7) << 3), sib) # mod=00, rm=100 (SIB follows)
1846
+ end
1847
+ # `lea` writes its reg field; base and index are read (#address_operands
1848
+ # loaded them and accounted for that itself).
1849
+ store_result(target, dst, only_wrote: target)
1850
+ end
1851
+
1852
+ # Reports which register holds a scaled address's base and which its
1853
+ # index. A promoted operand is used where it already is; anything else is
1854
+ # loaded into a scratch register. Unlike an arithmetic opcode, `lea` names
1855
+ # its base and index independently, so either assignment encodes — which
1856
+ # also lets whichever operand is already resident keep the register it is
1857
+ # in when neither is promoted.
1858
+ def address_operands(base_vreg, index_vreg)
1859
+ refresh_slot_residency
1860
+ base = @promoted[base_vreg]
1861
+ index = @promoted[index_vreg]
1862
+ if base && index
1863
+ [base, index]
1864
+ elsif base
1865
+ load_reg(EAX, index_vreg)
1866
+ [base, EAX]
1867
+ elsif index
1868
+ load_reg(EAX, base_vreg)
1869
+ [EAX, index]
1870
+ elsif slot_resident_in?(EAX, index_vreg) && !slot_resident_in?(EAX, base_vreg)
1871
+ load_reg(ECX, base_vreg)
1872
+ load_reg(EAX, index_vreg)
1873
+ [ECX, EAX]
1874
+ else
1875
+ load_reg(EAX, base_vreg)
1876
+ load_reg(ECX, index_vreg)
1877
+ [EAX, ECX]
1878
+ end
1252
1879
  end
1253
1880
 
1254
1881
  # :mulhi — the unsigned high 64 bits of a 64x64 product, the piece a
1255
1882
  # synthesized __int128 multiply needs beyond the low 64 that :mul gives.
1256
- # `mul rcx` (REX.W F7 /4) multiplies rax by rcx into rdx:rax; the high half
1257
- # lands in rdx, which is stored to the destination. The one-operand `mul`
1258
- # is the unsigned multiply, so this is the unsigned high product regardless
1259
- # of the operands' declared signedness (the low 64 bits, and hence a full
1260
- # 128-bit low result, are identical for signed and unsigned).
1883
+ # `mul` (REX.W F7 /4) multiplies rax by its one operand b's slot or
1884
+ # promoted register, or rcx when it has neither into rdx:rax; the high
1885
+ # half lands in rdx, which is stored to the destination. The one-operand
1886
+ # `mul` is the unsigned multiply, so this is the unsigned high product
1887
+ # regardless of the operands' declared signedness (the low 64 bits, and
1888
+ # hence a full 128-bit low result, are identical for signed and unsigned).
1261
1889
  def emit_mulhi(dst, a, b)
1262
- load_reg(EAX, a) # rax = a
1263
- load_reg(ECX, b) # rcx = b
1264
- emit(0x48, 0xF7, 0xE1) # mul rcx -> rdx:rax = rax * rcx
1890
+ refresh_slot_residency
1891
+ a, b = b, a if prefer_swapped_operands?(a, b)
1892
+ if rm_operand?(b)
1893
+ load_reg(EAX, a)
1894
+ emit_vreg_rm([0xF7], b, reg: 4, rex_w: true) # mul qword r/m64 (/4)
1895
+ else
1896
+ load_binary_operands(a, b, commutative: true)
1897
+ emit(0x48, 0xF7, 0xE1) # mul rcx -> rdx:rax = rax * rcx
1898
+ end
1265
1899
  store_reg(EDX, dst) # dst = high 64 bits
1266
1900
  end
1267
1901
 
1268
- # A size of 8 does a 64-bit signed division (REX.W cqo + REX.W idiv rcx),
1269
- # used for pointer differences; otherwise the 32-bit int division.
1902
+ # A size of 8 does a 64-bit signed division (REX.W cqo + REX.W idiv), used
1903
+ # for pointer differences; otherwise the 32-bit int division. The divisor
1904
+ # is the one-operand `idiv`'s r/m, which is b's slot wherever it can be.
1270
1905
  def emit_divmod(dst, a, b, result_reg, size = nil)
1271
- load_reg(EAX, a)
1272
- load_reg(ECX, b)
1273
- if size == 8
1274
- emit(0x48, 0x99) # cqo: sign-extend rax into rdx:rax
1275
- emit(0x48, 0xF7, 0xF9) # idiv rcx
1276
- else
1277
- emit(0x99) # cdq: sign-extend eax into edx:eax
1278
- emit(0xF7, 0xF9) # idiv ecx
1279
- end
1906
+ divisor_in_register = load_dividend_and_divisor(a, b)
1907
+ emit(0x48) if size == 8 # REX.W turns cdq into cqo
1908
+ emit(0x99) # cdq/cqo: sign-extend eax/rax into edx:eax / rdx:rax
1909
+ emit_divisor_operand(divisor_in_register, b, 7, size) # idiv (/7)
1280
1910
  store_reg(result_reg, dst)
1281
1911
  end
1282
1912
 
1283
1913
  # Unsigned division/remainder. Unlike the signed form, the high half of
1284
1914
  # the dividend is zeroed (xor edx, edx, which also clears the upper 32
1285
1915
  # bits of rdx for the 64-bit case) rather than sign-extended, and the
1286
- # unsigned `div` opcode is used. size 8 divides the full 64-bit rax by
1287
- # rcx; otherwise the 32-bit division. Quotient in eax, remainder in edx.
1916
+ # unsigned `div` opcode is used. size 8 divides the full 64-bit rax by the
1917
+ # divisor; otherwise the 32-bit division. Quotient in eax, remainder in edx.
1288
1918
  def emit_udivmod(dst, a, b, result_reg, size = nil)
1289
- load_reg(EAX, a)
1290
- load_reg(ECX, b)
1919
+ divisor_in_register = load_dividend_and_divisor(a, b)
1291
1920
  emit(0x31, 0xD2) # xor edx, edx
1292
- if size == 8
1293
- emit(0x48, 0xF7, 0xF1) # div rcx
1921
+ emit_divisor_operand(divisor_in_register, b, 6, size) # div (/6)
1922
+ store_reg(result_reg, dst)
1923
+ end
1924
+
1925
+ # Stages a division's operands: the dividend always into eax, the divisor
1926
+ # into ecx only when it is a transient, which the one-operand `div`/`idiv`
1927
+ # can name no other way. Returns true when the divisor is in ecx. Both
1928
+ # loads happen before the sign-extension step that follows, which writes
1929
+ # edx and must not be undone.
1930
+ #
1931
+ # The dividend and the quotient/remainder pair are fixed at rax and
1932
+ # rdx:rax by the instruction itself, so this is one of the places a
1933
+ # promoted destination changes nothing; a promoted *divisor*, though, is
1934
+ # named in place like any other r/m operand, and rdx cannot collide with
1935
+ # it (PROMOTION_REGISTERS holds none of the scratch registers).
1936
+ def load_dividend_and_divisor(a, b)
1937
+ if rm_operand?(b)
1938
+ load_reg(EAX, a)
1939
+ false
1294
1940
  else
1295
- emit(0xF7, 0xF1) # div ecx
1941
+ load_binary_operands(a, b)
1942
+ true
1943
+ end
1944
+ end
1945
+
1946
+ # The r/m operand of the one-operand `div`/`idiv` group (F7 /6 unsigned,
1947
+ # /7 signed): ecx when #load_dividend_and_divisor put it there, and b's
1948
+ # slot or promoted register otherwise.
1949
+ def emit_divisor_operand(in_register, b, extension, size)
1950
+ if in_register
1951
+ emit(0x48) if size == 8
1952
+ emit(0xF7, 0xC0 | (extension << 3) | ECX)
1953
+ else
1954
+ emit_vreg_rm([0xF7], b, reg: extension, rex_w: size == 8)
1296
1955
  end
1297
- store_reg(result_reg, dst)
1298
1956
  end
1299
1957
 
1300
1958
  # mov r64, [rbp + disp]: slots are always moved 64 bits at a time so a
@@ -1303,17 +1961,146 @@ module Rubycc
1303
1961
  # zero the upper 32 bits of rax, so the slot's high half is already zero.
1304
1962
  # The REX prefix carries W (64-bit operand) plus R for r8/r9 (>= 8), whose
1305
1963
  # low 3 bits go into the ModR/M reg field.
1964
+ #
1965
+ # The load disappears when `reg` already holds this slot's value and
1966
+ # becomes a register-to-register move when another scratch register does
1967
+ # (SlotResidency decides both). Either way `reg` ends up with the same 64
1968
+ # bits the memory form would have fetched — the slot was written 64 bits
1969
+ # at a time and it is those bits being reused — so the value
1970
+ # representation above is untouched, and a narrow value's high half is as
1971
+ # indeterminate (or as zero) as it was before.
1306
1972
  def load_reg(reg, vreg)
1307
- emit(0x48 | (reg >= 8 ? 0x04 : 0)) # REX.W (+ REX.R for r8/r9)
1308
- emit(0x8B)
1309
- emit_modrm_rbp_disp(reg & 7, slot_disp(vreg))
1973
+ refresh_slot_residency
1974
+ promoted = @promoted[vreg]
1975
+ if promoted
1976
+ # There is no slot to read: this value has been in `promoted` since
1977
+ # the prologue and stays there until the function returns, so the
1978
+ # load is a register-to-register move — or nothing at all when the
1979
+ # caller happens to want it where it already is. The move writes
1980
+ # `reg` and touches no memory, which is exactly what the residency
1981
+ # table has to be told (see SlotResidency#note_register_clobbered).
1982
+ emit_reg_move(reg, promoted) unless reg == promoted
1983
+ note_register_clobbered(reg)
1984
+ return
1985
+ end
1986
+ return if slot_resident_in?(reg, vreg)
1987
+
1988
+ source = register_holding_slot(vreg)
1989
+ if source
1990
+ emit_reg_move(reg, source)
1991
+ else
1992
+ emit(0x48 | (reg >= 8 ? 0x04 : 0)) # REX.W (+ REX.R for r8/r9)
1993
+ emit(0x8B)
1994
+ emit_modrm_rbp_disp(reg & 7, slot_disp(vreg))
1995
+ end
1996
+ note_slot_loaded(reg, vreg)
1310
1997
  end
1311
1998
 
1312
1999
  # mov [rbp + disp], r64. See load_reg for the 64-bit and REX rationale.
2000
+ # The store itself is never skipped: the slot is the value's home, and
2001
+ # nothing here knows whether a later branch reaches a reader by a path
2002
+ # that goes nowhere near this register.
1313
2003
  def store_reg(reg, vreg)
2004
+ refresh_slot_residency
2005
+ promoted = @promoted[vreg]
2006
+ if promoted
2007
+ # The value's home is a register, so the store is a move into it. No
2008
+ # slot is written and no scratch register can be describing one (a
2009
+ # promoted vreg is never recorded), so every residency in flight is
2010
+ # still true — it is only the emitted bytes that have to be accounted
2011
+ # for (SlotResidency#note_slots_undisturbed).
2012
+ emit_reg_move(promoted, reg) unless reg == promoted
2013
+ note_slots_undisturbed
2014
+ return
2015
+ end
2016
+ if @transient[vreg]
2017
+ # The value's only reader is the next instruction, which will find it
2018
+ # here; the slot itself is never named again, so nothing is written.
2019
+ note_slot_loaded(reg, vreg)
2020
+ return
2021
+ end
1314
2022
  emit(0x48 | (reg >= 8 ? 0x04 : 0)) # REX.W (+ REX.R for r8/r9)
1315
2023
  emit(0x89)
1316
2024
  emit_modrm_rbp_disp(reg & 7, slot_disp(vreg))
2025
+ note_slot_stored(reg, vreg)
2026
+ end
2027
+
2028
+ # Whether `vreg`'s slot may be named as an instruction's memory operand.
2029
+ # It may not when the value never reached it: a transient is left in the
2030
+ # register its producer computed it in, and a promoted value lives in a
2031
+ # register of its own for the whole function, so in both cases the slot
2032
+ # holds nothing. The test is on the two sets, not on what happens to be
2033
+ # resident, so it does not depend on how far into an instruction it is
2034
+ # asked.
2035
+ #
2036
+ # Only the floating ops ask any more; the integer ones ask #rm_operand?
2037
+ # instead, a promoted value being nameable there as a register even though
2038
+ # its slot is not. The difference does not arise in practice — a value the
2039
+ # vector register file touches is refused promotion outright
2040
+ # (IR::Promotion::VECTOR_OPS), so a floating operand is only ever a slot or
2041
+ # a transient — and the stricter test is the one to ask on a path that has
2042
+ # no register form to fall back to but xmm1.
2043
+ def slot_written?(vreg)
2044
+ !@transient[vreg] && !@promoted[vreg]
2045
+ end
2046
+
2047
+ # mov r64, r64 — the register-to-register form of #load_reg's mov, for a
2048
+ # value that is already in another scratch register or that lives in a
2049
+ # promoted one. REX.W widens it, REX.R extends the source (the ModR/M reg
2050
+ # field) and REX.B the destination (the rm field), so r8/r9 and r12..r15
2051
+ # work on either side. The ModR/M is register-direct (mod = 11), where an
2052
+ # rm of 100 names r12 rather than selecting a SIB byte, so no promoted
2053
+ # register needs a special case the way a memory operand's base would.
2054
+ def emit_reg_move(dst, src)
2055
+ emit(0x48 | (src >= 8 ? 0x04 : 0) | (dst >= 8 ? 0x01 : 0))
2056
+ emit(0x89, 0xC0 | ((src & 7) << 3) | (dst & 7))
2057
+ end
2058
+
2059
+ # Loads a two-operand instruction's operands into eax and ecx.
2060
+ #
2061
+ # Which one is fetched first stops being arbitrary once #load_reg can
2062
+ # reuse a resident value: if `b` is the value sitting in eax, loading `a`
2063
+ # there first would throw it away and force `b` to be re-read from memory.
2064
+ # Fetching ecx first instead keeps it, as a register move. A `commutative`
2065
+ # op can do better still — swapping the two makes the resident operand
2066
+ # eax's, so nothing is moved at all — and is safe to swap precisely
2067
+ # because the opcode's two operands are interchangeable (this is not true
2068
+ # of :sub or of the shifts, whose count must reach cl).
2069
+ def load_binary_operands(a, b, commutative: false)
2070
+ refresh_slot_residency
2071
+ if commutative && prefer_swapped_operands?(a, b)
2072
+ a, b = b, a
2073
+ elsif slot_resident_in?(EAX, b) && !slot_resident_in?(EAX, a)
2074
+ # Fetch ecx first: eax is where b is, and loading a would lose it —
2075
+ # which for a transient b would lose it for good, its slot never
2076
+ # having been written.
2077
+ load_reg(ECX, b)
2078
+ end
2079
+ load_reg(EAX, a)
2080
+ load_reg(ECX, b)
2081
+ end
2082
+
2083
+ # Whether a commutative op should exchange its operands. A promoted
2084
+ # destination outranks everything else: "sum = x + sum" is the same
2085
+ # addition as "sum = sum + x", and only the second can be accumulated in
2086
+ # place (#emit_promoted_binary), which saves a move whatever the operands
2087
+ # cost. With that settled either way, the older question stands alone.
2088
+ def swap_binary_operands?(dst, a, b)
2089
+ return dst == b && dst != a if @promoted[dst]
2090
+
2091
+ prefer_swapped_operands?(a, b)
2092
+ end
2093
+
2094
+ # Whether a commutative op is better off with its operands exchanged.
2095
+ # Two cases want it, and they are one case seen twice: whichever operand
2096
+ # is already in eax should be the one taken from a register, leaving the
2097
+ # other free to be read where it lives. An operand that can be named
2098
+ # neither in a slot nor in a promoted register (a transient) has to be
2099
+ # that one, since no r/m field can reach it.
2100
+ def prefer_swapped_operands?(a, b)
2101
+ return false unless rm_operand?(a)
2102
+
2103
+ !rm_operand?(b) || (slot_resident_in?(EAX, b) && !slot_resident_in?(EAX, a))
1317
2104
  end
1318
2105
 
1319
2106
  def slot_disp(vreg)