/* * Check that each destination register or spill slot is unique, * and that sources have the same number or less operands than * destinations. */ bool checkShuffle(const IRInstruction& inst, const RegAllocInfo& regs) { auto n = inst.numSrcs(); assert(n == inst.extra<Shuffle>()->size); RegSet destRegs; std::bitset<NumPreAllocatedSpillLocs> destSlots; auto& inst_regs = regs[inst]; for (uint32_t i = 0; i < n; ++i) { DEBUG_ONLY auto& rs = inst_regs.src(i); DEBUG_ONLY auto& rd = inst.extra<Shuffle>()->dests[i]; if (rd.numAllocated() == 0) continue; // dest was unused; ignore. if (rd.spilled()) { assert(!rs.spilled()); // no mem-mem copies } else { // rs could have less assigned registers/slots than rd, in these cases: // - when rs is empty, because the source is a constant. // - when rs has 1 register because it's untagged but rd needs 2 because // it's a more general (tagged) type, because of a phi. assert(rs.numWords() <= rd.numWords()); assert(rs.spilled() || rs.isFullSIMD() == rd.isFullSIMD()); } for (int j = 0; j < rd.numAllocated(); ++j) { if (rd.spilled()) { assert(!destSlots.test(rd.slot(j))); destSlots.set(rd.slot(j)); } else { assert(!destRegs.contains(rd.reg(j))); // no duplicate dests destRegs.add(rd.reg(j)); } } } return true; }