Support for insertelement, extractelement and shufflevector
* Support for insertelement and extractelement
foo
sema for shufflevector
handle poison
* misc changes
* eliminate long lines
* misc fixes
* fix
* fixes :)
* keep BV representation away
* move update and extract to vectortype class
MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -1911,4 +1911,124 @@ unique_ptr<Instr> Memcpy::dup(const string &suffix) const {
return make_unique<Memcpy>(*dst, *src, *bytes, align_dst, align_src, move);
}
+
+vector<Value*> ExtractElement::operands() const {
+ return { v, idx };
+}
+
+void ExtractElement::rauw(const Value &what, Value &with) {
+ RAUW(v);
+ RAUW(idx);
+}
+
+void ExtractElement::print(ostream &os) const {
+ os << getName() << " = extractelement " << *v << ", " << *idx;
+}
+
+StateValue ExtractElement::toSMT(State &s) const {
+ auto &[iv, ip] = s[*idx];
+ auto vty = v->getType().getAsVectorType();
+ expr inbounds = iv.ult(vty->numElementsConst());
+ auto [rv, rp] = vty->extract(s[*v], iv);
+ return { move(rv), ip && inbounds && rp };
+}
+
+expr ExtractElement::getTypeConstraints(const Function &f) const {
+ return Value::getTypeConstraints() &&
+ v->getType().enforceVectorType([&](auto &ty)
+ { return ty == getType(); }) &&
+ idx->getType().enforceIntType();
+}
+
+unique_ptr<Instr> ExtractElement::dup(const string &suffix) const {
+ return make_unique<ExtractElement>(getType(), getName() + suffix, *v, *idx);
+}
+
+
+vector<Value*> InsertElement::operands() const {
+ return { v, e, idx };
+}
+
+void InsertElement::rauw(const Value &what, Value &with) {
+ RAUW(v);
+ RAUW(e);
+ RAUW(idx);
+}
+
+void InsertElement::print(ostream &os) const {
+ os << getName() << " = insertelement" << *v << ", " << *e << ", " << *idx;
+}
+
+StateValue InsertElement::toSMT(State &s) const {
+ auto &[iv, ip] = s[*idx];
+ auto vty = v->getType().getAsVectorType();
+ expr inbounds = iv.ult(vty->numElementsConst());
+ auto [rv, rp] = vty->update(s[*v], s[*e], iv);
+ return { move(rv), expr::mkIf(ip && inbounds, move(rp),
+ vty->getDummyValue(false).non_poison) };
+}
+
+expr InsertElement::getTypeConstraints(const Function &f) const {
+ return Value::getTypeConstraints() &&
+ getType() == v->getType() &&
+ v->getType().enforceVectorType([&](auto &ty)
+ { return ty == e->getType(); }) &&
+ idx->getType().enforceIntType();
+}
+
+unique_ptr<Instr> InsertElement::dup(const string &suffix) const {
+ return make_unique<InsertElement>(getType(), getName() + suffix,
+ *v, *e, *idx);
+}
+
+
+vector<Value*> ShuffleVector::operands() const {
+ return { v1, v2, mask };
+}
+
+void ShuffleVector::rauw(const Value &what, Value &with) {
+ RAUW(v1);
+ RAUW(v2);
+ RAUW(mask);
+}
+
+void ShuffleVector::print(ostream &os) const {
+ os << getName() << " = shufflevector " << *v1 << ", " << *v2 << ", " << *mask;
+}
+
+StateValue ShuffleVector::toSMT(State &s) const {
+ auto vty = v1->getType().getAsVectorType();
+ expr sz = expr::mkUInt(vty->numElementsConst(), 32);
+ auto mty = mask->getType().getAsAggregateType();
+ vector<StateValue> vals;
+
+ for (unsigned i = 0, e = mty->numElementsConst(); i != e; ++i) {
+ auto [iv, ip] = mty->extract(s[*mask], i);
+ auto [lv, lp] = vty->extract(s[*v1], iv);
+ auto [rv, rp] = vty->extract(s[*v2], iv - sz);
+ expr v = expr::mkIf(iv.uge(sz), rv, lv);
+ expr np = expr::mkIf(iv.uge(sz), rp, lp);
+ expr inbounds = iv.ult(sz + sz);
+ vals.emplace_back(move(v), ip && inbounds && np);
+ }
+
+ return getType().getAsAggregateType()->aggregateVals(vals);
+}
+
+expr ShuffleVector::getTypeConstraints(const Function &f) const {
+ return Value::getTypeConstraints() &&
+ getType().enforceVectorTypeSameChildTy(v1->getType()) &&
+ getType().enforceVectorTypeEquiv(mask->getType()) &&
+ v1->getType().enforceVectorType() &&
+ v1->getType() == v2->getType() &&
+ // mask is a vector of i32
+ mask->getType().enforceVectorType([](auto &ty)
+ { return ty.enforceIntType(32); });
+}
+
+unique_ptr<Instr> ShuffleVector::dup(const string &suffix) const {
+ return make_unique<ShuffleVector>(getType(), getName() + suffix,
+ *v1, *v2, *mask);
+}
+
}

