cranelift-codegen 0.96.0

Low-level code generator library
Documentation
;; `select`/`bitselect`-related rewrites

;; remove select when both choices are the same
(rule (simplify (select    ty _ x x)) x)
(rule (simplify (bitselect ty _ x x)) x)

;; Transform select-of-icmp into {u,s}{min,max} instructions where possible.
(rule (simplify (select ty (sgt _ x y) x y)) (smax ty x y))
(rule (simplify (select ty (sge _ x y) x y)) (smax ty x y))
(rule (simplify (select ty (ugt _ x y) x y)) (umax ty x y))
(rule (simplify (select ty (uge _ x y) x y)) (umax ty x y))
(rule (simplify (select ty (slt _ x y) x y)) (smin ty x y))
(rule (simplify (select ty (sle _ x y) x y)) (smin ty x y))
(rule (simplify (select ty (ult _ x y) x y)) (umin ty x y))
(rule (simplify (select ty (ule _ x y) x y)) (umin ty x y))

;; These are the same rules as above, but when the operands for select are swapped
(rule (simplify (select ty (slt _ x y) y x)) (smax ty x y))
(rule (simplify (select ty (sle _ x y) y x)) (smax ty x y))
(rule (simplify (select ty (ult _ x y) y x)) (umax ty x y))
(rule (simplify (select ty (ule _ x y) y x)) (umax ty x y))
(rule (simplify (select ty (sgt _ x y) y x)) (smin ty x y))
(rule (simplify (select ty (sge _ x y) y x)) (smin ty x y))
(rule (simplify (select ty (ugt _ x y) y x)) (umin ty x y))
(rule (simplify (select ty (uge _ x y) y x)) (umin ty x y))

;; Transform bitselect-of-icmp into {u,s}{min,max} instructions where possible.
(rule (simplify (bitselect ty @ (multi_lane _ _) (sgt _ x y) x y)) (smax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (sge _ x y) x y)) (smax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ugt _ x y) x y)) (umax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (uge _ x y) x y)) (umax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (slt _ x y) x y)) (smin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (sle _ x y) x y)) (smin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ult _ x y) x y)) (umin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ule _ x y) x y)) (umin ty x y))

;; These are the same rules as above, but when the operands for select are swapped
(rule (simplify (bitselect ty @ (multi_lane _ _) (slt _ x y) y x)) (smax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (sle _ x y) y x)) (smax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ult _ x y) y x)) (umax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ule _ x y) y x)) (umax ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (sgt _ x y) y x)) (smin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (sge _ x y) y x)) (smin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (ugt _ x y) y x)) (umin ty x y))
(rule (simplify (bitselect ty @ (multi_lane _ _) (uge _ x y) y x)) (umin ty x y))

;; For floats convert fcmp lt into pseudo_min and gt into pseudo_max
;;
;; fmax_pseudo docs state:
;; The behaviour for this operations is defined as  fmax_pseudo(a, b) = (a < b) ? b : a, and the behaviour for zero
;; or NaN inputs follows from the behaviour of < with such inputs.
;;
;; That is exactly the operation that we match here!
(rule (simplify
       (select ty (fcmp _ (FloatCC.LessThan) x y) x y))
      (fmin_pseudo ty x y))
(rule (simplify
       (select ty (fcmp _ (FloatCC.GreaterThan) x y) x y))
      (fmax_pseudo ty x y))

;; TODO: perform this same optimization to `f{min,max}_pseudo` for vectors
;; with the `bitselect` instruction, but the pattern is a bit more complicated
;; due to most bitselects-over-floats having bitcasts.