Patches for building llvm on Solaris x86. Contributed by Nathan Keynes.
[oota-llvm.git] / utils / PerfectShuffle / PerfectShuffle.cpp
index 5fce2a56924f0a68e9a17d6d34963c0ae49a264f..26c4cf44c6e2e01824ba74415423391076ca3f42 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     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.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -16,7 +16,8 @@
 
 #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
@@ -60,9 +61,11 @@ static bool isOnlyLHSMask(unsigned short Mask) {
 /// 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.
@@ -102,9 +105,8 @@ struct Operator {
   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() {
@@ -296,7 +298,6 @@ int main() {
         
       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);
@@ -382,7 +383,9 @@ int main() {
     
     // 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!");
@@ -392,7 +395,7 @@ int main() {
     
     // 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);
@@ -438,37 +441,57 @@ int main() {
 }
 
 
+#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