Skip to content

Commit 5e145e4

Browse files
authored
Merge pull request #5940 from tautschnig/fix-5930
Support ==,!=,<,<=,>,>= over vectors
2 parents 3064855 + 316ae8b commit 5e145e4

File tree

5 files changed

+108
-14
lines changed

5 files changed

+108
-14
lines changed

regression/cbmc/gcc_vector1/main.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ int main()
105105
assert(z.members[2]==-x.members[2]);
106106
assert(z.members[3]==-x.members[3]);
107107

108+
// Boolean operators on vectors
109+
z = x;
110+
y.v = z.v == x.v;
111+
assert(y.members[0]);
112+
assert(y.members[1]);
113+
assert(y.members[2]);
114+
assert(y.members[3]);
115+
116+
y.v = x.v <= z.v;
117+
assert(y.members[0]);
118+
assert(y.members[1]);
119+
assert(y.members[2]);
120+
assert(y.members[3]);
121+
108122
// build vector with typecast
109123
z.v=(v4si){ 0, 1, 2, 3 };
110124
assert(z.members[0]==0 && z.members[1]==1 && z.members[2]==2 && z.members[3]==3);

src/ansi-c/c_typecheck_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class c_typecheck_baset:
182182
virtual void typecheck_expr_member(exprt &expr);
183183
virtual void typecheck_expr_ptrmember(exprt &expr);
184184
virtual void typecheck_expr_rel(binary_relation_exprt &expr);
185-
virtual void typecheck_expr_rel_vector(binary_relation_exprt &expr);
185+
virtual void typecheck_expr_rel_vector(binary_exprt &expr);
186186
virtual void adjust_float_rel(binary_relation_exprt &);
187187
static void add_rounding_mode(exprt &);
188188
virtual void typecheck_expr_index(exprt &expr);

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,18 +1417,12 @@ void c_typecheck_baset::typecheck_expr_rel(
14171417
throw 0;
14181418
}
14191419

1420-
void c_typecheck_baset::typecheck_expr_rel_vector(
1421-
binary_relation_exprt &expr)
1420+
void c_typecheck_baset::typecheck_expr_rel_vector(binary_exprt &expr)
14221421
{
1423-
exprt &op0=expr.op0();
1424-
exprt &op1=expr.op1();
1422+
const typet &o_type0 = as_const(expr).op0().type();
1423+
const typet &o_type1 = as_const(expr).op1().type();
14251424

1426-
const typet o_type0 = op0.type();
1427-
const typet o_type1 = op1.type();
1428-
1429-
if(
1430-
o_type0.id() != ID_vector || o_type1.id() != ID_vector ||
1431-
o_type0.subtype() != o_type1.subtype())
1425+
if(o_type0.id() != ID_vector || o_type0 != o_type1)
14321426
{
14331427
error().source_location = expr.source_location();
14341428
error() << "vector operator '" << expr.id() << "' not defined for types '"
@@ -1437,9 +1431,18 @@ void c_typecheck_baset::typecheck_expr_rel_vector(
14371431
throw 0;
14381432
}
14391433

1440-
// Comparisons between vectors produce a vector
1441-
// of integers with the same dimension.
1442-
expr.type()=vector_typet(signed_int_type(), to_vector_type(o_type0).size());
1434+
// Comparisons between vectors produce a vector of integers of the same width
1435+
// with the same dimension.
1436+
auto subtype_width = to_bitvector_type(o_type0.subtype()).get_width();
1437+
expr.type() =
1438+
vector_typet{signedbv_typet{subtype_width}, to_vector_type(o_type0).size()};
1439+
1440+
// Replace the id as the semantics of these are point-wise application (and
1441+
// the result is not of bool type).
1442+
if(expr.id() == ID_notequal)
1443+
expr.id(ID_vector_notequal);
1444+
else
1445+
expr.id("vector-" + id2string(expr.id()));
14431446
}
14441447

14451448
void c_typecheck_baset::typecheck_expr_ptrmember(exprt &expr)

src/goto-programs/remove_vector.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ static bool have_to_remove_vector(const exprt &expr)
3535
}
3636
else if(expr.id()==ID_unary_minus || expr.id()==ID_bitnot)
3737
return true;
38+
else if(
39+
expr.id() == ID_vector_equal || expr.id() == ID_vector_notequal ||
40+
expr.id() == ID_vector_lt || expr.id() == ID_vector_le ||
41+
expr.id() == ID_vector_gt || expr.id() == ID_vector_ge)
42+
{
43+
return true;
44+
}
3845
else if(expr.id()==ID_vector)
3946
return true;
4047
}
@@ -103,6 +110,7 @@ static void remove_vector(exprt &expr)
103110
// x+y -> vector(x[0]+y[0],x[1]+y[1],...)
104111
array_exprt array_expr({}, array_type);
105112
array_expr.operands().resize(numeric_cast_v<std::size_t>(dimension));
113+
array_expr.add_source_location() = expr.source_location();
106114

