svn commit: r193724 - in vendor/llvm/dist: include/llvm/Support lib/CodeGen lib/CodeGen/SelectionDAG test/CodeGen/X86

Ed Schouten ed at FreeBSD.org
Mon Jun 8 15:36:39 UTC 2009


Author: ed
Date: Mon Jun  8 15:36:37 2009
New Revision: 193724
URL: http://svn.freebsd.org/changeset/base/193724

Log:
  Import LLVM r73070.
  
  Now I'm going to stop importing code for a while. I spent a lot of time
  the last couple of days figuring out which LLVM commit caused g++ to
  miscompile, which in its turn caused Clang to miscompile the next build.
  I had to run `make buildworld' twice each time I bisected a revision.

Added:
  vendor/llvm/dist/test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll
Modified:
  vendor/llvm/dist/include/llvm/Support/OutputBuffer.h
  vendor/llvm/dist/lib/CodeGen/ELF.h
  vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.cpp
  vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.h
  vendor/llvm/dist/lib/CodeGen/ELFWriter.cpp
  vendor/llvm/dist/lib/CodeGen/ELFWriter.h
  vendor/llvm/dist/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp

Modified: vendor/llvm/dist/include/llvm/Support/OutputBuffer.h
==============================================================================
--- vendor/llvm/dist/include/llvm/Support/OutputBuffer.h	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/include/llvm/Support/OutputBuffer.h	Mon Jun  8 15:36:37 2009	(r193724)
@@ -134,11 +134,22 @@ namespace llvm {
       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
     }
+    void fixxword(uint64_t X, unsigned Offset) {
+      unsigned char *P = &Output[Offset];
+      P[0] = (X >> (isLittleEndian ?  0 : 56)) & 255;
+      P[1] = (X >> (isLittleEndian ?  8 : 48)) & 255;
+      P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255;
+      P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255;
+      P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255;
+      P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255;
+      P[6] = (X >> (isLittleEndian ? 48 :  8)) & 255;
+      P[7] = (X >> (isLittleEndian ? 56 :  0)) & 255;
+    }
     void fixaddr(uint64_t X, unsigned Offset) {
       if (!is64Bit)
         fixword((unsigned)X, Offset);
       else
-        assert(0 && "Emission of 64-bit data not implemented yet!");
+        fixxword(X, Offset);
     }
 
     unsigned char &operator[](unsigned Index) {

Modified: vendor/llvm/dist/lib/CodeGen/ELF.h
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/ELF.h	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/ELF.h	Mon Jun  8 15:36:37 2009	(r193724)
@@ -21,6 +21,7 @@
 #ifndef CODEGEN_ELF_H
 #define CODEGEN_ELF_H
 
+#include "llvm/CodeGen/MachineRelocation.h"
 #include "llvm/Support/DataTypes.h"
 #include <cstring>
 
@@ -64,6 +65,36 @@ namespace llvm {
     EV_CURRENT = 1
   };
 
+  struct ELFHeader {
+    // e_machine - This field is the target specific value to emit as the
+    // e_machine member of the ELF header.
+    unsigned short e_machine;
+
+    // e_flags - The machine flags for the target.  This defaults to zero.
+    unsigned e_flags;
+
+    // e_size - Holds the ELF header's size in bytes
+    unsigned e_ehsize;
+
+    // Endianess and ELF Class (64 or 32 bits)
+    unsigned ByteOrder;
+    unsigned ElfClass;
+
+    unsigned getByteOrder() const { return ByteOrder; }
+    unsigned getElfClass() const { return ElfClass; }
+    unsigned getSize() const { return e_ehsize; }
+    unsigned getMachine() const { return e_machine; }
+    unsigned getFlags() const { return e_flags; }
+
+    ELFHeader(unsigned short machine, unsigned flags,
+              bool is64Bit, bool isLittleEndian)
+      : e_machine(machine), e_flags(flags) {
+        ElfClass  = is64Bit ? ELFCLASS64 : ELFCLASS32;
+        ByteOrder = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
+        e_ehsize  = is64Bit ? 64 : 52;
+      }
+  };
+
   /// ELFSection - This struct contains information about each section that is
   /// emitted to the file.  This is eventually turned into the section header
   /// table at the end of the file.
@@ -118,11 +149,11 @@ namespace llvm {
 
     // Special section indices.
     enum {
-      SHN_UNDEF     = 0,      // Undefined, missing, irrelevant, or meaningless
+      SHN_UNDEF     = 0,      // Undefined, missing, irrelevant
       SHN_LORESERVE = 0xff00, // Lowest reserved index
       SHN_LOPROC    = 0xff00, // Lowest processor-specific index
       SHN_HIPROC    = 0xff1f, // Highest processor-specific index
-      SHN_ABS       = 0xfff1, // Symbol has absolute value; does not need relocation
+      SHN_ABS       = 0xfff1, // Symbol has absolute value; no relocation
       SHN_COMMON    = 0xfff2, // FORTRAN COMMON or C external global variables
       SHN_HIRESERVE = 0xffff  // Highest reserved index
     };
@@ -134,6 +165,15 @@ namespace llvm {
     /// up for emission to the file.
     std::vector<unsigned char> SectionData;
 
+    /// Relocations - The relocations that we have encountered so far in this 
+    /// section that we will need to convert to Elf relocation entries when
+    /// the file is written.
+    std::vector<MachineRelocation> Relocations;
+
+    /// Section Header Size 
+    static unsigned getSectionHdrSize(bool is64Bit)
+      { return is64Bit ? 64 : 40; }
+
     ELFSection(const std::string &name)
       : Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
         Link(0), Info(0), Align(0), EntSize(0) {}
@@ -167,7 +207,7 @@ namespace llvm {
       STT_FILE = 4 
     };
 
-    ELFSym(const GlobalValue *gv) : GV(gv), Value(0),
+    ELFSym(const GlobalValue *gv) : GV(gv), NameIdx(0), Value(0),
                                     Size(0), Info(0), Other(0),
                                     SectionIdx(ELFSection::SHN_UNDEF) {}
 

Modified: vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.cpp
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.cpp	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.cpp	Mon Jun  8 15:36:37 2009	(r193724)
@@ -73,6 +73,9 @@ bool ELFCodeEmitter::finishFunction(Mach
   // Add a symbol to represent the function.
   ELFSym FnSym(MF.getFunction());
 
+  // Update Section Size
+  ES->Size = CurBufferPtr - BufferBegin;
+
   // Figure out the binding (linkage) of the symbol.
   switch (MF.getFunction()->getLinkage()) {
   default:
@@ -106,8 +109,29 @@ bool ELFCodeEmitter::finishFunction(Mach
   // Finally, add it to the symtab.
   EW.SymbolTable.push_back(FnSym);
 
-  // Update Section Size
-  ES->Size = CurBufferPtr - BufferBegin;
+  // Relocations
+  // -----------
+  // If we have emitted any relocations to function-specific objects such as 
+  // basic blocks, constant pools entries, or jump tables, record their
+  // addresses now so that we can rewrite them with the correct addresses
+  // later.
+  for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
+    MachineRelocation &MR = Relocations[i];
+    intptr_t Addr;
+
+    if (MR.isBasicBlock()) {
+      Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
+      MR.setConstantVal(ES->SectionIdx);
+      MR.setResultPointer((void*)Addr);
+    } else if (MR.isGlobalValue()) {
+      EW.PendingGlobals.insert(MR.getGlobalValue());
+    } else {
+      assert(0 && "Unhandled relocation type");
+    }
+    ES->Relocations.push_back(MR);
+  }
+  Relocations.clear();
+
   return false;
 }
 

Modified: vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.h
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.h	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/ELFCodeEmitter.h	Mon Jun  8 15:36:37 2009	(r193724)
@@ -20,8 +20,24 @@ namespace llvm {
   /// emit the code for functions to the ELF file.
   class ELFCodeEmitter : public MachineCodeEmitter {
     ELFWriter &EW;
+
+    /// Target machine description
     TargetMachine &TM;
-    ELFSection *ES;  // Section to write to.
+
+    /// Section containing code for functions
+    ELFSection *ES;
+
+    /// Relocations - These are the relocations that the function needs, as
+    /// emitted.
+    std::vector<MachineRelocation> Relocations;
+
+    /// MBBLocations - This vector is a mapping from MBB ID's to their address.
+    /// It is filled in by the StartMachineBasicBlock callback and queried by
+    /// the getMachineBasicBlockAddress callback.
+    std::vector<uintptr_t> MBBLocations;
+
+    /// FnStartPtr - Pointer to the start location of the current function
+    /// in the buffer
     uint8_t *FnStartPtr;
   public:
     explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
@@ -30,10 +46,19 @@ namespace llvm {
     bool finishFunction(MachineFunction &F);
 
     void addRelocation(const MachineRelocation &MR) {
-      assert(0 && "relo not handled yet!");
+      Relocations.push_back(MR);
     }
 
     virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {
+      if (MBBLocations.size() <= (unsigned)MBB->getNumber())
+        MBBLocations.resize((MBB->getNumber()+1)*2);
+      MBBLocations[MBB->getNumber()] = getCurrentPCOffset();
+    }
+
+    virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) {
+      assert(MBBLocations.size() > (unsigned)MBB->getNumber() && 
+             MBBLocations[MBB->getNumber()] && "MBB not emitted!");
+      return MBBLocations[MBB->getNumber()];
     }
 
     virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {

Modified: vendor/llvm/dist/lib/CodeGen/ELFWriter.cpp
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/ELFWriter.cpp	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/ELFWriter.cpp	Mon Jun  8 15:36:37 2009	(r193724)
@@ -31,6 +31,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "elfwriter"
+
 #include "ELFWriter.h"
 #include "ELFCodeEmitter.h"
 #include "ELF.h"
@@ -48,6 +50,7 @@
 #include "llvm/Support/OutputBuffer.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
 #include <list>
 using namespace llvm;
 
@@ -67,13 +70,13 @@ MachineCodeEmitter *llvm::AddELFWriter(P
 //===----------------------------------------------------------------------===//
 
 ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
-  : MachineFunctionPass(&ID), O(o), TM(tm) {
-  e_flags = 0;  // e_flags defaults to 0, no flags.
-  e_machine = TM.getELFWriterInfo()->getEMachine();
-
+  : MachineFunctionPass(&ID), O(o), TM(tm), ElfHdr() {
   is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
   isLittleEndian = TM.getTargetData()->isLittleEndian();
 
+  ElfHdr = new ELFHeader(TM.getELFWriterInfo()->getEMachine(), 0,
+                         is64Bit, isLittleEndian);
+
   // Create the machine code emitter object for this target.
   MCE = new ELFCodeEmitter(*this);
   NumSections = 0;
@@ -81,6 +84,7 @@ ELFWriter::ELFWriter(raw_ostream &o, Tar
 
 ELFWriter::~ELFWriter() {
   delete MCE;
+  delete ElfHdr;
 }
 
 // doInitialization - Emit the file header and all of the global variables for
@@ -92,9 +96,6 @@ bool ELFWriter::doInitialization(Module 
   std::vector<unsigned char> &FH = FileHeader;
   OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
 
-  unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
-  unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
-
   // ELF Header
   // ----------
   // Fields e_shnum e_shstrndx are only known after all section have
@@ -111,26 +112,26 @@ bool ELFWriter::doInitialization(Module 
   FHOut.outbyte('L');  // e_ident[EI_MAG2]
   FHOut.outbyte('F');  // e_ident[EI_MAG3]
 
-  FHOut.outbyte(ElfClass);   // e_ident[EI_CLASS]
-  FHOut.outbyte(ElfEndian);  // e_ident[EI_DATA]
-  FHOut.outbyte(EV_CURRENT); // e_ident[EI_VERSION]
+  FHOut.outbyte(ElfHdr->getElfClass());   // e_ident[EI_CLASS]
+  FHOut.outbyte(ElfHdr->getByteOrder());  // e_ident[EI_DATA]
+  FHOut.outbyte(EV_CURRENT);  // e_ident[EI_VERSION]
 
   FH.resize(16);  // e_ident[EI_NIDENT-EI_PAD]
 
-  FHOut.outhalf(ET_REL);     // e_type
-  FHOut.outhalf(e_machine);  // e_machine = target
-  FHOut.outword(EV_CURRENT); // e_version
-  FHOut.outaddr(0);          // e_entry = 0 -> no entry point in .o file
-  FHOut.outaddr(0);          // e_phoff = 0 -> no program header for .o
-
+  FHOut.outhalf(ET_REL);               // e_type
+  FHOut.outhalf(ElfHdr->getMachine()); // e_machine = target
+  FHOut.outword(EV_CURRENT);           // e_version
+  FHOut.outaddr(0);                    // e_entry = 0, no entry point in .o file
+  FHOut.outaddr(0);                    // e_phoff = 0, no program header for .o
   ELFHdr_e_shoff_Offset = FH.size();
-  FHOut.outaddr(0);                 // e_shoff = sec hdr table off in bytes
-  FHOut.outword(e_flags);           // e_flags = whatever the target wants
+  FHOut.outaddr(0);                    // e_shoff = sec hdr table off in bytes
+  FHOut.outword(ElfHdr->getFlags());   // e_flags = whatever the target wants
+  FHOut.outhalf(ElfHdr->getSize());    // e_ehsize = ELF header size
+  FHOut.outhalf(0);                    // e_phentsize = prog header entry size
+  FHOut.outhalf(0);                    // e_phnum = # prog header entries = 0
 
-  FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size
-  FHOut.outhalf(0);                 // e_phentsize = prog header entry size
-  FHOut.outhalf(0);                 // e_phnum     = # prog header entries = 0
-  FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size
+  // e_shentsize = Section header entry size
+  FHOut.outhalf(ELFSection::getSectionHdrSize(is64Bit));
 
   // e_shnum     = # of section header ents
   ELFHdr_e_shnum_Offset = FH.size();
@@ -251,9 +252,10 @@ bool ELFWriter::doFinalization(Module &M
   // Emit the symbol table now, if non-empty.
   EmitSymbolTable();
 
-  // FIXME: Emit the relocations now.
+  // Emit the relocation sections.
+  EmitRelocations();
 
-  // Emit the string table for the sections in the ELF file we have.
+  // Emit the string table for the sections in the ELF file.
   EmitSectionTableStringTable();
 
   // Emit the sections to the .o file, and emit the section table for the file.
@@ -268,6 +270,10 @@ bool ELFWriter::doFinalization(Module &M
   return false;
 }
 
+/// EmitRelocations - Emit relocations
+void ELFWriter::EmitRelocations() {
+}
+
 /// EmitSymbolTable - If the current symbol table is non-empty, emit the string
 /// table for it and then the symbol table itself.
 void ELFWriter::EmitSymbolTable() {
@@ -284,7 +290,6 @@ void ELFWriter::EmitSymbolTable() {
 
   // Set the zero'th symbol to a null byte, as required.
   StrTabOut.outbyte(0);
-  SymbolTable[0].NameIdx = 0;
   unsigned Index = 1;
   for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) {
     // Use the name mangler to uniquify the LLVM symbol.
@@ -312,9 +317,9 @@ void ELFWriter::EmitSymbolTable() {
   // string table of each symbol, emit the symbol table itself.
   ELFSection &SymTab = getSection(".symtab", ELFSection::SHT_SYMTAB, 0);
   SymTab.Align = is64Bit ? 8 : 4;
-  SymTab.Link = SymTab.SectionIdx;     // Section Index of .strtab.
-  SymTab.Info = FirstNonLocalSymbol;   // First non-STB_LOCAL symbol.
-  SymTab.EntSize = 16; // Size of each symtab entry. FIXME: wrong for ELF64
+  SymTab.Link = StrTab.SectionIdx;      // Section Index of .strtab.
+  SymTab.Info = FirstNonLocalSymbol;    // First non-STB_LOCAL symbol.
+  SymTab.EntSize = is64Bit ? 24 : 16;   // Size of each symtab entry. 
   DataBuffer &SymTabBuf = SymTab.SectionData;
   OutputBuffer SymTabOut(SymTabBuf, is64Bit, isLittleEndian);
 
@@ -391,11 +396,21 @@ void ELFWriter::OutputSectionsAndSection
   // Emit all of the section data in order.
   for (std::list<ELFSection>::iterator I = SectionList.begin(),
          E = SectionList.end(); I != E; ++I) {
+
+    // Section idx 0 has 0 offset
+    if (!I->SectionIdx)
+      continue;
+
+    // Update Section size
+    if (!I->Size)
+      I->Size = I->SectionData.size();
+
     // Align FileOff to whatever the alignment restrictions of the section are.
     if (I->Align)
       FileOff = (FileOff+I->Align-1) & ~(I->Align-1);
+
     I->Offset = FileOff;
-    FileOff += I->SectionData.size();
+    FileOff += I->Size;
   }
 
   // Align Section Header.
@@ -429,19 +444,23 @@ void ELFWriter::OutputSectionsAndSection
       for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1);
            FileOff != NewFileOff; ++FileOff)
         O << (char)0xAB;
-    O.write((char*)&S.SectionData[0], S.SectionData.size());
-    FileOff += S.SectionData.size();
+    O.write((char*)&S.SectionData[0], S.Size);
+
+    DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.Name
+         << ", Size: " << S.Size << ", Offset: " << S.Offset << "\n";
+
+    FileOff += S.Size;
 
     TableOut.outword(S.NameIdx);  // sh_name - Symbol table name idx
     TableOut.outword(S.Type);     // sh_type - Section contents & semantics
-    TableOut.outword(S.Flags);    // sh_flags - Section flags.
+    TableOut.outaddr(S.Flags);    // sh_flags - Section flags.
     TableOut.outaddr(S.Addr);     // sh_addr - The mem addr this section is in.
     TableOut.outaddr(S.Offset);   // sh_offset - Offset from the file start.
-    TableOut.outword(S.Size);     // sh_size - The section size.
+    TableOut.outaddr(S.Size);     // sh_size - The section size.
     TableOut.outword(S.Link);     // sh_link - Section header table index link.
     TableOut.outword(S.Info);     // sh_info - Auxillary information.
-    TableOut.outword(S.Align);    // sh_addralign - Alignment of section.
-    TableOut.outword(S.EntSize);  // sh_entsize - Size of entries in the section
+    TableOut.outaddr(S.Align);    // sh_addralign - Alignment of section.
+    TableOut.outaddr(S.EntSize);  // sh_entsize - Size of entries in the section
 
     SectionList.pop_front();
   }

Modified: vendor/llvm/dist/lib/CodeGen/ELFWriter.h
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/ELFWriter.h	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/ELFWriter.h	Mon Jun  8 15:36:37 2009	(r193724)
@@ -14,6 +14,7 @@
 #ifndef ELFWRITER_H
 #define ELFWRITER_H
 
+#include "llvm/ADT/SetVector.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "ELF.h"
 #include <list>
@@ -46,15 +47,12 @@ namespace llvm {
 
   protected:
     /// Output stream to send the resultant object file to.
-    ///
     raw_ostream &O;
 
     /// Target machine description.
-    ///
     TargetMachine &TM;
 
     /// Mang - The object used to perform name mangling for this module.
-    ///
     Mangler *Mang;
 
     /// MCE - The MachineCodeEmitter object that we are exposing to emit machine
@@ -62,19 +60,8 @@ namespace llvm {
     ELFCodeEmitter *MCE;
 
     //===------------------------------------------------------------------===//
-    // Properties to be set by the derived class ctor, used to configure the
-    // ELFWriter.
-
-    // e_machine - This field is the target specific value to emit as the
-    // e_machine member of the ELF header.
-    unsigned short e_machine;
-
-    // e_flags - The machine flags for the target.  This defaults to zero.
-    unsigned e_flags;
-
-    //===------------------------------------------------------------------===//
     // Properties inferred automatically from the target machine.
-    //
+    //===------------------------------------------------------------------===//
 
     /// is64Bit/isLittleEndian - This information is inferred from the target
     /// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
@@ -95,6 +82,9 @@ namespace llvm {
     // as well!).
     DataBuffer FileHeader;
 
+    /// ElfHdr - Hold information about the ELF Header
+    ELFHeader *ElfHdr;
+
     /// SectionList - This is the list of sections that we have emitted to the
     /// file.  Once the file has been completely built, the section header table
     /// is constructed from this info.
@@ -140,6 +130,11 @@ namespace llvm {
     /// local symbols first in the list).
     std::vector<ELFSym> SymbolTable;
 
+    /// PendingSyms - This is a list of externally defined symbols that we have
+    /// been asked to emit, but have not seen a reference to.  When a reference
+    /// is seen, the symbol will move from this list to the SymbolTable.
+    SetVector<GlobalValue*> PendingGlobals;
+
     // As we complete the ELF file, we need to update fields in the ELF header
     // (e.g. the location of the section table).  These members keep track of
     // the offset in ELFHeader of these various pieces to update and other
@@ -149,9 +144,8 @@ namespace llvm {
     unsigned ELFHdr_e_shnum_Offset;     // e_shnum    in ELF header.
   private:
     void EmitGlobal(GlobalVariable *GV);
-
     void EmitSymbolTable();
-
+    void EmitRelocations();
     void EmitSectionTableStringTable();
     void OutputSectionsAndSectionTable();
   };

Modified: vendor/llvm/dist/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
==============================================================================
--- vendor/llvm/dist/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp	Mon Jun  8 15:26:09 2009	(r193723)
+++ vendor/llvm/dist/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp	Mon Jun  8 15:36:37 2009	(r193724)
@@ -92,6 +92,26 @@ void DAGTypeLegalizer::ExpandRes_BIT_CON
     }
   }
 
+  if (InVT.isVector() && OutVT.isInteger()) {
+    // Handle cases like i64 = BIT_CONVERT v1i64 on x86, where the operand
+    // is legal but the result is not.
+    MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OutVT), 2);
+
+    if (isTypeLegal(NVT)) {
+      SDValue CastInOp = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, InOp);
+      MVT EltNVT = NVT.getVectorElementType();
+      Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltNVT, CastInOp,
+                       DAG.getIntPtrConstant(0));
+      Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltNVT, CastInOp,
+                       DAG.getIntPtrConstant(1));
+
+      if (TLI.isBigEndian())
+        std::swap(Lo, Hi);
+      
+      return;
+    }
+  }
+
   // Lower the bit-convert to a store/load from the stack.
   assert(NOutVT.isByteSized() && "Expanded type not byte sized!");
 

Added: vendor/llvm/dist/test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor/llvm/dist/test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll	Mon Jun  8 15:36:37 2009	(r193724)
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+mmx | grep movl | count 2
+
+define i64 @a(i32 %a, i32 %b) nounwind readnone {
+entry:
+	%0 = insertelement <2 x i32> undef, i32 %a, i32 0		; <<2 x i32>> [#uses=1]
+	%1 = insertelement <2 x i32> %0, i32 %b, i32 1		; <<2 x i32>> [#uses=1]
+	%conv = bitcast <2 x i32> %1 to i64		; <i64> [#uses=1]
+	ret i64 %conv
+}
+


More information about the svn-src-vendor mailing list