15#include "llvm/ADT/APInt.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/Support/MathExtras.h"
34 const llvm::APInt &output) {
37 assert(input.getBitWidth() < 32 &&
"Input width too large");
38 unsigned offset = input.getZExtValue() *
numOutputs;
40 table.setBitVal(offset + i, output[i]);
48 for (
unsigned i = 0; i < (1u <<
numInputs); ++i) {
50 llvm::APInt permutedInput = input;
53 for (
unsigned j = 0; j <
numInputs; ++j) {
54 if (permutation[j] != j)
55 permutedInput.setBitVal(j, input[permutation[j]]);
67 for (
unsigned i = 0; i < (1u <<
numInputs); ++i) {
71 llvm::APInt negatedInput = input ^ llvm::APInt(
numInputs, mask);
83 for (
unsigned i = 0; i < (1u <<
numInputs); ++i) {
88 llvm::APInt negatedOutput = output ^ llvm::APInt(
numOutputs, negation);
110 os <<
table <<
")\n";
113 for (
unsigned i = 0; i <
numInputs; ++i) {
114 os <<
"i" << i <<
" ";
117 os <<
"o" << i <<
" ";
128 for (
unsigned i = 0; i < (1u <<
numInputs); ++i) {
130 for (
unsigned j = 0; j <
numInputs; ++j) {
131 os << ((i >> j) & 1) <<
" ";
139 os << output[j] <<
" ";
155llvm::SmallVector<unsigned> identityPermutation(
unsigned size) {
156 llvm::SmallVector<unsigned> identity(size);
157 for (
unsigned i = 0; i < size; ++i)
165unsigned permuteNegationMask(
unsigned negationMask,
166 ArrayRef<unsigned> permutation) {
168 for (
unsigned i = 0; i < permutation.size(); ++i)
169 if (negationMask & (1u << permutation[i]))
176llvm::SmallVector<unsigned> invertPermutation(ArrayRef<unsigned> permutation) {
177 llvm::SmallVector<unsigned> inverse(permutation.size());
178 for (
unsigned i = 0; i < permutation.size(); ++i) {
179 inverse[permutation[i]] = i;
188 llvm::SmallVectorImpl<unsigned> &permutation)
const {
190 "NPN classes must have the same number of inputs");
192 "NPN classes must be equivalent for input mapping");
205 permutation.push_back(thisInverse[canonicalPos]);
218 for (uint32_t negMask = 0; negMask < (1u << tt.
numInputs); ++negMask) {
222 auto permutation = identityPermutation(tt.
numInputs);
228 unsigned currentNegMask = permuteNegationMask(negMask, permutation);
231 for (
unsigned outputNegMask = 0; outputNegMask < (1u << tt.
numOutputs);
238 NPNClass candidate(candidateTT, permutation, currentNegMask,
244 canonical = std::move(candidate);
246 }
while (std::next_permutation(permutation.begin(), permutation.end()));
254 os <<
" Input permutation: [";
261 os <<
" Input negation: 0b";
266 os <<
" Output negation: 0b";
271 os <<
" Canonical truth table:\n";
285 {0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
286 0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL,
287 0x00000000FFFFFFFFULL},
288 {0xAAAAAAAAAAAAAAAAULL, 0xCCCCCCCCCCCCCCCCULL, 0xF0F0F0F0F0F0F0F0ULL,
289 0xFF00FF00FF00FF00ULL, 0xFFFF0000FFFF0000ULL,
290 0xFFFFFFFF00000000ULL},
296template <
bool positive>
298 assert(numVars <= 64 &&
"Number of variables too large");
299 assert(varIndex < numVars &&
"Variable index out of bounds");
300 uint64_t numBits = 1u << numVars;
305 uint64_t maskValue =
kVarMasks[positive][varIndex];
308 maskValue &= (1ULL << numBits) - 1;
309 return APInt(numBits, maskValue);
314 uint64_t patternWidth = 1u << (varIndex + 1);
315 APInt
pattern(patternWidth, 0);
318 uint64_t shift = 1u << varIndex;
319 if constexpr (positive) {
321 pattern.setBits(shift, patternWidth);
327 return APInt::getSplat(numBits,
pattern);
332 return createVarMaskImpl<true>(numVars, varIndex);
333 return createVarMaskImpl<false>(numVars, varIndex);
351std::pair<APInt, APInt>
353 assert(numVars <= 64 &&
"Number of variables too large");
354 assert(var < numVars &&
"Variable index out of bounds");
355 assert(f.getBitWidth() == (1u << numVars) &&
"Truth table size mismatch");
356 uint64_t numBits = 1u << numVars;
357 uint64_t shift = 1u << var;
363 APInt blockPattern = APInt::getLowBitsSet(2 * shift, shift);
364 APInt mask0 = APInt::getSplat(numBits, blockPattern);
365 APInt mask1 = mask0.shl(shift);
368 APInt selected0 = f & mask0;
369 APInt selected1 = f & mask1;
372 APInt cof0 = selected0 | selected0.shl(shift);
373 APInt cof1 = selected1 | selected1.lshr(shift);
384 for (
const auto &cube :
cubes) {
385 APInt cubeTT = ~APInt(1 <<
numVars, 0);
386 for (
unsigned i = 0; i <
numVars; ++i) {
387 if (cube.hasLiteral(i))
397 os <<
"SOPForm: " <<
numVars <<
" vars, " <<
cubes.size() <<
" cubes\n";
398 for (
const auto &cube :
cubes) {
400 for (
unsigned i = 0; i <
numVars; ++i) {
401 if (cube.mask & (1ULL << i)) {
402 os << ((cube.inverted & (1ULL << i)) ?
"!" :
"");
403 os <<
"x" << i <<
" ";
452APInt isopImpl(
const APInt &tt,
const APInt &dc,
unsigned numVars,
453 unsigned varIndex,
SOPForm &result) {
454 assert((tt & ~dc).isZero() &&
"tt must be subset of dc");
461 if (dc.isAllOnes()) {
462 result.
cubes.emplace_back();
473 APInt negCof, posCof, negDC, posDC;
474 for (
int i = varIndex - 1; i >= 0; --i) {
477 if (negCof != posCof || negDC != posDC) {
482 assert(var >= 0 &&
"No variable found in support");
485 size_t negBegin = result.
cubes.size();
486 APInt negCover = isopImpl(negCof & ~posDC, negDC, numVars, var, result);
487 size_t negEnd = result.
cubes.size();
490 APInt posCover = isopImpl(posCof & ~negDC, posDC, numVars, var, result);
491 size_t posEnd = result.
cubes.size();
494 APInt remaining = (negCof & ~negCover) | (posCof & ~posCover);
495 APInt sharedCover = isopImpl(remaining, negDC & posDC, numVars, var, result);
498 APInt negMask = createVarMaskImpl<false>(numVars, var);
499 APInt totalCover = sharedCover | (negCover & negMask) | (posCover & ~negMask);
502 for (
size_t i = negBegin; i < negEnd; ++i)
503 result.
cubes[i].setLiteral(var,
true);
505 for (
size_t i = negEnd; i < posEnd; ++i)
506 result.
cubes[i].setLiteral(var,
false);
514 assert((1u << numVars) == truthTable.getBitWidth() &&
515 "Truth table size must match 2^numVars");
518 if (numVars == 0 || truthTable.isZero())
521 (void)isopImpl(truthTable, truthTable, numVars, numVars, sop);
assert(baseType &&"element must be base type")
RewritePatternSet pattern
static APInt createVarMaskImpl(unsigned numVars, unsigned varIndex)
Create a mask for a variable in the truth table.
static constexpr uint64_t kVarMasks[2][6]
Precomputed masks for variables in truth tables up to 6 variables (64 bits).
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
SOPForm extractISOP(const llvm::APInt &truthTable, unsigned numVars)
Extract ISOP (Irredundant Sum-of-Products) from a truth table.
std::pair< llvm::APInt, llvm::APInt > computeCofactors(const llvm::APInt &f, unsigned numVars, unsigned varIndex)
Compute cofactor of a Boolean function for a given variable.
llvm::APInt createVarMask(unsigned numVars, unsigned varIndex, bool positive)
Create a mask for a variable in the truth table.
Represents a boolean function as a truth table.
BinaryTruthTable applyOutputNegation(unsigned negation) const
Apply output negation to create a new truth table.
llvm::APInt table
Truth table data as a packed bit vector.
BinaryTruthTable applyInputNegation(unsigned mask) const
Apply input negation to create a new truth table.
unsigned numInputs
Number of inputs for this boolean function.
void dump(llvm::raw_ostream &os=llvm::errs()) const
Debug dump method for truth tables.
bool isLexicographicallySmaller(const BinaryTruthTable &other) const
Check if this truth table is lexicographically smaller than another.
bool operator==(const BinaryTruthTable &other) const
Equality comparison for truth tables.
llvm::APInt getOutput(const llvm::APInt &input) const
Get the output value for a given input combination.
BinaryTruthTable applyPermutation(ArrayRef< unsigned > permutation) const
Apply input permutation to create a new truth table.
void setOutput(const llvm::APInt &input, const llvm::APInt &output)
Set the output value for a given input combination.
unsigned numOutputs
Number of outputs for this boolean function.
Represents the canonical form of a boolean function under NPN equivalence.
unsigned outputNegation
Output negation mask.
static NPNClass computeNPNCanonicalForm(const BinaryTruthTable &tt)
Compute the canonical NPN form for a given truth table.
void getInputPermutation(const NPNClass &targetNPN, llvm::SmallVectorImpl< unsigned > &permutation) const
Get input permutation from this NPN class to another equivalent NPN class.
BinaryTruthTable truthTable
Canonical truth table.
void dump(llvm::raw_ostream &os=llvm::errs()) const
Debug dump method for NPN classes.
bool equivalentOtherThanPermutation(const NPNClass &other) const
Equality comparison for NPN classes.
llvm::SmallVector< unsigned > inputPermutation
Input permutation applied.
unsigned inputNegation
Input negation mask.
bool isLexicographicallySmaller(const NPNClass &other) const