|
4957 | 4957 | (produces_flags_opportunistic_def producer sum_value) |
4958 | 4958 | (Cond.Hs)))) |
4959 | 4959 |
|
| 4960 | +;; Use of the flags output of `umul_overflow`/`smul_overflow` can produce a |
| 4961 | +;; `Cond` and give an opportunistic def of the other output. The multiply does |
| 4962 | +;; not set the condition flags; the overflow is detected by comparing the |
| 4963 | +;; product against itself extended from the original type (or, for 64-bit |
| 4964 | +;; values, by comparing the high half of the product against zero). Hence the |
| 4965 | +;; `ProducesFlagsOpportunisticDef2` chains for the narrow cases. For 64-bit |
| 4966 | +;; multiplies, the low product and overflow flag are lowered independently, |
| 4967 | +;; since the lowerings have no overlap/shared computation. |
| 4968 | + |
| 4969 | +;; madd out, a_uxt, b_uxt |
| 4970 | +;; cmp out, out, uxt{b,h} |
| 4971 | +(rule 5 |
| 4972 | + (is_nonzero |
| 4973 | + (second_result umul @ (umul_overflow (fits_in_16 ty) a b))) |
| 4974 | + (if-let (first_result prod_value) umul) |
| 4975 | + (let ((a_uext Reg (put_in_reg_zext32 a)) |
| 4976 | + (b_uext Reg (put_in_reg_zext32 b)) |
| 4977 | + (dst WritableReg (temp_writable_reg $I64)) |
| 4978 | + (producer ProducesFlags |
| 4979 | + (produces_flags_opportunistic_def2 |
| 4980 | + (MInst.AluRRRR (ALUOp3.MAdd) (operand_size ty) dst a_uext b_uext (zero_reg)) |
| 4981 | + dst |
| 4982 | + prod_value |
| 4983 | + (MInst.AluRRRExtend (ALUOp.SubS) (OperandSize.Size32) |
| 4984 | + (writable_zero_reg) dst dst |
| 4985 | + (lower_extend_op ty (ArgumentExtension.Uext)))))) |
| 4986 | + (CondResult.Cond producer (Cond.Ne)))) |
| 4987 | + |
| 4988 | +;; umaddl out, a, b |
| 4989 | +;; cmp out, out, uxtw |
| 4990 | +(rule 6 |
| 4991 | + (is_nonzero |
| 4992 | + (second_result umul @ (umul_overflow $I32 a b))) |
| 4993 | + (if-let (first_result prod_value) umul) |
| 4994 | + (let ((dst WritableReg (temp_writable_reg $I64)) |
| 4995 | + (producer ProducesFlags |
| 4996 | + (produces_flags_opportunistic_def2 |
| 4997 | + (MInst.AluRRRR (ALUOp3.UMAddL) (operand_size $I32) dst a b (zero_reg)) |
| 4998 | + dst |
| 4999 | + prod_value |
| 5000 | + (MInst.AluRRRExtend (ALUOp.SubS) (OperandSize.Size64) |
| 5001 | + (writable_zero_reg) dst dst |
| 5002 | + (ExtendOp.UXTW))))) |
| 5003 | + (CondResult.Cond producer (Cond.Ne)))) |
| 5004 | + |
| 5005 | +;; umulh tmp, a, b |
| 5006 | +;; cmp tmp, #0 |
| 5007 | +(rule 7 |
| 5008 | + (is_nonzero |
| 5009 | + (second_result umul @ (umul_overflow $I64 a b))) |
| 5010 | + (let ((tmp Reg (umulh $I64 a b)) |
| 5011 | + (producer ProducesFlags (cmp64_imm tmp (u8_into_imm12 0)))) |
| 5012 | + (CondResult.Cond producer (Cond.Ne)))) |
| 5013 | + |
| 5014 | +;; madd out, a_sxt, b_sxt |
| 5015 | +;; cmp out, out, sxt{b,h} |
| 5016 | +(rule 8 |
| 5017 | + (is_nonzero |
| 5018 | + (second_result smul @ (smul_overflow (fits_in_16 ty) a b))) |
| 5019 | + (if-let (first_result prod_value) smul) |
| 5020 | + (let ((a_sext Reg (put_in_reg_sext32 a)) |
| 5021 | + (b_sext Reg (put_in_reg_sext32 b)) |
| 5022 | + (dst WritableReg (temp_writable_reg $I64)) |
| 5023 | + (producer ProducesFlags |
| 5024 | + (produces_flags_opportunistic_def2 |
| 5025 | + (MInst.AluRRRR (ALUOp3.MAdd) (operand_size ty) dst a_sext b_sext (zero_reg)) |
| 5026 | + dst |
| 5027 | + prod_value |
| 5028 | + (MInst.AluRRRExtend (ALUOp.SubS) (OperandSize.Size32) |
| 5029 | + (writable_zero_reg) dst dst |
| 5030 | + (lower_extend_op ty (ArgumentExtension.Sext)))))) |
| 5031 | + (CondResult.Cond producer (Cond.Ne)))) |
| 5032 | + |
| 5033 | +;; smaddl out, a, b |
| 5034 | +;; cmp out, out, sxtw |
| 5035 | +(rule 9 |
| 5036 | + (is_nonzero |
| 5037 | + (second_result smul @ (smul_overflow $I32 a b))) |
| 5038 | + (if-let (first_result prod_value) smul) |
| 5039 | + (let ((dst WritableReg (temp_writable_reg $I64)) |
| 5040 | + (producer ProducesFlags |
| 5041 | + (produces_flags_opportunistic_def2 |
| 5042 | + (MInst.AluRRRR (ALUOp3.SMAddL) (operand_size $I32) dst a b (zero_reg)) |
| 5043 | + dst |
| 5044 | + prod_value |
| 5045 | + (MInst.AluRRRExtend (ALUOp.SubS) (OperandSize.Size64) |
| 5046 | + (writable_zero_reg) dst dst |
| 5047 | + (ExtendOp.SXTW))))) |
| 5048 | + (CondResult.Cond producer (Cond.Ne)))) |
| 5049 | + |
| 5050 | +;; smulh tmp, a, b |
| 5051 | +;; cmp tmp, out, asr #63 |
| 5052 | +(rule 10 |
| 5053 | + (is_nonzero |
| 5054 | + (second_result smul @ (smul_overflow $I64 a b))) |
| 5055 | + (if-let (first_result prod_value) smul) |
| 5056 | + (let ((prod Reg (put_in_reg prod_value)) |
| 5057 | + (tmp Reg (smulh $I64 a b)) |
| 5058 | + (producer ProducesFlags |
| 5059 | + (cmp_rr_shift_asr (OperandSize.Size64) tmp prod 63))) |
| 5060 | + (CondResult.Cond producer (Cond.Ne)))) |
| 5061 | + |
4960 | 5062 | (attr emit_icmp (veri chain)) |
4961 | 5063 | (decl emit_icmp (IntCC Value Value) CondResult) |
4962 | 5064 |
|
|
0 commit comments