diff --git a/hercules_cg/src/cpu.rs b/hercules_cg/src/cpu.rs index 117e4f1da67b6e7ecce310c4cc2e6d04b21e2e02..8dfe06e7443372d45214a886d7e1b46d78545ab0 100644 --- a/hercules_cg/src/cpu.rs +++ b/hercules_cg/src/cpu.rs @@ -602,6 +602,20 @@ impl<'a> CPUContext<'a> { left.idx(), right.idx() )?, + DynamicConstant::Min(left, right) => write!( + body, + " %dc{} = call @llvm.umin.i64(i64%dc{},i64%dc{})\n", + dc.idx(), + left.idx(), + right.idx() + )?, + DynamicConstant::Max(left, right) => write!( + body, + " %dc{} = call @llvm.umax.i64(i64%dc{},i64%dc{})\n", + dc.idx(), + left.idx(), + right.idx() + )?, } } Ok(()) diff --git a/hercules_cg/src/rt.rs b/hercules_cg/src/rt.rs index 13370c4580a9365f0a9013b573e558133656d407..6e56ebc48d381108f4483411b4e497bed6aec8ed 100644 --- a/hercules_cg/src/rt.rs +++ b/hercules_cg/src/rt.rs @@ -469,6 +469,20 @@ impl<'a> RTContext<'a> { self.codegen_dynamic_constant(right, w)?; write!(w, ")")?; } + DynamicConstant::Min(left, right) => { + write!(w, "::core::cmp::min(")?; + self.codegen_dynamic_constant(left, w)?; + write!(w, ",")?; + self.codegen_dynamic_constant(right, w)?; + write!(w, ")")?; + } + DynamicConstant::Max(left, right) => { + write!(w, "::core::cmp::max(")?; + self.codegen_dynamic_constant(left, w)?; + write!(w, ",")?; + self.codegen_dynamic_constant(right, w)?; + write!(w, ")")?; + } } Ok(()) } diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index 4fd0cf0b11a55beb3320e4211b2c52f7c0e4e38d..ffa338b5a4169a1646b0ca0a582dba44777ffd12 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -1,3 +1,4 @@ +use std::cmp::{max, min}; use std::fmt::Write; use std::ops::Coroutine; use std::ops::CoroutineState; @@ -121,6 +122,8 @@ pub enum DynamicConstant { Mul(DynamicConstantID, DynamicConstantID), Div(DynamicConstantID, DynamicConstantID), Rem(DynamicConstantID, DynamicConstantID), + Min(DynamicConstantID, DynamicConstantID), + Max(DynamicConstantID, DynamicConstantID), } /* @@ -445,13 +448,17 @@ impl Module { | DynamicConstant::Sub(x, y) | DynamicConstant::Mul(x, y) | DynamicConstant::Div(x, y) - | DynamicConstant::Rem(x, y) => { + | DynamicConstant::Rem(x, y) + | DynamicConstant::Min(x, y) + | DynamicConstant::Max(x, y) => { match &self.dynamic_constants[dc_id.idx()] { DynamicConstant::Add(_, _) => write!(w, "+")?, DynamicConstant::Sub(_, _) => write!(w, "-")?, DynamicConstant::Mul(_, _) => write!(w, "*")?, DynamicConstant::Div(_, _) => write!(w, "/")?, DynamicConstant::Rem(_, _) => write!(w, "%")?, + DynamicConstant::Min(_, _) => write!(w, "min")?, + DynamicConstant::Max(_, _) => write!(w, "max")?, _ => (), } write!(w, "(")?; @@ -1014,6 +1021,14 @@ pub fn evaluate_dynamic_constant( DynamicConstant::Rem(left, right) => { Some(evaluate_dynamic_constant(left, dcs)? % evaluate_dynamic_constant(right, dcs)?) } + DynamicConstant::Min(left, right) => Some(min( + evaluate_dynamic_constant(left, dcs)?, + evaluate_dynamic_constant(right, dcs)?, + )), + DynamicConstant::Max(left, right) => Some(max( + evaluate_dynamic_constant(left, dcs)?, + evaluate_dynamic_constant(right, dcs)?, + )), } } diff --git a/hercules_ir/src/typecheck.rs b/hercules_ir/src/typecheck.rs index d6862c354199dc748797e47d4f663f898df24d7b..5a64e5771b6c8db1698c1471c5ce34fc4dcae323 100644 --- a/hercules_ir/src/typecheck.rs +++ b/hercules_ir/src/typecheck.rs @@ -193,7 +193,9 @@ fn typeflow( | DynamicConstant::Sub(x, y) | DynamicConstant::Mul(x, y) | DynamicConstant::Div(x, y) - | DynamicConstant::Rem(x, y) => { + | DynamicConstant::Rem(x, y) + | DynamicConstant::Min(x, y) + | DynamicConstant::Max(x, y) => { check_dynamic_constants(x, dynamic_constants, num_parameters) && check_dynamic_constants(y, dynamic_constants, num_parameters) } @@ -1328,5 +1330,27 @@ fn dyn_const_subst( reverse_dynamic_constant_map, ) } + DynamicConstant::Min(l, r) => { + let x = *l; + let y = *r; + let sx = dyn_const_subst(dynamic_constants, reverse_dynamic_constant_map, dc_args, x); + let sy = dyn_const_subst(dynamic_constants, reverse_dynamic_constant_map, dc_args, y); + intern_dyn_const( + DynamicConstant::Min(sx, sy), + dynamic_constants, + reverse_dynamic_constant_map, + ) + } + DynamicConstant::Max(l, r) => { + let x = *l; + let y = *r; + let sx = dyn_const_subst(dynamic_constants, reverse_dynamic_constant_map, dc_args, x); + let sy = dyn_const_subst(dynamic_constants, reverse_dynamic_constant_map, dc_args, y); + intern_dyn_const( + DynamicConstant::Max(sx, sy), + dynamic_constants, + reverse_dynamic_constant_map, + ) + } } } diff --git a/hercules_opt/src/utils.rs b/hercules_opt/src/utils.rs index 77fa1ff6525c575414b94e12905502b257ac1a12..2a4fd94c7d527147336553b0ade231967b67d004 100644 --- a/hercules_opt/src/utils.rs +++ b/hercules_opt/src/utils.rs @@ -130,6 +130,24 @@ pub(crate) fn substitute_dynamic_constants( dc_c } } + DynamicConstant::Min(left, right) => { + let new_left = substitute_dynamic_constants(dc_a, dc_b, left, edit); + let new_right = substitute_dynamic_constants(dc_a, dc_b, right, edit); + if new_left != left || new_right != right { + edit.add_dynamic_constant(DynamicConstant::Min(new_left, new_right)) + } else { + dc_c + } + } + DynamicConstant::Max(left, right) => { + let new_left = substitute_dynamic_constants(dc_a, dc_b, left, edit); + let new_right = substitute_dynamic_constants(dc_a, dc_b, right, edit); + if new_left != left || new_right != right { + edit.add_dynamic_constant(DynamicConstant::Max(new_left, new_right)) + } else { + dc_c + } + } } }