/// Extract all of the characters from the number \p Num one by one and /// insert them into the string builder \p SB. static void DecodeFixedWidth(APInt &Num, std::string &SB) { uint64_t CL = Huffman::CharsetLength; // NL is the number of characters that we can hold in a 64bit number. // Each letter takes Log2(CL) bits. Doing this computation in floating- // point arithmetic could give a slightly better (more optimistic) result, // but the computation may not be constant at compile time. uint64_t NumLetters = 64 / Log2_64_Ceil(CL); assert(Num.getBitWidth() > 8 && "Not enough bits for arithmetic on this alphabet"); // Try to decode eight numbers at once. It is much faster to work with // local 64bit numbers than working with APInt. In this loop we try to // extract NL characters at once and process them using a local 64-bit // number. // Calculate CharsetLength**NumLetters (CL to the power of NL), which is the // highest numeric value that can hold NumLetters characters in a 64bit // number. Notice: this loop is optimized away and CLX is computed to a // constant integer at compile time. uint64_t CLX = 1; for (unsigned i = 0; i < NumLetters; i++) { CLX *= CL; } while (Num.ugt(CLX)) { unsigned BW = Num.getBitWidth(); APInt C = APInt(BW, CLX); APInt Quotient(1, 0), Remainder(1, 0); APInt::udivrem(Num, C, Quotient, Remainder); // Try to reduce the bitwidth of the API after the division. This can // accelerate the division operation in future iterations because the // number becomes smaller (fewer bits) with each iteration. However, // We can't reduce the number to something too small because we still // need to be able to perform the "mod charset_length" operation. Num = Quotient.zextOrTrunc(std::max(Quotient.getActiveBits(), 64u)); uint64_t Tail = Remainder.getZExtValue(); for (unsigned i = 0; i < NumLetters; i++) { SB += Huffman::Charset[Tail % CL]; Tail = Tail / CL; } } // Pop characters out of the APInt one by one. while (Num.getBoolValue()) { unsigned BW = Num.getBitWidth(); APInt C = APInt(BW, CL); APInt Quotient(1, 0), Remainder(1, 0); APInt::udivrem(Num, C, Quotient, Remainder); Num = Quotient; SB += Huffman::Charset[Remainder.getZExtValue()]; } }
bool X86MCInstrAnalysis::clearsSuperRegisters(const MCRegisterInfo &MRI, const MCInst &Inst, APInt &Mask) const { const MCInstrDesc &Desc = Info->get(Inst.getOpcode()); unsigned NumDefs = Desc.getNumDefs(); unsigned NumImplicitDefs = Desc.getNumImplicitDefs(); assert(Mask.getBitWidth() == NumDefs + NumImplicitDefs && "Unexpected number of bits in the mask!"); bool HasVEX = (Desc.TSFlags & X86II::EncodingMask) == X86II::VEX; bool HasEVEX = (Desc.TSFlags & X86II::EncodingMask) == X86II::EVEX; bool HasXOP = (Desc.TSFlags & X86II::EncodingMask) == X86II::XOP; const MCRegisterClass &GR32RC = MRI.getRegClass(X86::GR32RegClassID); const MCRegisterClass &VR128XRC = MRI.getRegClass(X86::VR128XRegClassID); const MCRegisterClass &VR256XRC = MRI.getRegClass(X86::VR256XRegClassID); auto ClearsSuperReg = [=](unsigned RegID) { // On X86-64, a general purpose integer register is viewed as a 64-bit // register internal to the processor. // An update to the lower 32 bits of a 64 bit integer register is // architecturally defined to zero extend the upper 32 bits. if (GR32RC.contains(RegID)) return true; // Early exit if this instruction has no vex/evex/xop prefix. if (!HasEVEX && !HasVEX && !HasXOP) return false; // All VEX and EVEX encoded instructions are defined to zero the high bits // of the destination register up to VLMAX (i.e. the maximum vector register // width pertaining to the instruction). // We assume the same behavior for XOP instructions too. return VR128XRC.contains(RegID) || VR256XRC.contains(RegID); }; Mask.clearAllBits(); for (unsigned I = 0, E = NumDefs; I < E; ++I) { const MCOperand &Op = Inst.getOperand(I); if (ClearsSuperReg(Op.getReg())) Mask.setBit(I); } for (unsigned I = 0, E = NumImplicitDefs; I < E; ++I) { const MCPhysReg Reg = Desc.getImplicitDefs()[I]; if (ClearsSuperReg(Reg)) Mask.setBit(NumDefs + I); } return Mask.getBoolValue(); }
/// Extract all of the characters from the number \p Num one by one and /// insert them into the string builder \p SB. static void DecodeFixedWidth(APInt &Num, std::string &SB) { uint64_t CL = Huffman::CharsetLength; assert(Num.getBitWidth() > 8 && "Not enough bits for arithmetic on this alphabet"); // Try to decode eight numbers at once. It is much faster to work with // local 64bit numbers than working with APInt. In this loop we try to // extract 8 characters at one and process them using a local 64bit number. // In this code we assume a worse case scenario where our alphabet is a full // 8-bit ascii. It is possible to improve this code by packing one or two // more characters into the 64bit local variable. uint64_t CL8 = CL * CL * CL * CL * CL * CL * CL * CL; while (Num.ugt(CL8)) { unsigned BW = Num.getBitWidth(); APInt C = APInt(BW, CL8); APInt Quotient(1, 0), Remainder(1, 0); APInt::udivrem(Num, C, Quotient, Remainder); // Try to reduce the bitwidth of the API after the division. This can // accelerate the division operation in future iterations because the // number becomes smaller (fewer bits) with each iteration. However, // We can't reduce the number to something too small because we still // need to be able to perform the "mod charset_length" operation. Num = Quotient.zextOrTrunc(std::max(Quotient.getActiveBits(), 64u)); uint64_t Tail = Remainder.getZExtValue(); for (int i=0; i < 8; i++) { SB += Huffman::Charset[Tail % CL]; Tail = Tail / CL; } } // Pop characters out of the APInt one by one. while (Num.getBoolValue()) { unsigned BW = Num.getBitWidth(); APInt C = APInt(BW, CL); APInt Quotient(1, 0), Remainder(1, 0); APInt::udivrem(Num, C, Quotient, Remainder); Num = Quotient; SB += Huffman::Charset[Remainder.getZExtValue()]; } }