MODIFY
ir/instr.h
ir/instr.h
@@ -489,4 +489,46 @@ public:
std::unique_ptr<Instr> dup(const std::string &suffix) const override;
};
+
+class ExtractElement final : public Instr {
+ Value *v, *idx;
+public:
+ ExtractElement(Type &type, std::string &&name, Value &v, Value &idx)
+ : Instr(type, move(name)), v(&v), idx(&idx) {}
+ std::vector<Value*> operands() const override;
+ void rauw(const Value &what, Value &with) override;
+ void print(std::ostream &os) const override;
+ StateValue toSMT(State &s) const override;
+ smt::expr getTypeConstraints(const Function &f) const override;
+ std::unique_ptr<Instr> dup(const std::string &suffix) const override;
+};
+
+
+class InsertElement final : public Instr {
+ Value *v, *e, *idx;
+public:
+ InsertElement(Type &type, std::string &&name, Value &v, Value &e, Value &idx)
+ : Instr(type, move(name)), v(&v), e(&e), idx(&idx) {}
+ std::vector<Value*> operands() const override;
+ void rauw(const Value &what, Value &with) override;
+ void print(std::ostream &os) const override;
+ StateValue toSMT(State &s) const override;
+ smt::expr getTypeConstraints(const Function &f) const override;
+ std::unique_ptr<Instr> dup(const std::string &suffix) const override;
+};
+
+
+class ShuffleVector final : public Instr {
+ Value *v1, *v2, *mask;
+public:
+ ShuffleVector(Type &type, std::string &&name, Value &v1, Value &v2, Value &m)
+ : Instr(type, move(name)), v1(&v1), v2(&v2), mask(&m) {}
+ std::vector<Value*> operands() const override;
+ void rauw(const Value &what, Value &with) override;
+ void print(std::ostream &os) const override;
+ StateValue toSMT(State &s) const override;
+ smt::expr getTypeConstraints(const Function &f) const override;
+ std::unique_ptr<Instr> dup(const std::string &suffix) const override;
+};
+
}

