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:
@@ -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))))
|
||||
|
||||
Reference in New Issue
Block a user