我一直在尝试使用Z3证明某些SIMD向量化,并且在尝试对有条件地在位或通道(例如Intel _mm_shuffle_epi8
)周围移动的SIMD操作进行建模时遇到问题 >
当我尝试将符号high
和low
与似乎不受支持的Extract
一起使用时,会发生问题:
assert a.sort() == BitVecSort(128)
assert b.sort() == BitVecSort(128)
Extract( Extract(i+3,i,b)*8+7, Extract(i+3,i,b)*8, a)
产生
z3.z3types.Z3Exception: Symbolic expressions cannot be cast to concrete Boolean values.
问题似乎有两个方面:
Z3似乎不支持符号大小的BitVecs
>>> a = Int('a')
>>> b = BitVec('b', a)
ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type
会很整洁,但是a。结果,Extract
需要能够准确知道其返回值的类型BitVec
,并要求high
和low
都是具体的,即使它看起来像唯一真正的要求应该是simplify(high - low)
产生具体的价值。
这样做的正确方法是什么?
答案 0 :(得分:3)
SMTLib位向量逻辑仅针对具体的位大小定义。这不仅是一个疏忽:这是逻辑的基本限制:没有决定程序可以决定可能涉及符号大小的位向量公式的正确性,因为位向量公式的真实性可以根据大小而变化。经典示例是:
x <= 7
如果x
是大小<= 3的位向量,则上述内容为true,否则为true。如果这是人为的,请考虑以下因素:
x*x <= x+x+x
同样,如果x
为2位宽,则为true,但如果为3位宽,则为true。因此,SMTLib要求所有位向量大小在规范时都是具体的。请注意,您可以 编写适用于任意位大小的高级程序,但是一旦将它们渲染并发送到求解器,所有位向量大小都必须是已知的具体常量。
关于您对Extract
的问题。没错,严格来说,最后长度的具体性就足够了。但是z3py是SMTLib之上的一个薄层,并且没有做这样的简化。 “具体”要求来自对相应的SMTLib函数的类似限制:
All function symbols with declaration of the form ((_ extract i j) (_ BitVec m) (_ BitVec n)) where - i, j, m, n are numerals - m > i ≥ j ≥ 0, - n = i - j + 1 "
请参见此处:http://smtlib.cs.uiowa.edu/theories-FixedSizeBitVectors.shtml请注意,出于这个原因,即使逻辑本身也被称为“ FixedSizeBitVectors”,而不仅仅是“ BitVectors”。
但是,要提取固定大小的块,只需右移lo
,然后掩蔽/提取所需的位数,并不是很困难:
((_ extract 7 0) (bvlshr x lo))
如果块的大小不是恒定的,那么您又会进入符号位向量大小的世界,出于上面我提到的原因,SMTLib避免了这种情况。 (这也是extract
将具体整数用作参数并以有趣的SMTLib表示法表示该参数为具体值的原因。)
如果必须使用“符号”字长,最好的办法是编写程序,并通过确保每种情况下的具体大小分别证明感兴趣的每个“符号”字长。 (基本上是您感兴趣的所有大小的大小写分隔。)
答案 1 :(得分:1)
是的,高/低必须保持恒定,以便静态知道结果类型。 尽管需要固定输出的最大大小,但您可以使用shift和/或遮罩来执行所需的操作。