-//===-- BuildShuffleTable.cpp - Perfect Shuffle Generator -----------------===//
+//===-- PerfectShuffle.cpp - Perfect Shuffle Generator --------------------===//
//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Chris Lattner and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include <iostream>
#include <vector>
-
+#include <cassert>
+#include <cstdlib>
struct Operator;
// Masks are 4-nibble hex numbers. Values 0-7 in any nibble means that it takes
/// getLHSOnlyMask - Given a mask that refers to its LHS and RHS, modify it to
/// refer to the LHS only (for when one argument value is passed into the same
/// function twice).
+#if 0
static unsigned short getLHSOnlyMask(unsigned short Mask) {
return Mask & 0xBBBB; // Keep only LHS and Undefs.
}
+#endif
/// getCompressedMask - Turn a 16-bit uncompressed mask (where each elt uses 4
/// bits) into a compressed 13-bit mask, where each elt is multiplied by 9.
unsigned short OpNum;
const char *Name;
- Operator(unsigned short shufflemask, const char *name)
- : ShuffleMask(shufflemask), Name(name) {
- OpNum = TheOperators.size();
+ Operator(unsigned short shufflemask, const char *name, unsigned opnum)
+ : ShuffleMask(shufflemask), OpNum(opnum), Name(name) {
TheOperators.push_back(this);
}
~Operator() {
for (unsigned opnum = 0, e = TheOperators.size(); opnum != e; ++opnum) {
Operator *Op = TheOperators[opnum];
- unsigned short Mask = Op->ShuffleMask;
// Evaluate op(LHS,LHS)
unsigned ResultMask = Op->getTransformedMask(LHS, LHS);
// Build up the table to emit.
std::cout << "\n// This table is 6561*4 = 26244 bytes in size.\n";
- std::cout << "static const unsigned InstrTab[6561+1] = {\n";
+ std::cout << "static const unsigned PerfectShuffleTable[6561+1] = {\n";
for (unsigned i = 0; i != 0x8889; ++i) {
if (!isValidMask(i)) continue;
// CostSat - The cost of this operation saturated to two bits.
unsigned CostSat = ShufTab[i].Cost;
- if (CostSat > 3) CostSat = 3;
+ if (CostSat > 4) CostSat = 4;
+ if (CostSat == 0) CostSat = 1;
+ --CostSat; // Cost is now between 0-3.
unsigned OpNum = ShufTab[i].Op ? ShufTab[i].Op->OpNum : 0;
assert(OpNum < 16 && "Too few bits to encode operation!");
// Encode this as 2 bits of saturated cost, 4 bits of opcodes, 13 bits of
// LHS, and 13 bits of RHS = 32 bits.
- unsigned Val = (CostSat << 30) | (OpNum << 27) | (LHS << 13) | RHS;
+ unsigned Val = (CostSat << 30) | (OpNum << 26) | (LHS << 13) | RHS;
std::cout << " " << Val << "U,\t// ";
PrintMask(i, std::cout);
}
+#define GENERATE_ALTIVEC
+
+#ifdef GENERATE_ALTIVEC
///===---------------------------------------------------------------------===//
/// The altivec instruction definitions. This is the altivec-specific part of
/// this file.
///===---------------------------------------------------------------------===//
+// Note that the opcode numbers here must match those in the PPC backend.
+enum {
+ OP_COPY = 0, // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3>
+ OP_VMRGHW,
+ OP_VMRGLW,
+ OP_VSPLTISW0,
+ OP_VSPLTISW1,
+ OP_VSPLTISW2,
+ OP_VSPLTISW3,
+ OP_VSLDOI4,
+ OP_VSLDOI8,
+ OP_VSLDOI12
+};
+
struct vmrghw : public Operator {
- vmrghw() : Operator(0x0415, "vmrghw") {}
+ vmrghw() : Operator(0x0415, "vmrghw", OP_VMRGHW) {}
} the_vmrghw;
struct vmrglw : public Operator {
- vmrglw() : Operator(0x2637, "vmrglw") {}
+ vmrglw() : Operator(0x2637, "vmrglw", OP_VMRGLW) {}
} the_vmrglw;
template<unsigned Elt>
struct vspltisw : public Operator {
- vspltisw(const char *N) : Operator(MakeMask(Elt, Elt, Elt, Elt), N) {}
+ vspltisw(const char *N, unsigned Opc)
+ : Operator(MakeMask(Elt, Elt, Elt, Elt), N, Opc) {}
};
-vspltisw<0> the_vspltisw0("vspltisw0");
-vspltisw<1> the_vspltisw1("vspltisw1");
-vspltisw<2> the_vspltisw2("vspltisw2");
-vspltisw<3> the_vspltisw3("vspltisw3");
+vspltisw<0> the_vspltisw0("vspltisw0", OP_VSPLTISW0);
+vspltisw<1> the_vspltisw1("vspltisw1", OP_VSPLTISW1);
+vspltisw<2> the_vspltisw2("vspltisw2", OP_VSPLTISW2);
+vspltisw<3> the_vspltisw3("vspltisw3", OP_VSPLTISW3);
template<unsigned N>
struct vsldoi : public Operator {
- vsldoi(const char *n) : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), n){
+ vsldoi(const char *Name, unsigned Opc)
+ : Operator(MakeMask(N&7, (N+1)&7, (N+2)&7, (N+3)&7), Name, Opc) {
}
};
-vsldoi<1> the_vsldoi1("vsldoi4");
-vsldoi<2> the_vsldoi2("vsldoi8");
-vsldoi<3> the_vsldoi3("vsldoi12");
+vsldoi<1> the_vsldoi1("vsldoi4" , OP_VSLDOI4);
+vsldoi<2> the_vsldoi2("vsldoi8" , OP_VSLDOI8);
+vsldoi<3> the_vsldoi3("vsldoi12", OP_VSLDOI12);
+#endif