class mmStorehPi(MovStatement): mrmap = [2,3] def __init__(self, src, dst): super(mmStorehPi, self).__init__() self.dst = VecDest(dst, 4, self.mrmap) if isinstance(dst, Pointer) else VecDest(dst.pointer, 4, self.mrmap) self.srcs += [ src ] @staticmethod def canStore(reglen, mrmap, horizontal=True, isAligned=False): if not horizontal: return False return reglen == 4 and mrmap == mmStorehPi.mrmap @staticmethod def getStore(src, dst): return mmStorehPi(src, dst) def replaceRefs(self, refMap): dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self return Mov(src, dst) def computeSym(self, nameList): src = self.srcs[0].computeSym(nameList) return [ src[2], src[3] ] def unparse(self, indent): return indent + "_mm_storeh_pi(" + self.dst.unparse("") + ", " + self.srcs[0].unparse("") + ");" def printInst(self, indent): return indent + "mmStorehPi( " + self.srcs[0].printInst("") + ", " + self.dst.printInst("") + " )"
class mmStorePs(MovStatement): mrmap = [0,1,2,3] # static definition of the mem-reg mapping imposed by the store def __init__(self, src, dst): super(mmStorePs, self).__init__() # silent introduction of VecDest operator self.dst = VecDest(dst, 4, self.mrmap, isAligned=True) if isinstance(dst, Pointer) else VecDest(dst.pointer, 4, self.mrmap, isAligned=True) self.srcs += [ src ] def replaceRefs(self, refMap): dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self return Mov(src, dst) @staticmethod def canStore(reglen, mrmap, horizontal=True, isAligned=False): if not horizontal: return False return reglen == 4 and mrmap == mmStoreuPs.mrmap and isAligned @staticmethod def getStore(src, dst): return mmStorePs(src, dst) def computeSym(self, nameList): return self.srcs[0].computeSym(nameList) def unparse(self, indent): return indent + "_mm_store_ps(" + self.dst.unparse("") + ", " + self.srcs[0].unparse("") + ");" def printInst(self, indent): return indent + "mmStorePs( " + self.srcs[0].printInst("") + ", " + self.dst.printInst("") + " )"
class mmStoreSd(MovStatement): mrmap = [0] def __init__(self, src, dst): super(mmStoreSd, self).__init__() # self.dst = ScaDest(dst) if isinstance(dst, Pointer) else ScaDest(dst.pointer) # I don't anything else than a pointer can get here self.dst = VecDest(dst, 2, self.mrmap) if isinstance( dst, Pointer) else VecDest(dst.pointer, 2, self.mrmap) self.srcs += [src] # self.srcZMask = src.getZMask() # self.slen = 2 # self.dlen = 1 @staticmethod def canStore(reglen, mrmap, horizontal=True, isAligned=False): if not horizontal: return False return reglen == 2 and mrmap == mmStoreSd.mrmap @staticmethod def getStore(src, dst): return mmStoreSd(src, dst) def replaceRefs(self, refMap): # pointer = AddressOf(self.dst.replaceRefs(refMap)) # src = self.srcs[0].replaceRefs(refMap) # return mmStoreSd(src, pointer) dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self if self.srcZMask != [0, 1]: return Mov(mmMoveSd(mmSetzeroPd(), src), dst) return Mov(src, dst) # def replaceInLHS(self, old, new): # if self.dst == old: # return mmStoreSd(self.srcs[0], AddressOf(new)) def computeSym(self, nameList): return [self.srcs[0].computeSym(nameList)[0]] def unparse(self, indent): return indent + "_mm_store_sd(" + self.dst.unparse( "") + ", " + self.srcs[0].unparse("") + ");" def printInst(self, indent): return indent + "mmStoreSd( " + self.srcs[0].printInst( "") + ", " + self.dst.printInst("") + " )"
class mmStoreuPs(MovStatement): mrmap = [0,1,2,3] # static definition of the mem-reg mapping imposed by the store def __init__(self, src, dst): super(mmStoreuPs, self).__init__() dstpointer = dst if isinstance(dst, Pointer) else dst.pointer # silent introduction of VecDest operator self.dst = VecDest(dstpointer, 4, self.mrmap) self.srcs += [ src ] self.pointer = dstpointer def replaceRefs(self, refMap): dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self return Mov(src, dst) @staticmethod def canStore(reglen, mrmap, horizontal=True, isAligned=False): if not horizontal: return False return reglen == 4 and mrmap == mmStoreuPs.mrmap @staticmethod def getStore(src, dst): return mmStoreuPs(src, dst) def computeSym(self, nameList): return self.srcs[0].computeSym(nameList) def unparse(self, indent): return indent + "_mm_storeu_ps(" + self.dst.unparse("") + ", " + self.srcs[0].unparse("") + ");" def printInst(self, indent): return indent + "mmStoreuPs( " + self.srcs[0].printInst("") + ", " + self.dst.printInst("") + " )" def align(self, analysis): for i, source in enumerate(self.srcs): self.srcs[i] = source.align(analysis) analysis.env = self.env # restore the analysis env that corresponds to this instruction if analysis.congruenceAnalysis.lessEqual(analysis.evaluateExpr(sympify(self.dst.pointer.ref.physLayout.name) + getReference(icode, self.dst.pointer.mat).getLinIdx(self.dst.pointer.at))[1], AbstractElement((0, self.dst.reglen))): return mmStorePs(self.srcs[0], self.dst.pointer) else: return self
class mmStoreSsNoZeromask(MovStatement): ''' This class can and must be used instead of mmStoreSs by generic store instructions. ''' mrmap = [0] def __init__(self, src, dst): super(mmStoreSsNoZeromask, self).__init__() self.dst = VecDest(dst, 4, self.mrmap) if isinstance(dst, Pointer) else VecDest(dst.pointer, 4, self.mrmap) # When passing VecAccess in ScaRep self.srcs += [ src ] # self.srcZMask = src.getZMask() @staticmethod def canStore(reglen, mrmap, horizontal=True, isAligned=False): if not horizontal: return False return reglen == 4 and mrmap == mmStoreSs.mrmap @staticmethod def getStore(src, dst): return mmStoreSsNoZeromask(src, dst) def replaceRefs(self, refMap): dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self # if self.srcZMask != [0,1,1,1]: # return Mov(mmMoveSs(mmSetzeroPs(), src), dst) return Mov(src, dst) def computeSym(self, nameList): return [ self.srcs[0].computeSym(nameList)[0] ] def unparse(self, indent): return indent + "_mm_store_ss(" + self.dst.unparse("") + ", " + self.srcs[0].unparse("") + ");" def printInst(self, indent): return indent + "mmStoreSsNoZeromask( " + self.srcs[0].printInst("") + ", " + self.dst.printInst("") + " )"
class mmStoreGs(MovStatement): '''Wrapper of a vector store instruction. Useful when we want to represent a composite store instruction as a single logical instruction and then have it easily replaced by a scalar during scalar replacement. ''' def __init__(self, src, dst, mrmap, isCompact=False, isCorner=True, horizontal=True): super(mmStoreGs, self).__init__() self.srcs += [src] self.mrmap = mrmap dstptr = dst if isinstance(dst, Pointer) else dst.pointer self.dst = VecDest(dstptr, 4, mrmap, horizontal, isCompact, isCorner) self.horizontal = horizontal self.isCompact = isCompact self.isCorner = isCorner self.orientation = 'horizontal' if horizontal else 'vertical' self.reglen = 4 self.analysis = None self._content = None @property def content(self): if self._content is None: self._content = self.generateContent() return self._content def generateContent(self): dst = self.dst.pointer src = self.srcs[0] mrmap = self.mrmap horizontal = self.horizontal isCompact = self.isCompact content = None if len(mrmap) == 1: if mrmap[0] == 0: content = [mmStoreSsNoZeromask(src, dst)] else: ei = mmShufflePs(src, src, tuple(4*[mrmap[0]])) content = [mmStoreSsNoZeromask(ei, dst)] elif mrmap == [0, 1]: if horizontal or isCompact: content = [mmStorelPi(src, PointerCast("__m64", dst))] else: p0 = dst p1 = Pointer((dst.mat, (dst.at[0] + 1, dst.at[1]))) e1 = mmShufflePs(src, src, (2,2,2,1)) content = [mmStoreSsNoZeromask(src, p0), mmStoreSsNoZeromask(e1, p1)] elif mrmap == [0, 1, 2]: if horizontal or isCompact: p0 = dst p2 = Pointer((dst.mat, (dst.at[0], dst.at[1] + 2))) e2 = mmShufflePs(src, src, (3,3,3,2)) content = [mmStorelPi(src, PointerCast("__m64", p0)), mmStoreSsNoZeromask(e2, p2)] else: ps = [dst, Pointer((dst.mat, (dst.at[0] + 1, dst.at[1]))), Pointer((dst.mat, (dst.at[0] + 2, dst.at[1])))] e1 = mmShufflePs(src, src, (3,3,3,1)) e2 = mmShufflePs(src, src, (3,3,3,2)) content = [mmStoreSsNoZeromask(src, ps[0]), mmStoreSsNoZeromask(e1, ps[1]), mmStoreSsNoZeromask(e2, ps[2])] elif mrmap == [0, 1, 2, 3]: if horizontal or isCompact: content = [mmStoreuPs(src, dst)] else: ps = [dst] + [Pointer((dst.mat, (dst.at[0] + i, dst.at[1]))) for i in range(1, 4)] es = [mmShufflePs(src, src, (3,3,3,i)) for i in range(1,4)] content = [mmStoreSsNoZeromask(src, ps[0])] + [mmStoreSsNoZeromask(es[i-1], ps[i]) for i in range(1,4)] elif mrmap == [1, 2]: if horizontal or isCompact: v1_2 = mmShufflePs(src, src, (3,3,2,1)) content = [mmStorelPi(v1_2, PointerCast("__m64", dst))] elif mrmap == [2, 3]: if horizontal or isCompact: content = [mmStorehPi(src, PointerCast("__m64", dst))] elif mrmap == [1, 2, 3]: if horizontal or isCompact: pointer2 = Pointer((dst.mat, (dst.at[0], dst.at[1] + 1))) e1 = mmShufflePs(src, src, (1,1,1,1)) content = [mmStoreSsNoZeromask(e1, dst), mmStorehPi(src, PointerCast("__m64", pointer2))] if content is None: raise ValueError('mmStoreGs does not support mrmap %s with %s layout yet' % (str(mrmap), 'horizontal' if horizontal else 'vertical')) # content.append(DebugPrint(["\"Storing "+getReference(icode, dst.mat).physLayout.name+"\"", "\" [ \"", str(dst.at[0]), "\" , \"", str(dst.at[1]), "\" ] at line \"", "__LINE__"])); return content def replaceRefs(self, refMap): dst = self.dst.replaceRefs(refMap) src = self.srcs[0].replaceRefs(refMap) if isinstance(dst, VecDest): self.dst = dst self.srcs[0] = src return self return Mov(src, dst) @staticmethod def canStore(reglen, mrmap, horizontal, isAligned=False): return reglen == 4 @staticmethod def getStore(src, dst): mrmap = dst.mrmap if isinstance(mrmap, int): mrmap = [mrmap] return mmStoreGs(src, dst, mrmap, dst.isCompact, dst.isCorner, dst.horizontal) def computeSym(self, nameList): return self.srcs[0].computeSym(nameList)[:len(self.mrmap)] def unparse(self, indent): content = self.content if self.analysis is not None and isinstance(self.analysis, IntervalCongruenceReductionAnalysis): for instr in content: instr.env = self.env self.analysis.propagateEnvToSrcs(instr) content = [instr.align(self.analysis) for instr in content] return '\n'.join(instr.unparse(indent) for instr in content) def printInst(self, indent): # return 'mmStoreGs(%s, %s, %s)' % (str(self.mrmap), self.orientation, ','.join([instr.printInst(indent) for instr in self._content])) return 'mmStoreGs(%r, %r, %r, %s)' % (self.dst, self.srcs[0], self.mrmap, self.orientation) def align(self, analysis): self.analysis = analysis return self