MODIFY
ir/type.cpp
ir/type.cpp
@@ -162,6 +162,13 @@ expr Type::enforceVectorTypeIff(const Type &other) const {
return !other.enforceVectorType() || (enforceVectorType() && elems);
}
+expr Type::enforceVectorTypeSameChildTy(const Type &other) const {
+ if (auto agg = getAsAggregateType())
+ if (auto agg2 = other.getAsAggregateType())
+ return agg->getChild(0) == agg2->getChild(0);
+ return false;
+}
+
expr Type::enforceVectorTypeEquiv(const Type &other) const {
return enforceVectorTypeIff(other) && other.enforceVectorTypeIff(*this);
}
@@ -208,6 +215,10 @@ const StructType* Type::getAsStructType() const {
return nullptr;
}
+const VectorType* Type::getAsVectorType() const {
+ return nullptr;
+}
+
expr Type::toBV(expr e) const {
return e;
}
@@ -604,24 +615,6 @@ StateValue AggregateType::extract(const StateValue &val, unsigned index) const {
val.non_poison.extract(h, l) });
}
-StateValue AggregateType::extract(const StateValue &val,
- const expr &index) const {
- auto &elementTy = *children[0];
- for (unsigned i = 1; i < elements; ++i) {
- assert(elementTy.bits() == children[i]->bits());
- }
- unsigned bw_elem = elementTy.bits();
- unsigned bw_val = val.value.bits();
- assert(bw_val == val.non_poison.bits());
- expr idx = index.zextOrTrunc(bw_val) * expr::mkUInt(bw_elem, bw_val);
-
- unsigned h = elements * bw_elem - 1;
- unsigned l = (elements - 1) * bw_elem;
-
- return elementTy.fromBV({ (val.value << idx).extract(h, l),
- (val.non_poison << idx).extract(h, l) });
-}
-
unsigned AggregateType::bits() const {
unsigned bw = 0;
for (unsigned i = 0; i < elements; ++i) {
@@ -764,6 +757,47 @@ VectorType::VectorType(string &&name, unsigned elements, Type &elementTy)
children.resize(elements, &elementTy);
}
+StateValue VectorType::extract(const StateValue &val,
+ const expr &index) const {
+ auto &elementTy = *children[0];
+ for (unsigned i = 1; i < elements; ++i) {
+ assert(elementTy.bits() == children[i]->bits());
+ }
+ unsigned bw_elem = elementTy.bits();
+ unsigned bw_val = val.value.bits();
+ assert(bw_val == val.non_poison.bits());
+ expr idx = index.zextOrTrunc(bw_val) * expr::mkUInt(bw_elem, bw_val);
+
+ unsigned h = elements * bw_elem - 1;
+ unsigned l = (elements - 1) * bw_elem;
+
+ return elementTy.fromBV({ (val.value << idx).extract(h, l),
+ (val.non_poison << idx).extract(h, l) });
+}
+
+StateValue VectorType::update(const StateValue &val,
+ const StateValue &n,
+ const expr &index) const {
+ auto &elementTy = *children[0];
+ for (unsigned i = 1; i < elements; ++i) {
+ assert(elementTy.bits() == children[i]->bits());
+ }
+
+ unsigned bw_elem = elementTy.bits();
+ unsigned bw_val = bits();
+
+ expr idx = index.zextOrTrunc(bw_val) * expr::mkUInt(bw_elem, bw_val);
+ expr fill = expr::mkUInt(0, bw_val - bw_elem);
+ expr mask = ~expr::mkInt(-1, bw_elem).concat(fill).lshr(idx);
+
+ StateValue n_bv = elementTy.toBV(n);
+ expr nv_shifted = n_bv.value.concat(fill).lshr(idx);
+ expr np_shifted = n_bv.non_poison.concat(fill).lshr(idx);
+
+ return fromBV({ (val.value & mask) | nv_shifted,
+ (val.non_poison & mask) | np_shifted});
+}
+
expr VectorType::getTypeConstraints() const {
auto &elementTy = *children[0];
expr r = AggregateType::getTypeConstraints() &&
@@ -794,6 +828,10 @@ void VectorType::print(ostream &os) const {
os << '<' << elements << " x " << *children[0] << '>';
}
+const VectorType* VectorType::getAsVectorType() const {
+ return this;
+}
+
StructType::StructType(string &&name, vector<Type*> &&children)
: AggregateType(move(name), move(children)) {
@@ -1030,6 +1068,10 @@ const StructType* SymbolicType::getAsStructType() const {
return &*s;
}
+const VectorType* SymbolicType::getAsVectorType() const {
+ return &*v;
+}
+
expr SymbolicType::toBV(expr e) const {
DISPATCH(toBV(move(e)), UNREACHABLE());
}

MODIFY
ir/type.h
ir/type.h
@@ -21,6 +21,7 @@ class AggregateType;
class FloatType;
class StructType;
class SymbolicType;
+class VectorType;
class VoidType;
class State;
struct StateValue;
@@ -71,6 +72,7 @@ public:
// enforce same number of elements if other is a vector
smt::expr enforceVectorTypeIff(const Type &other) const;
smt::expr enforceVectorTypeEquiv(const Type &other) const;
+ smt::expr enforceVectorTypeSameChildTy(const Type &other) const;
virtual smt::expr enforceVectorType(
const std::function<smt::expr(const Type&)> &enforceElem) const;
smt::expr enforceScalarOrVectorType(
@@ -84,6 +86,7 @@ public:
virtual const FloatType* getAsFloatType() const;
virtual const AggregateType* getAsAggregateType() const;
virtual const StructType* getAsStructType() const;
+ virtual const VectorType* getAsVectorType() const;
virtual smt::expr toBV(smt::expr e) const;
virtual IR::StateValue toBV(IR::StateValue v) const;
@@ -239,8 +242,6 @@ public:
StateValue aggregateVals(const std::vector<StateValue> &vals) const;
IR::StateValue extract(const IR::StateValue &val, unsigned index) const;
- IR::StateValue extract(const IR::StateValue &val,
- const smt::expr &index) const;
Type& getChild(unsigned index) const { return *children[index]; }
unsigned bits() const override;
@@ -278,11 +279,17 @@ public:
VectorType(std::string &&name) : AggregateType(std::move(name)) {}
VectorType(std::string &&name, unsigned elements, Type &elementTy);
+ IR::StateValue extract(const IR::StateValue &val,
+ const smt::expr &index) const;
+ IR::StateValue update(const IR::StateValue &val,
+ const IR::StateValue &n,
+ const smt::expr &idx) const;
smt::expr getTypeConstraints() const override;
bool isVectorType() const override;
smt::expr enforceVectorType(
const std::function<smt::expr(const Type&)> &enforceElem) const override;
void print(std::ostream &os) const override;
+ const VectorType* getAsVectorType() const override;
};
@@ -339,6 +346,7 @@ public:
const FloatType* getAsFloatType() const override;
const AggregateType* getAsAggregateType() const override;
const StructType* getAsStructType() const override;
+ const VectorType* getAsVectorType() const override;
smt::expr toBV(smt::expr e) const override;
IR::StateValue toBV(IR::StateValue v) const override;
smt::expr fromBV(smt::expr e) const override;

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -498,6 +498,23 @@ public:
return error(i);
}
+ RetTy visitExtractElementInst(llvm::ExtractElementInst &i) {
+ PARSE_BINOP();
+ RETURN_IDENTIFIER(make_unique<ExtractElement>(*ty, value_name(i), *a, *b));
+ }
+
+ RetTy visitInsertElementInst(llvm::InsertElementInst &i) {
+ PARSE_TRIOP();
+ RETURN_IDENTIFIER(make_unique<InsertElement>(*ty, value_name(i), *a, *b,
+ *c));
+ }
+
+ RetTy visitShuffleVectorInst(llvm::ShuffleVectorInst &i) {
+ PARSE_TRIOP();
+ RETURN_IDENTIFIER(make_unique<ShuffleVector>(*ty, value_name(i), *a, *b,
+ *c));
+ }
+
RetTy visitDbgInfoIntrinsic(llvm::DbgInfoIntrinsic&) { return {}; }
RetTy visitInstruction(llvm::Instruction &i) { return error(i); }

ADD
tests/unit/vector/extractelement1.opt
+Name: constant-folding-1
+%r = extractelement <2 x i4> <i4 3, i4 poison>, i8 0
+ =>
+%r = 3
+
+
+Name: constant-folding-2
+%r = extractelement <4 x i64> <i64 3, i64 poison, i64 8, i64 16>, i8 3
+ =>
+%r = 16
+
+
+Name: constant-folding-3
+%r = extractelement <2 x i4> <i4 3, i4 undef>, i8 1
+ =>
+%r = 5
+
+
+Name: constant-folding-4
+%r = extractelement <2 x i4> <i4 3, i4 poison>, i8 1
+ =>
+%r = 5
+
+
+Name: constant-folding-5
+%r = extractelement <2 x i4> <i4 3, i4 poison>, i8 3
+ =>
+%r = poison
+
+
+Name: constant-folding-6
+%r = extractelement <2 x i4> <i4 3, i4 4>, i8 poison
+ =>
+%r = poison
+
+
+Name: constant-folding-7
+%r = extractelement <2 x float> <float 3.0, float 4.0>, i8 poison
+ =>
+%r = poison
+
+
+Name: constant-folding-8
+%r = extractelement <2 x float> <float 3.0, float 4.0>, i8 0
+ =>
+%r = 3.0
+
+
+Name: constant-folding-9
+%r = extractelement <2 x float> <float 3.0, float 4.0>, i8 3
+ =>
+%r = poison

ADD
tests/unit/vector/insertelement1.opt
+Name: constant-folding-1
+%r = insertelement <4 x i4> <i4 3, i4 poison, i4 5, i4 7>, i4 5, i8 1
+ =>
+%r = <4 x i4> <i4 3, i4 5, i4 5, i4 7>
+
+
+Name: constant-folding-2
+%r = <4 x i4> <i4 3, i4 5, i4 5, i4 7>
+ =>
+%r = insertelement <4 x i4> <i4 3, i4 poison, i4 5, i4 7>, i4 5, i8 1
+
+
+Name: constant-folding-3
+%r = insertelement <4 x i4> <i4 3, i4 poison, i4 5, i4 7>, i4 5, i8 8
+ =>
+%r = <4 x i4> <i4 poison, i4 poison, i4 poison, i4 poison>
+
+
+Name: constant-folding-4
+%r = insertelement <4 x i4> <i4 3, i4 poison, i4 5, i4 7>, i4 5, i8 poison
+ =>
+%r = <4 x i4> <i4 poison, i4 poison, i4 poison, i4 poison>
+
+
+Name: constant-folding-5
+%r = insertelement <4 x i4> <i4 3, i4 poison, i4 5, i4 7>, i4 poison, i8 0
+ =>
+%r = <4 x i4> <i4 poison, i4 poison, i4 5, i4 7>
+
+
+Name: constant-folding-6
+%r = insertelement <4 x half> <half 3.0, half poison, half 5.0, half 7.0>, half 2.0, i8 2
+ =>
+%r = <4 x half> <half 3.0, half poison, half 2.0, half 7.0>
+
+
+Name: constant-folding-7
+%r = insertelement <4 x half> <half 3.0, half poison, half 5.0, half 7.0>, half 2.0, i8 1
+ =>
+%r = <4 x half> <half 3.0, half 2.0, half 5.0, half 7.0>
+
+
+Name: constant-folding-8
+%r = insertelement <4 x half> <half 3.0, half poison, half 5.0, half 7.0>, half 2.0, i8 8
+ =>
+%r = <4 x half> <half poison, half poison, half poison, half poison>
+
+
+Name: constant-folding-8
+%r = insertelement <4 x half> <half 3.0, half poison, half 5.0, half 7.0>, half 2.0, i8 poison
+ =>
+%r = <4 x half> <half poison, half poison, half poison, half poison>

ADD
tests/unit/vector/shufflevector1.opt
+Name: constant-folding-1
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <1 x i32> <i32 0>
+ =>
+%r = <1 x i4> <i4 3>
+
+
+Name: constant-folding-2
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <1 x i32> <i32 1>
+ =>
+%r = <1 x i4> <i4 5>
+
+
+Name: constant-folding-3
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <1 x i32> <i32 2>
+ =>
+%r = <1 x i4> <i4 4>
+
+
+Name: constant-folding-4
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <1 x i32> <i32 3>
+ =>
+%r = <1 x i4> <i4 6>
+
+
+Name: constant-folding-5
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <2 x i32> <i32 3, i32 2>
+ =>
+%r = <2 x i4> <i4 6, i4 4>
+
+Name: constant-folding-6
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <3 x i32> <i32 3, i32 2, i32 1>
+ =>
+%r = <3 x i4> <i4 6, i4 4, i4 5>
+
+
+Name: constant-folding-7
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ =>
+%r = <4 x i4> <i4 6, i4 4, i4 5, i4 3>
+
+
+Name: constant-folding-8
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ =>
+%r = <4 x i4> <i4 6, i4 4, i4 5, i4 3>
+
+
+Name: constant-folding-9
+%r = shufflevector <2 x i4> <i4 3, i4 5>, <2 x i4> <i4 4, i4 6>, <3 x i32> <i32 poison, i32 1, i32 4>
+ =>
+%r = <3 x i4> <i4 poison, i4 5, i4 poison>
+
+
+Name: constant-folding-10
+%r = shufflevector <2 x float> <float 3.0, float 5.0>, <2 x float> <float 4.0, float 6.0>, <3 x i32> <i32 poison, i32 1, i32 4>
+ =>
+%r = <3 x float> <float poison, float 5.0, float poison>

MODIFY
tools/alive_lexer.re
tools/alive_lexer.re
@@ -217,6 +217,9 @@ space+ {
"free" { return FREE; }
"fshl" { return FSHL; }
"fshr" { return FSHR; }
+"extractelement" { return EXTRACTELEMENT; }
+"insertelement" { return INSERTELEMENT; }
+"shufflevector" { return SHUFFLEVECTOR; }
"ret" { return RETURN; }
"bswap" { return BSWAP; }
"bitreverse" { return BITREVERSE; }

MODIFY
tools/alive_parser.cpp
tools/alive_parser.cpp
@@ -892,6 +892,42 @@ static unique_ptr<Instr> parse_malloc(string_view name) {
return make_unique<Malloc>(pointer_type, string(name), op, false);
}
+static unique_ptr<Instr> parse_extractelement(string_view name) {
+ // %p = extractelement vty %v, ty %idx
+ auto &ty_a = parse_type();
+ auto &a = parse_operand(ty_a);
+ parse_comma();
+ auto &ty_idx = parse_type();
+ auto &idx = parse_operand(ty_idx);
+ return make_unique<ExtractElement>(get_sym_type(), string(name), a, idx);
+}
+
+static unique_ptr<Instr> parse_insertelement(string_view name) {
+ // %p = insertelement vty %v, ty %n, ty %idx
+ auto &ty_a = parse_type();
+ auto &a = parse_operand(ty_a);
+ parse_comma();
+ auto &ty_e = parse_type();
+ auto &e = parse_operand(ty_e);
+ parse_comma();
+ auto &ty_idx = parse_type();
+ auto &idx = parse_operand(ty_idx);
+ return make_unique<InsertElement>(get_sym_type(), string(name), a, e, idx);
+}
+
+static unique_ptr<Instr> parse_shufflevector(string_view name) {
+ // %p = shufflevector ty %a, ty %b, ty %c
+ auto &ty_a = parse_type();
+ auto &a = parse_operand(ty_a);
+ parse_comma();
+ auto &ty_b = parse_type();
+ auto &b = parse_operand(ty_b);
+ parse_comma();
+ auto &ty_m = parse_vector_type();
+ auto &m = parse_operand(ty_m);
+ return make_unique<ShuffleVector>(get_sym_type(), string(name), a, b, m);
+}
+
static unique_ptr<Instr> parse_copyop(string_view name, token t) {
tokenizer.unget(t);
auto &ty = parse_type();
@@ -966,6 +1002,12 @@ static unique_ptr<Instr> parse_instr(string_view name) {
return parse_call(name);
case MALLOC:
return parse_malloc(name);
+ case EXTRACTELEMENT:
+ return parse_extractelement(name);
+ case INSERTELEMENT:
+ return parse_insertelement(name);
+ case SHUFFLEVECTOR:
+ return parse_shufflevector(name);
case INT_TYPE:
case HALF:
case FLOAT:

MODIFY
tools/tokens.h
tools/tokens.h
@@ -27,6 +27,7 @@ TOKEN(DOUBLE)
TOKEN(EQ)
TOKEN(EQUALS)
TOKEN(EXACT)
+TOKEN(EXTRACTELEMENT)
TOKEN(EXTRACTVALUE)
TOKEN(FADD)
TOKEN(FALSE)
@@ -48,6 +49,7 @@ TOKEN(GLOBAL_NAME)
TOKEN(HALF)
TOKEN(ICMP)
TOKEN(IDENTIFIER)
+TOKEN(INSERTELEMENT)
TOKEN(INT_TYPE)
TOKEN(LABEL)
TOKEN(LPAREN)
@@ -86,6 +88,7 @@ TOKEN(SEXT)
TOKEN(SGE)
TOKEN(SGT)
TOKEN(SHL)
+TOKEN(SHUFFLEVECTOR)
TOKEN(SITOFP)
TOKEN(SLE)
TOKEN(SLT)

Support for insertelement, extractelement and shufflevector (#141)

* Support for insertelement and extractelement

foo

sema for shufflevector

handle poison

* misc changes

* eliminate long lines

* misc fixes

* fix

* fixes :)

* keep BV representation away

* move update and extract to vectortype class