Permalink
Browse files

Constant folding for real values

  • Loading branch information...
1 parent 05d68f7 commit 23c9b518da8df4a08e7f368d06307161b53281e1 @nickg committed Jun 10, 2012
Showing with 132 additions and 36 deletions.
  1. +0 −1 lib/std/standard.vhd
  2. +4 −2 src/sem.c
  3. +90 −32 src/simp.c
  4. +2 −0 src/tree.c
  5. +8 −1 src/type.c
  6. +10 −0 test/simp/cfold.vhd
  7. +18 −0 test/test_simp.c
View
@@ -6,7 +6,6 @@ package STANDARD is
type INTEGER;
type STRING;
- type REAL;
type BOOLEAN is (FALSE, TRUE);
View
@@ -793,6 +793,7 @@ static bool sem_check_subtype(tree_t t, type_t type, type_t *pbase)
case T_CARRAY:
case T_SUBTYPE:
case T_INTEGER:
+ case T_REAL:
for (unsigned i = 0; i < type_dims(base); i++)
type_add_dim(type, type_dim(base, i));
break;
@@ -1192,13 +1193,15 @@ static bool sem_check_type_decl(tree_t t)
case T_INTEGER:
case T_PHYSICAL:
+ case T_REAL:
{
range_t r = type_dim(type, 0);
// Check the range expressions as if they were INTEGERs
// when there is no base type
type_set_push();
- //type_set_add(sem_std_type("INTEGER"));
+ type_set_add(sem_std_type(type_kind(type) == T_REAL
+ ? "REAL" : "INTEGER"));
bool ok = sem_check(r.left) && sem_check(r.right);
type_set_pop();
@@ -2252,7 +2255,6 @@ static bool sem_resolve_overload(tree_t t, tree_t *pick, int *matches,
tree_set_type(t, type_universal_int());
break;
case T_REAL:
- printf("here!!\n");
tree_set_type(t, type_universal_real());
break;
default:
View
@@ -34,11 +34,21 @@ static int errors = 0;
static tree_t simp_tree(tree_t t, void *context);
-static bool folded_num(tree_t t, literal_t *l)
+static bool folded_int(tree_t t, literal_t *l)
{
if (tree_kind(t) == T_LITERAL) {
*l = tree_literal(t);
- return true;
+ return (l->kind == L_INT);
+ }
+ else
+ return false;
+}
+
+static bool folded_real(tree_t t, literal_t *l)
+{
+ if (tree_kind(t) == T_LITERAL) {
+ *l = tree_literal(t);
+ return (l->kind == L_REAL);
}
else
return false;
@@ -66,12 +76,12 @@ static bool folded_agg(tree_t t)
literal_t dummy;
switch (a.kind) {
case A_NAMED:
- if (!folded_num(a.name, &dummy))
+ if (!folded_int(a.name, &dummy))
return false;
break;
case A_RANGE:
- if (!folded_num(a.range.left, &dummy)
- || !folded_num(a.range.right, &dummy))
+ if (!folded_int(a.range.left, &dummy)
+ || !folded_int(a.range.right, &dummy))
return false;
break;
default:
@@ -101,6 +111,23 @@ static tree_t get_int_lit(tree_t t, int64_t i)
return f;
}
+static tree_t get_real_lit(tree_t t, double r)
+{
+ tree_t fdecl = tree_ref(t);
+ assert(tree_kind(fdecl) == T_FUNC_DECL);
+
+ literal_t l;
+ l.kind = L_REAL;
+ l.r = r;
+
+ tree_t f = tree_new(T_LITERAL);
+ tree_set_loc(f, tree_loc(t));
+ tree_set_literal(f, l);
+ tree_set_type(f, tree_type(t));
+
+ return f;
+}
+
static tree_t get_bool_lit(tree_t t, bool v)
{
tree_t fdecl = tree_ref(t);
@@ -142,7 +169,46 @@ static tree_t simp_fcall_log(tree_t t, ident_t builtin, bool *args)
return t;
}
-static tree_t simp_fcall_num(tree_t t, ident_t builtin, literal_t *args)
+static tree_t simp_fcall_real(tree_t t, ident_t builtin, literal_t *args)
+{
+ const int lkind = args[0].kind; // Assume all types checked same
+ assert(lkind == L_REAL);
+
+ if (icmp(builtin, "mul")) {
+ return get_real_lit(t, args[0].r * args[1].r);
+ }
+ else if (icmp(builtin, "div")) {
+ return get_real_lit(t, args[0].r / args[1].r);
+ }
+ else if (icmp(builtin, "add")) {
+ return get_real_lit(t, args[0].r + args[1].r);
+ }
+ else if (icmp(builtin, "sub")) {
+ return get_real_lit(t, args[0].r - args[1].r);
+ }
+ else if (icmp(builtin, "neg")) {
+ return get_real_lit(t, -args[0].r);
+ }
+ else if (icmp(builtin, "identity")) {
+ return get_real_lit(t, args[0].r);
+ }
+ else if (icmp(builtin, "eq")) {
+ return get_bool_lit(t, args[0].r == args[1].r);
+ }
+ else if (icmp(builtin, "neq")) {
+ return get_bool_lit(t, args[0].r != args[1].r);
+ }
+ else if (icmp(builtin, "gt")) {
+ return get_bool_lit(t, args[0].r > args[1].r);
+ }
+ else if (icmp(builtin, "lt")) {
+ return get_bool_lit(t, args[0].r < args[1].r);
+ }
+ else
+ return t;
+}
+
+static tree_t simp_fcall_int(tree_t t, ident_t builtin, literal_t *args)
{
const int lkind = args[0].kind; // Assume all types checked same
assert(lkind == L_INT);
@@ -166,28 +232,16 @@ static tree_t simp_fcall_num(tree_t t, ident_t builtin, literal_t *args)
return get_int_lit(t, args[0].i);
}
else if (icmp(builtin, "eq")) {
- if (args[0].kind == L_INT && args[1].kind == L_INT)
- return get_bool_lit(t, args[0].i == args[1].i);
- else
- assert(false);
+ return get_bool_lit(t, args[0].i == args[1].i);
}
else if (icmp(builtin, "neq")) {
- if (args[0].kind == L_INT && args[1].kind == L_INT)
- return get_bool_lit(t, args[0].i != args[1].i);
- else
- assert(false);
+ return get_bool_lit(t, args[0].i != args[1].i);
}
else if (icmp(builtin, "gt")) {
- if (args[0].kind == L_INT && args[1].kind == L_INT)
- return get_bool_lit(t, args[0].i > args[1].i);
- else
- assert(false);
+ return get_bool_lit(t, args[0].i > args[1].i);
}
else if (icmp(builtin, "lt")) {
- if (args[0].kind == L_INT && args[1].kind == L_INT)
- return get_bool_lit(t, args[0].i < args[1].i);
- else
- assert(false);
+ return get_bool_lit(t, args[0].i < args[1].i);
}
else
return t;
@@ -245,25 +299,29 @@ static tree_t simp_fcall(tree_t t)
if (tree_params(t) > MAX_BUILTIN_ARGS)
return t;
- bool can_fold_num = true;
- bool can_fold_log = true;
- bool can_fold_agg = true;
+ bool can_fold_int = true;
+ bool can_fold_log = true;
+ bool can_fold_agg = true;
+ bool can_fold_real = true;
literal_t largs[MAX_BUILTIN_ARGS];
bool bargs[MAX_BUILTIN_ARGS];
for (unsigned i = 0; i < tree_params(t); i++) {
param_t p = tree_param(t, i);
assert(p.kind == P_POS);
- can_fold_num = can_fold_num && folded_num(p.value, &largs[i]);
- can_fold_log = can_fold_log && folded_bool(p.value, &bargs[i]);
- can_fold_agg = can_fold_agg && folded_agg(p.value);
+ can_fold_int = can_fold_int && folded_int(p.value, &largs[i]);
+ can_fold_log = can_fold_log && folded_bool(p.value, &bargs[i]);
+ can_fold_agg = can_fold_agg && folded_agg(p.value);
+ can_fold_real = can_fold_real && folded_real(p.value, &largs[i]);
}
- if (can_fold_num)
- return simp_fcall_num(t, builtin, largs);
+ if (can_fold_int)
+ return simp_fcall_int(t, builtin, largs);
else if (can_fold_log)
return simp_fcall_log(t, builtin, bargs);
else if (can_fold_agg)
return simp_fcall_agg(t, builtin);
+ else if (can_fold_real)
+ return simp_fcall_real(t, builtin, largs);
else
return t;
}
@@ -345,7 +403,7 @@ static tree_t simp_array_ref(tree_t t)
for (unsigned i = 0; i < tree_params(t); i++) {
param_t p = tree_param(t, i);
assert(p.kind == P_POS);
- can_fold = can_fold && folded_num(p.value, &indexes[i]);
+ can_fold = can_fold && folded_int(p.value, &indexes[i]);
}
if (!can_fold)
@@ -662,7 +720,7 @@ static tree_t simp_cassign(tree_t t)
static tree_t simp_check_bounds(tree_t i, int64_t low, int64_t high)
{
literal_t folded;
- if (folded_num(i, &folded)) {
+ if (folded_int(i, &folded)) {
if (folded.i < low || folded.i > high)
simp_error(i, "index out of bounds");
}
View
@@ -1179,6 +1179,7 @@ static unsigned tree_visit_type(type_t type,
switch (type_kind(type)) {
case T_SUBTYPE:
case T_INTEGER:
+ case T_REAL:
case T_PHYSICAL:
case T_CARRAY:
for (unsigned i = 0; i < type_dims(type); i++) {
@@ -2175,6 +2176,7 @@ static tree_t tree_rewrite_aux(tree_t t, struct rewrite_ctx *ctx)
if (HAS_TYPE(t) && (t->type != NULL)) {
switch (type_kind(t->type)) {
case T_INTEGER:
+ case T_REAL:
case T_SUBTYPE:
case T_PHYSICAL:
case T_CARRAY:
View
@@ -43,7 +43,7 @@ struct type {
};
union {
type_t result; // T_FUNC
- tree_t resolution; // T_INTEGER, T_SUBTYPE
+ tree_t resolution; // T_SUBTYPE
};
union {
struct { // T_ENUM
@@ -157,6 +157,13 @@ bool type_eq(type_t a, type_t b)
&& (type_ident(a) == uint_i || type_ident(b) == uint_i))
return true;
+ // Universal real type is equal to any other real type
+ type_t universal_real = type_universal_real();
+ ident_t ureal_i = type_ident(universal_real);
+ if (type_kind(a) == T_REAL
+ && (type_ident(a) == ureal_i || type_ident(b) == ureal_i))
+ return true;
+
// XXX: this is not quite right as structurally equivalent types
// may be declared in different scopes with the same name but
// shouldn't compare equal
View
@@ -70,4 +70,14 @@ begin
a := (5 => 1, 6 => 2, 7 => 3); -- Error
end process;
+ process is
+ variable r : real;
+ variable b : boolean;
+ begin
+ r := 1.0 + 0.0;
+ r := 1.5 * 4.0;
+ r := 2.0 / 2.0;
+ b := 4.6 > 1.2;
+ end process;
+
end architecture;
View
@@ -66,6 +66,18 @@ static bool folded_i(tree_t t, int64_t i)
return l.i == i;
}
+static bool folded_r(tree_t t, double r)
+{
+ if (tree_kind(t) != T_LITERAL)
+ return false;
+
+ literal_t l = tree_literal(t);
+ if (l.kind != L_REAL)
+ return false;
+
+ return l.r == r;
+}
+
static bool folded_b(tree_t t, bool b)
{
if (tree_kind(t) != T_REF)
@@ -159,6 +171,12 @@ START_TEST(test_cfold)
fail_unless(tree_kind(s) == T_BLOCK);
fail_unless(tree_stmts(s) == 2);
+ p = tree_stmt(a, 3);
+ fail_unless(folded_r(tree_value(tree_stmt(p, 0)), 1.0));
+ fail_unless(folded_r(tree_value(tree_stmt(p, 1)), 6.0));
+ fail_unless(folded_r(tree_value(tree_stmt(p, 2)), 1.0));
+ fail_unless(folded_b(tree_value(tree_stmt(p, 3)), true));
+
fail_unless(simplify_errors() == (sizeof(expect) / sizeof(error_t)) - 1);
}
END_TEST

0 comments on commit 23c9b51

Please sign in to comment.