Skip to content

Commit 4c24ace

Browse files
committed
Support ==,!=,<,<=,>,>= over vectors
These need to be rewritten to point-wise applications and return -1 (true) or 0 (false) per element. Fixes: #5930
1 parent f649c47 commit 4c24ace

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
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/goto-programs/remove_vector.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ 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_equal || expr.id() == ID_notequal || expr.id() == ID_lt ||
40+
expr.id() == ID_le || expr.id() == ID_gt || expr.id() == ID_ge)
41+
{
42+
return true;
43+
}
3844
else if(expr.id()==ID_vector)
3945
return true;
4046
}
@@ -103,6 +109,7 @@ static void remove_vector(exprt &expr)
103109
// x+y -> vector(x[0]+y[0],x[1]+y[1],...)
104110
array_exprt array_expr({}, array_type);
105111
array_expr.operands().resize(numeric_cast_v<std::size_t>(dimension));
112+
array_expr.add_source_location() = expr.source_location();
106113

107114
for(std::size_t i=0; i<array_expr.operands().size(); i++)
108115
{
@@ -130,6 +137,7 @@ static void remove_vector(exprt &expr)
130137
// -x -> vector(-x[0],-x[1],...)
131138
array_exprt array_expr({}, array_type);
132139
array_expr.operands().resize(numeric_cast_v<std::size_t>(dimension));
140+
array_expr.add_source_location() = expr.source_location();
133141

134142
for(std::size_t i=0; i<array_expr.operands().size(); i++)
135143
{
@@ -141,6 +149,41 @@ static void remove_vector(exprt &expr)
141149

142150
expr=array_expr;
143151
}
152+
else if(
153+
expr.id() == ID_equal || expr.id() == ID_notequal || expr.id() == ID_lt ||
154+
expr.id() == ID_le || expr.id() == ID_gt || expr.id() == ID_ge)
155+
{
156+
// component-wise and generate 0 (false) or -1 (true)
157+
// x ~ y -> vector(x[0] ~ y[0] ? -1 : 0, x[1] ~ y[1] ? -1 : 0, ...)
158+
159+
auto const &binary_expr = to_binary_expr(expr);
160+
const vector_typet &vector_type = to_vector_type(expr.type());
161+
const auto dimension = numeric_cast_v<std::size_t>(vector_type.size());
162+
163+
const typet &subtype = vector_type.subtype();
164+
exprt minus_one = from_integer(-1, subtype);
165+
exprt zero = from_integer(0, subtype);
166+
167+
exprt::operandst operands;
168+
operands.reserve(dimension);
169+
170+
for(std::size_t i = 0; i < dimension; ++i)
171+
{
172+
exprt index = from_integer(i, vector_type.size().type());
173+
174+
operands.push_back(
175+
if_exprt{binary_relation_exprt{index_exprt{binary_expr.lhs(), index},
176+
binary_expr.id(),
177+
index_exprt{binary_expr.rhs(), index}},
178+
minus_one,
179+
zero});
180+
}
181+
182+
source_location source_location = expr.source_location();
183+
expr = array_exprt{std::move(operands),
184+
array_typet{subtype, vector_type.size()}};
185+
expr.add_source_location() = std::move(source_location);
186+
}
144187
else if(expr.id()==ID_vector)
145188
{
146189
expr.id(ID_array);
@@ -158,7 +201,9 @@ static void remove_vector(exprt &expr)
158201
numeric_cast_v<std::size_t>(to_constant_expr(array_type.size()));
159202
exprt casted_op =
160203
typecast_exprt::conditional_cast(op, array_type.subtype());
204+
source_location source_location = expr.source_location();
161205
expr = array_exprt(exprt::operandst(dimension, casted_op), array_type);
206+
expr.add_source_location() = std::move(source_location);
162207
}
163208
}
164209
}

src/util/std_expr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,8 +664,8 @@ class binary_predicate_exprt:public binary_exprt
664664

665665
DATA_CHECK(
666666
vm,
667-
expr.type().id() == ID_bool,
668-
"result of binary predicate expression should be of type bool");
667+
expr.type().id() == ID_bool || expr.id().id() == ID_vector,
668+
"result of binary predicate expression should be of type bool or vector");
669669
}
670670
};
671671

0 commit comments

Comments
 (0)