1;; Prelude definitions specific to the mid-end. 2 3;; Any `extern` definitions here are generally implemented in `src/opts.rs`. 4 5;;;;; eclass and enode access ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 6 7;; Extract any node(s) for the given eclass ID. 8(decl multi inst_data (Type InstructionData) Value) 9(extern extractor inst_data inst_data_etor) 10 11;; Identical to `inst_data`, just with a different ISLE type. 12;; This is basically a manual version of `curry`/`uncurry` in Haskell: 13;; to compose extractors the outer one needs to be single-parameter, 14;; so this combines the two parameters of `inst_data` into one. 15(type TypeAndInstructionData (primitive TypeAndInstructionData)) 16(decl multi inst_data_tupled (TypeAndInstructionData) Value) 17(extern extractor inst_data_tupled inst_data_tupled_etor) 18 19;; Construct a pure node, returning a new (or deduplicated 20;; already-existing) eclass ID. 21(decl make_inst (Type InstructionData) Value) 22(extern constructor make_inst make_inst_ctor) 23 24;; Constructors for value arrays. 25(decl value_array_2_ctor (Value Value) ValueArray2) 26(extern constructor value_array_2_ctor value_array_2_ctor) 27(decl value_array_3_ctor (Value Value Value) ValueArray3) 28(extern constructor value_array_3_ctor value_array_3_ctor) 29 30(rule (eq ty x y) (icmp ty (IntCC.Equal) x y)) 31(rule (ne ty x y) (icmp ty (IntCC.NotEqual) x y)) 32(rule (ult ty x y) (icmp ty (IntCC.UnsignedLessThan) x y)) 33(rule (ule ty x y) (icmp ty (IntCC.UnsignedLessThanOrEqual) x y)) 34(rule (ugt ty x y) (icmp ty (IntCC.UnsignedGreaterThan) x y)) 35(rule (uge ty x y) (icmp ty (IntCC.UnsignedGreaterThanOrEqual) x y)) 36(rule (slt ty x y) (icmp ty (IntCC.SignedLessThan) x y)) 37(rule (sle ty x y) (icmp ty (IntCC.SignedLessThanOrEqual) x y)) 38(rule (sgt ty x y) (icmp ty (IntCC.SignedGreaterThan) x y)) 39(rule (sge ty x y) (icmp ty (IntCC.SignedGreaterThanOrEqual) x y)) 40 41;; 3-way comparison, returning -1/0/+1 in I8 42(decl spaceship_s (Type Value Value) Value) 43(rule (spaceship_s ty x y) (isub $I8 (sgt ty x y) (slt ty x y))) 44(extractor (spaceship_s ty x y) (isub $I8 (sgt ty x y) (slt ty x y))) 45(decl spaceship_u (Type Value Value) Value) 46(rule (spaceship_u ty x y) (isub $I8 (ugt ty x y) (ult ty x y))) 47(extractor (spaceship_u ty x y) (isub $I8 (ugt ty x y) (ult ty x y))) 48 49;;;;; optimization toplevel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 50 51;; The main matcher rule invoked by the toplevel driver. 52(decl multi simplify (Value) Value) 53 54;; Mark a node as requiring remat when used in a different block. 55(decl remat (Value) Value) 56(extern constructor remat remat) 57 58;; Mark a node as subsuming whatever else it's rewritten from -- this 59;; is definitely preferable, not just a possible option. Useful for, 60;; e.g., constant propagation where we arrive at a definite "final 61;; answer". 62(decl subsume (Value) Value) 63(extern constructor subsume subsume) 64 65;;;;; constructors ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 66 67(decl iconst_sextend_etor (Type i64) TypeAndInstructionData) 68(extern extractor iconst_sextend_etor iconst_sextend_etor) 69 70;; Construct an `iconst` from an `i64` or Extract an `i64` from an `iconst` 71;; by treating the constant as signed. 72;; When extracting, smaller types get their value sign-extended to 64-bits, 73;; so that `iconst.i8 255` will give you a `-1_i64`. 74;; When constructing, the rule will fail if the value cannot be represented in 75;; the target type. If it fits, it'll be masked accordingly in the constant. 76(decl iconst_s (Type i64) Value) 77(extractor (iconst_s ty c) (inst_data_tupled (iconst_sextend_etor ty c))) 78(rule 0 (iconst_s ty c) 79 (if-let c_masked (u64_and (i64_as_u64 c) (ty_umax ty))) 80 (if-let c_reextended (i64_sextend_u64 ty c_masked)) 81 (if-let $true (u64_eq (i64_as_u64 c) (i64_as_u64 c_reextended))) 82 (iconst ty (imm64 c_masked))) 83(rule 1 (iconst_s $I128 c) (sextend $I128 (iconst_s $I64 c))) 84 85;; Construct an `iconst` from a `u64` or Extract a `u64` from an `iconst` 86;; by treating the constant as unsigned. 87;; When extracting, smaller types get their value zero-extended to 64-bits, 88;; so that `iconst.i8 255` will give you a `255_u64`. 89;; When constructing, the rule will fail if the value cannot be represented in 90;; the target type. 91(decl iconst_u (Type u64) Value) 92(extractor (iconst_u ty c) (iconst ty (u64_from_imm64 c))) 93(rule 0 (iconst_u ty c) 94 (if-let $true (u64_le c (ty_umax ty))) 95 (iconst ty (imm64 c))) 96(rule 1 (iconst_u $I128 c) (uextend $I128 (iconst_u $I64 c))) 97 98;; These take `Value`, rather than going through `inst_data_tupled`, because 99;; most of the time they want to return the original `Value`, and it would be 100;; a waste to need to re-GVN the instruction data in those cases. 101(decl multi sextend_maybe_etor (Type Value) Value) 102(extern extractor infallible sextend_maybe_etor sextend_maybe_etor) 103(decl multi uextend_maybe_etor (Type Value) Value) 104(extern extractor infallible uextend_maybe_etor uextend_maybe_etor) 105 106;; Match or Construct a possibly-`uextend`ed value. 107;; Gives the extended-to type and inner value when matching something that was 108;; extended, or the input value and its type when the value isn't an extension. 109;; Useful to write a single pattern that can match things that may or may not 110;; have undergone C's "usual arithmetic conversions". 111;; When generating values, extending to the same type is invalid CLIF, 112;; so this avoids doing that where there's no extension actually needed. 113(decl uextend_maybe (Type Value) Value) 114(extractor (uextend_maybe ty val) (uextend_maybe_etor ty val)) 115(rule 0 (uextend_maybe ty val) (uextend ty val)) 116(rule 1 (uextend_maybe ty val@(value_type ty)) val) 117 118;; Same as `uextend_maybe` above, just for `sextend`. 119(decl sextend_maybe (Type Value) Value) 120(extractor (sextend_maybe ty val) (sextend_maybe_etor ty val)) 121(rule 0 (sextend_maybe ty val) (sextend ty val)) 122(rule 1 (sextend_maybe ty val@(value_type ty)) val) 123