107115
for(std::size_t i=0; i<array_expr.operands().size(); i++)
108116
{
@@ -130,6 +138,7 @@ static void remove_vector(exprt &expr)
130138
// -x -> vector(-x[0],-x[1],...)
131139
array_exprt array_expr({}, array_type);
132140
array_expr.operands().resize(numeric_cast_v<std::size_t>(dimension));
141+
array_expr.add_source_location() = expr.source_location();
133142

134143
for(std::size_t i=0; i<array_expr.operands().size(); i++)
135144
{
@@ -141,6 +150,66 @@ static void remove_vector(exprt &expr)
141150

142151
expr=array_expr;
143152
}
153+
else if(
154+
expr.id() == ID_vector_equal || expr.id() == ID_vector_notequal ||
155+
expr.id() == ID_vector_lt || expr.id() == ID_vector_le ||
156+
expr.id() == ID_vector_gt || expr.id() == ID_vector_ge)
157+
{
158+
// component-wise and generate 0 (false) or -1 (true)
159+
// x ~ y -> vector(x[0] ~ y[0] ? -1 : 0, x[1] ~ y[1] ? -1 : 0, ...)
160+
161+
auto const &binary_expr = to_binary_expr(expr);
162+
const vector_typet &vector_type = to_vector_type(expr.type());
163+
const auto dimension = numeric_cast_v<std::size_t>(vector_type.size());
164+
165+
const typet &subtype = vector_type.subtype();
166+
PRECONDITION(subtype.id() == ID_signedbv);
167+
exprt minus_one = from_integer(-1, subtype);
168+
exprt zero = from_integer(0, subtype);
169+
170+
exprt::operandst operands;
171+
operands.reserve(dimension);
172+
173+
const bool is_float =
174+
binary_expr.lhs().type().subtype().id() == ID_floatbv;
175+
irep_idt new_id;
176+
if(binary_expr.id() == ID_vector_notequal)
177+
{
178+
if(is_float)
179+
new_id = ID_ieee_float_notequal;
180+
else
181+
new_id = ID_notequal;
182+
}
183+
else if(binary_expr.id() == ID_vector_equal)
184+
{
185+
if(is_float)
186+
new_id = ID_ieee_float_equal;
187+
else
188+
new_id = ID_equal;
189+
}
190+
else
191+
{
192+
// just strip the "vector-" prefix
193+
new_id = id2string(binary_expr.id()).substr(7);
194+
}
195+
196+
for(std::size_t i = 0; i < dimension; ++i)
197+
{
198+
exprt index = from_integer(i, vector_type.size().type());
199+
200+
operands.push_back(
201+
if_exprt{binary_relation_exprt{index_exprt{binary_expr.lhs(), index},
202+
new_id,
203+
index_exprt{binary_expr.rhs(), index}},
204+
minus_one,
205+
zero});
206+
}
207+
208+
source_locationt source_location = expr.source_location();
209+
expr = array_exprt{std::move(operands),
210+
array_typet{subtype, vector_type.size()}};
211+
expr.add_source_location() = std::move(source_location);
212+
}
144213
else if(expr.id()==ID_vector)
145214
{
146215
expr.id(ID_array);
@@ -158,7 +227,9 @@ static void remove_vector(exprt &expr)
158227
numeric_cast_v<std::size_t>(to_constant_expr(array_type.size()));
159228
exprt casted_op =
160229
typecast_exprt::conditional_cast(op, array_type.subtype());
230+
source_locationt source_location = expr.source_location();
161231
expr = array_exprt(exprt::operandst(dimension, casted_op), array_type);
232+
expr.add_source_location() = std::move(source_location);
162233
}
163234
}
164235
}

src/util/irep_ids.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,12 @@ IREP_ID_ONE(min)
843843
IREP_ID_ONE(constant_interval)
844844
IREP_ID_TWO(C_bounds_check, #bounds_check)
845845
IREP_ID_ONE(count_leading_zeros)
846+
IREP_ID_TWO(vector_equal, vector-=)
847+
IREP_ID_TWO(vector_notequal, vector-!=)
848+
IREP_ID_TWO(vector_ge, vector->=)
849+
IREP_ID_TWO(vector_le, vector-<=)
850+
IREP_ID_TWO(vector_gt, vector->)
851+
IREP_ID_TWO(vector_lt, vector-<)
846852

847853
// Projects depending on this code base that wish to extend the list of
848854
// available ids should provide a file local_irep_ids.def in their source tree

0 commit comments

Comments
 (0)