x64 backend: add lowerings with load-op-store fusion. (#4071)

x64 backend: add lowerings with load-op-store fusion.

These lowerings use the `OP [mem], reg` forms (or in AT&T syntax, `OP
%reg, (mem)`) -- i.e., x86 instructions that load from memory, perform
an ALU operation, and store the result, all in one instruction. Using
these instruction forms, we can merge three CLIF ops together: a load,
an arithmetic operation, and a store.
This commit is contained in:
Chris Fallin
2022-04-26 18:58:26 -07:00
committed by GitHub
parent 164bfeaf7e
commit dd45f44511
9 changed files with 1442 additions and 298 deletions

View File

@@ -2655,3 +2655,131 @@
(side_effect_concat
(x64_movrm $I64 addr_lo value_lo)
(x64_movrm $I64 addr_hi value_hi)))))
;; Rules for `load*` + ALU op + `store*` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Add mem, reg
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(iadd (and
(sinkable_load sink)
(load flags addr offset))
src2))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_add_mem ty (to_amode flags addr offset) src2))))
;; Add mem, reg with args swapped
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(iadd src2
(and
(sinkable_load sink)
(load flags addr offset))))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_add_mem ty (to_amode flags addr offset) src2))))
;; Sub mem, reg
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(isub (and
(sinkable_load sink)
(load flags addr offset))
src2))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_sub_mem ty (to_amode flags addr offset) src2))))
;; And mem, reg
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(band (and
(sinkable_load sink)
(load flags addr offset))
src2))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_and_mem ty (to_amode flags addr offset) src2))))
;; And mem, reg with args swapped
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(band src2
(and
(sinkable_load sink)
(load flags addr offset))))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_and_mem ty (to_amode flags addr offset) src2))))
;; Or mem, reg
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(bor (and
(sinkable_load sink)
(load flags addr offset))
src2))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_or_mem ty (to_amode flags addr offset) src2))))
;; Or mem, reg with args swapped
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(bor src2
(and
(sinkable_load sink)
(load flags addr offset))))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_or_mem ty (to_amode flags addr offset) src2))))
;; Xor mem, reg
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(bxor (and
(sinkable_load sink)
(load flags addr offset))
src2))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_xor_mem ty (to_amode flags addr offset) src2))))
;; Xor mem, reg with args swapped
(rule (lower
(store =flags
(has_type (ty_32_or_64 ty)
(bxor src2
(and
(sinkable_load sink)
(load flags addr offset))))
=addr
=offset))
(let ((_ RegMemImm (sink_load sink)))
(side_effect
(x64_xor_mem ty (to_amode flags addr offset) src2))))