ISLE: remove all uses of argument polarity, and remove it from the language. (#4091)
This PR removes "argument polarity": the feature of ISLE extractors that lets them take inputs aside from the value to be matched. Cases that need this expressivity have been subsumed by #4072 with if-let clauses; we can now finally remove this misfeature of the language, which has caused significant confusion and has always felt like a bit of a hack. This PR (i) removes the feature from the ISLE compiler; (ii) removes it from the reference documentation; and (iii) refactors away all uses of the feature in our three existing backends written in ISLE.
This commit is contained in:
@@ -937,14 +937,18 @@
|
||||
|
||||
;; Detect specific integer values
|
||||
|
||||
(decl i64_nonequal (i64 i64) i64)
|
||||
(extern extractor i64_nonequal i64_nonequal (out in))
|
||||
(decl pure i64_nonequal (i64 i64) i64)
|
||||
(extern constructor i64_nonequal i64_nonequal)
|
||||
|
||||
(decl i64_nonzero (i64) i64)
|
||||
(extractor (i64_nonzero val) (i64_nonequal val <0))
|
||||
(decl pure i64_nonzero (i64) i64)
|
||||
(rule (i64_nonzero x)
|
||||
(if (i64_nonequal x 0))
|
||||
x)
|
||||
|
||||
(decl i64_not_neg1 (i64) i64)
|
||||
(extractor (i64_not_neg1 val) (i64_nonequal val <-1))
|
||||
(decl pure i64_not_neg1 (i64) i64)
|
||||
(rule (i64_not_neg1 x)
|
||||
(if (i64_nonequal x -1))
|
||||
x)
|
||||
|
||||
;; Integer type casts (with the rust `as` semantics).
|
||||
|
||||
@@ -1116,12 +1120,13 @@
|
||||
|
||||
;; Form the sum of two offset values, and check that the result is
|
||||
;; a valid `MemArg::Symbol` offset (i.e. is even and fits into i32).
|
||||
(decl memarg_symbol_offset_sum (i64 i32) i64)
|
||||
(extern extractor memarg_symbol_offset_sum memarg_symbol_offset_sum (in out))
|
||||
(decl pure memarg_symbol_offset_sum (i64 i64) i32)
|
||||
(extern constructor memarg_symbol_offset_sum memarg_symbol_offset_sum)
|
||||
|
||||
;; Likewise, but just check a single offset value.
|
||||
(decl memarg_symbol_offset (i32) i64)
|
||||
(extractor (memarg_symbol_offset offset) (memarg_symbol_offset_sum <0 offset))
|
||||
(decl pure memarg_symbol_offset (i64) i32)
|
||||
(rule (memarg_symbol_offset x)
|
||||
(memarg_symbol_offset_sum x 0))
|
||||
|
||||
;; Lower an address into a `MemArg`.
|
||||
|
||||
@@ -1130,29 +1135,33 @@
|
||||
(rule (lower_address flags addr (i64_from_offset offset))
|
||||
(memarg_reg_plus_off addr offset flags))
|
||||
|
||||
(rule (lower_address flags (def_inst (iadd x y)) (i64_from_offset 0))
|
||||
(rule (lower_address flags (iadd x y) (i64_from_offset 0))
|
||||
(memarg_reg_plus_reg x y flags))
|
||||
|
||||
(rule (lower_address flags
|
||||
(def_inst (symbol_value (symbol_value_data name (reloc_distance_near) offset)))
|
||||
(i64_from_offset (memarg_symbol_offset_sum <offset final_offset)))
|
||||
(symbol_value (symbol_value_data name (reloc_distance_near) sym_offset))
|
||||
(i64_from_offset offset))
|
||||
(if-let final_offset (memarg_symbol_offset_sum offset sym_offset))
|
||||
(memarg_symbol name final_offset flags))
|
||||
|
||||
|
||||
;; Test whether a `load` address will be lowered to a `MemArg::Symbol`.
|
||||
|
||||
(decl load_sym (Inst) Inst)
|
||||
(extractor (load_sym inst)
|
||||
(and inst
|
||||
(load _ (def_inst (symbol_value (symbol_value_data _ (reloc_distance_near) offset)))
|
||||
(i64_from_offset (memarg_symbol_offset_sum <offset _)))))
|
||||
|
||||
(decl uload16_sym (Inst) Inst)
|
||||
(extractor (uload16_sym inst)
|
||||
(and inst
|
||||
(uload16 _ (def_inst (symbol_value (symbol_value_data _ (reloc_distance_near) offset)))
|
||||
(i64_from_offset (memarg_symbol_offset_sum <offset _)))))
|
||||
(decl pure load_sym (Inst) Inst)
|
||||
(rule (load_sym inst)
|
||||
(if-let (load _ (symbol_value (symbol_value_data _ (reloc_distance_near) sym_offset))
|
||||
(i64_from_offset load_offset))
|
||||
inst)
|
||||
(if (memarg_symbol_offset_sum sym_offset load_offset))
|
||||
inst)
|
||||
|
||||
(decl pure uload16_sym (Inst) Inst)
|
||||
(rule (uload16_sym inst)
|
||||
(if-let (uload16 _ (symbol_value (symbol_value_data _ (reloc_distance_near) sym_offset))
|
||||
(i64_from_offset load_offset))
|
||||
inst)
|
||||
(if (memarg_symbol_offset_sum sym_offset load_offset))
|
||||
inst)
|
||||
|
||||
;; Helpers for stack-slot addresses ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -1170,11 +1179,11 @@
|
||||
|
||||
;; A value that is the result of a sign-extend from a 32-bit value.
|
||||
(decl sext32_value (Value) Value)
|
||||
(extractor (sext32_value x) (def_inst (sextend (and x (value_type $I32)))))
|
||||
(extractor (sext32_value x) (sextend (and x (value_type $I32))))
|
||||
|
||||
;; A value that is the result of a zero-extend from a 32-bit value.
|
||||
(decl zext32_value (Value) Value)
|
||||
(extractor (zext32_value x) (def_inst (uextend (and x (value_type $I32)))))
|
||||
(extractor (zext32_value x) (uextend (and x (value_type $I32))))
|
||||
|
||||
|
||||
;; Helpers for sinkable loads ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1777,8 +1786,8 @@
|
||||
;; Similarly, because we cannot allocate temp registers, if an instruction
|
||||
;; requires matching source and destination registers, this needs to be handled
|
||||
;; by the user. Another helper to verify that constraint.
|
||||
(decl same_reg (WritableReg) Reg)
|
||||
(extern extractor same_reg same_reg (in))
|
||||
(decl pure same_reg (WritableReg Reg) Reg)
|
||||
(extern constructor same_reg same_reg)
|
||||
|
||||
;; Push a `MInst.AluRRR` instruction to a sequence.
|
||||
(decl push_alu_reg (VecMInstBuilder ALUOp WritableReg Reg Reg) Reg)
|
||||
@@ -1788,7 +1797,8 @@
|
||||
|
||||
;; Push a `MInst.AluRUImm32Shifted` instruction to a sequence.
|
||||
(decl push_alu_uimm32shifted (VecMInstBuilder ALUOp WritableReg Reg UImm32Shifted) Reg)
|
||||
(rule (push_alu_uimm32shifted ib op (real_reg dst) (same_reg <dst) imm)
|
||||
(rule (push_alu_uimm32shifted ib op (real_reg dst) r imm)
|
||||
(if (same_reg dst r))
|
||||
(let ((_ Unit (inst_builder_push ib (MInst.AluRUImm32Shifted op dst imm))))
|
||||
dst))
|
||||
|
||||
@@ -1801,7 +1811,8 @@
|
||||
|
||||
;; Push a `MInst.RxSBG` instruction to a sequence.
|
||||
(decl push_rxsbg (VecMInstBuilder RxSBGOp WritableReg Reg Reg u8 u8 i8) Reg)
|
||||
(rule (push_rxsbg ib op (real_reg dst) (same_reg <dst) src start_bit end_bit rotate_amt)
|
||||
(rule (push_rxsbg ib op (real_reg dst) r src start_bit end_bit rotate_amt)
|
||||
(if (same_reg dst r))
|
||||
(let ((_ Unit (inst_builder_push ib
|
||||
(MInst.RxSBG op dst src start_bit end_bit rotate_amt))))
|
||||
dst))
|
||||
@@ -2088,9 +2099,9 @@
|
||||
(rule (emit_put_in_reg_zext32 dst (and (value_type (fits_in_16 ty)) (sinkable_load load)))
|
||||
(emit_zext32_mem dst ty (sink_load load)))
|
||||
(rule (emit_put_in_reg_zext32 dst val @ (value_type (fits_in_16 ty)))
|
||||
(emit_zext32_reg dst ty (put_in_reg val)))
|
||||
(emit_zext32_reg dst ty val))
|
||||
(rule (emit_put_in_reg_zext32 dst val @ (value_type (ty_32_or_64 ty)))
|
||||
(emit_mov ty dst (put_in_reg val)))
|
||||
(emit_mov ty dst val))
|
||||
|
||||
;; Place `Value` into destination, sign-extending to 32 bits if smaller. (Non-SSA form.)
|
||||
(decl emit_put_in_reg_sext32 (WritableReg Value) Unit)
|
||||
@@ -2099,9 +2110,9 @@
|
||||
(rule (emit_put_in_reg_sext32 dst (and (value_type (fits_in_16 ty)) (sinkable_load load)))
|
||||
(emit_sext32_mem dst ty (sink_load load)))
|
||||
(rule (emit_put_in_reg_sext32 dst val @ (value_type (fits_in_16 ty)))
|
||||
(emit_sext32_reg dst ty (put_in_reg val)))
|
||||
(emit_sext32_reg dst ty val))
|
||||
(rule (emit_put_in_reg_sext32 dst val @ (value_type (ty_32_or_64 ty)))
|
||||
(emit_mov ty dst (put_in_reg val)))
|
||||
(emit_mov ty dst val))
|
||||
|
||||
;; Place `Value` into destination, zero-extending to 64 bits if smaller. (Non-SSA form.)
|
||||
(decl emit_put_in_reg_zext64 (WritableReg Value) Unit)
|
||||
@@ -2110,9 +2121,9 @@
|
||||
(rule (emit_put_in_reg_zext64 dst (and (value_type (gpr32_ty ty)) (sinkable_load load)))
|
||||
(emit_zext64_mem dst ty (sink_load load)))
|
||||
(rule (emit_put_in_reg_zext64 dst val @ (value_type (gpr32_ty ty)))
|
||||
(emit_zext64_reg dst ty (put_in_reg val)))
|
||||
(emit_zext64_reg dst ty val))
|
||||
(rule (emit_put_in_reg_zext64 dst val @ (value_type (gpr64_ty ty)))
|
||||
(emit_mov ty dst (put_in_reg val)))
|
||||
(emit_mov ty dst val))
|
||||
|
||||
;; Place `Value` into destination, sign-extending to 64 bits if smaller. (Non-SSA form.)
|
||||
(decl emit_put_in_reg_sext64 (WritableReg Value) Unit)
|
||||
@@ -2121,9 +2132,9 @@
|
||||
(rule (emit_put_in_reg_sext64 dst (and (value_type (gpr32_ty ty)) (sinkable_load load)))
|
||||
(emit_sext64_mem dst ty (sink_load load)))
|
||||
(rule (emit_put_in_reg_sext64 dst val @ (value_type (gpr32_ty ty)))
|
||||
(emit_sext64_reg dst ty (put_in_reg val)))
|
||||
(emit_sext64_reg dst ty val))
|
||||
(rule (emit_put_in_reg_sext64 dst val @ (value_type (gpr64_ty ty)))
|
||||
(emit_mov ty dst (put_in_reg val)))
|
||||
(emit_mov ty dst val))
|
||||
|
||||
;; Place `Value` into a register, zero-extending to 32 bits if smaller.
|
||||
(decl put_in_reg_zext32 (Value) Reg)
|
||||
@@ -2132,9 +2143,9 @@
|
||||
(rule (put_in_reg_zext32 (and (value_type (fits_in_16 ty)) (sinkable_load load)))
|
||||
(zext32_mem ty (sink_load load)))
|
||||
(rule (put_in_reg_zext32 val @ (value_type (fits_in_16 ty)))
|
||||
(zext32_reg ty (put_in_reg val)))
|
||||
(zext32_reg ty val))
|
||||
(rule (put_in_reg_zext32 val @ (value_type (ty_32_or_64 _ty)))
|
||||
(put_in_reg val))
|
||||
val)
|
||||
|
||||
;; Place `Value` into a register, sign-extending to 32 bits if smaller.
|
||||
(decl put_in_reg_sext32 (Value) Reg)
|
||||
@@ -2143,9 +2154,9 @@
|
||||
(rule (put_in_reg_sext32 (and (value_type (fits_in_16 ty)) (sinkable_load load)))
|
||||
(sext32_mem ty (sink_load load)))
|
||||
(rule (put_in_reg_sext32 val @ (value_type (fits_in_16 ty)))
|
||||
(sext32_reg ty (put_in_reg val)))
|
||||
(sext32_reg ty val))
|
||||
(rule (put_in_reg_sext32 val @ (value_type (ty_32_or_64 _ty)))
|
||||
(put_in_reg val))
|
||||
val)
|
||||
|
||||
;; Place `Value` into a register, zero-extending to 64 bits if smaller.
|
||||
(decl put_in_reg_zext64 (Value) Reg)
|
||||
@@ -2154,9 +2165,9 @@
|
||||
(rule (put_in_reg_zext64 (and (value_type (gpr32_ty ty)) (sinkable_load load)))
|
||||
(zext64_mem ty (sink_load load)))
|
||||
(rule (put_in_reg_zext64 val @ (value_type (gpr32_ty ty)))
|
||||
(zext64_reg ty (put_in_reg val)))
|
||||
(zext64_reg ty val))
|
||||
(rule (put_in_reg_zext64 val @ (value_type (gpr64_ty ty)))
|
||||
(put_in_reg val))
|
||||
val)
|
||||
|
||||
;; Place `Value` into a register, sign-extending to 64 bits if smaller.
|
||||
(decl put_in_reg_sext64 (Value) Reg)
|
||||
@@ -2165,9 +2176,9 @@
|
||||
(rule (put_in_reg_sext64 (and (value_type (gpr32_ty ty)) (sinkable_load load)))
|
||||
(sext64_mem ty (sink_load load)))
|
||||
(rule (put_in_reg_sext64 val @ (value_type (gpr32_ty ty)))
|
||||
(sext64_reg ty (put_in_reg val)))
|
||||
(sext64_reg ty val))
|
||||
(rule (put_in_reg_sext64 val @ (value_type (gpr64_ty ty)))
|
||||
(put_in_reg val))
|
||||
val)
|
||||
|
||||
;; Place `Value` into the low half of a register pair, zero-extending
|
||||
;; to 32 bits if smaller. The high half is taken from the input.
|
||||
|
||||
@@ -341,7 +341,9 @@
|
||||
;; If the `avoid_div_traps` flag is true, we perform the check explicitly.
|
||||
;; This still can be omittted if the divisor is a non-zero immediate.
|
||||
(decl zero_divisor_check_needed (Value) bool)
|
||||
(rule (zero_divisor_check_needed (i64_from_value (i64_nonzero _))) $false)
|
||||
(rule (zero_divisor_check_needed (i64_from_value x))
|
||||
(if (i64_nonzero x))
|
||||
$false)
|
||||
(rule (zero_divisor_check_needed (value_type (allow_div_traps))) $false)
|
||||
(rule (zero_divisor_check_needed _) $true)
|
||||
|
||||
@@ -422,7 +424,9 @@
|
||||
;; minimum (signed) integer value is divided by -1, so if the divisor
|
||||
;; is any immediate different from -1, the check can be omitted.
|
||||
(decl div_overflow_check_needed (Value) bool)
|
||||
(rule (div_overflow_check_needed (i64_from_value (i64_not_neg1 _))) $false)
|
||||
(rule (div_overflow_check_needed (i64_from_value x))
|
||||
(if (i64_not_neg1 x))
|
||||
$false)
|
||||
(rule (div_overflow_check_needed _) $true)
|
||||
|
||||
;; Perform the integer-overflow check if necessary. This implements:
|
||||
@@ -1168,7 +1172,8 @@
|
||||
|
||||
;; Load the address of a symbol, target reachable via PC-relative instruction.
|
||||
(rule (lower (symbol_value (symbol_value_data name (reloc_distance_near)
|
||||
(memarg_symbol_offset offset))))
|
||||
off)))
|
||||
(if-let offset (memarg_symbol_offset off))
|
||||
(load_addr (memarg_symbol name offset (memflags_trusted))))
|
||||
|
||||
;; Load the address of a symbol, general case.
|
||||
@@ -1984,14 +1989,16 @@
|
||||
;; Note that the ISA only provides instructions with a PC-relative memory
|
||||
;; address here, so we need to check whether the sinkable load matches this.
|
||||
(rule (icmpu_val $true x @ (value_type (fits_in_64 ty))
|
||||
(sinkable_load_16 (load_sym y)))
|
||||
(sinkable_load_16 ld))
|
||||
(if-let y (load_sym ld))
|
||||
(icmpu_mem_zext16 (ty_ext32 ty) (put_in_reg_zext32 x) (sink_load y)))
|
||||
|
||||
;; Compare (unsigned) a register and zero-extended memory.
|
||||
;; Note that the ISA only provides instructions with a PC-relative memory
|
||||
;; address here, so we need to check whether the sinkable load matches this.
|
||||
(rule (icmpu_val $true x @ (value_type (fits_in_64 ty))
|
||||
(sinkable_uload16 (uload16_sym y)))
|
||||
(sinkable_uload16 ld))
|
||||
(if-let y (uload16_sym ld))
|
||||
(icmpu_mem_zext16 ty x (sink_uload16 y)))
|
||||
(rule (icmpu_val $true x @ (value_type (fits_in_64 ty)) (sinkable_uload32 y))
|
||||
(icmpu_mem_zext32 ty x (sink_uload32 y)))
|
||||
|
||||
@@ -486,9 +486,9 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn same_reg(&mut self, src: Reg, dst: WritableReg) -> Option<()> {
|
||||
fn same_reg(&mut self, dst: WritableReg, src: Reg) -> Option<Reg> {
|
||||
if dst.to_reg() == src {
|
||||
Some(())
|
||||
Some(src)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
src/clif.isle 443b34b797fc8ace
|
||||
src/prelude.isle a7915a6b88310eb5
|
||||
src/isa/s390x/inst.isle 8218bd9e8556446b
|
||||
src/isa/s390x/lower.isle 6a8de81f8dc4e568
|
||||
src/isa/s390x/inst.isle 36c2500563cdd4e6
|
||||
src/isa/s390x/lower.isle e5c946ab8a265b77
|
||||
|
||||
2199
cranelift/codegen/src/isa/s390x/lower/isle/generated_code.rs
generated
2199
cranelift/codegen/src/isa/s390x/lower/isle/generated_code.rs
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user