[llvm-commits] [llvm] r57663 - in /llvm/trunk: CMakeLists.txt Makefile.rules lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/add-trick32.ll test/CodeGen/X86/add-trick64.ll test/TableGen/2006-09-18-LargeInt.td utils/TableGen/DAGISelEmitter.cpp utils/TableGen/Record.cpp utils/TableGen/Record.h utils/TableGen/RegisterInfoEmitter.cpp utils/TableGen/TGLexer.cpp utils/TableGen/TGLexer.h utils/TableGen/TGParser.cpp

Dan Gohman gohman at apple.com
Thu Oct 16 18:33:44 PDT 2008


Author: djg
Date: Thu Oct 16 20:33:43 2008
New Revision: 57663

URL: http://llvm.org/viewvc/llvm-project?rev=57663&view=rev
Log:
Fun x86 encoding tricks: when adding an immediate value of 128,
use a SUB instruction instead of an ADD, because -128 can be
encoded in an 8-bit signed immediate field, while +128 can't be.
This avoids the need for a 32-bit immediate field in this case.

A similar optimization applies to 64-bit adds with 0x80000000,
with the 32-bit signed immediate field.

To support this, teach tablegen how to handle 64-bit constants.

Added:
    llvm/trunk/test/CodeGen/X86/add-trick32.ll
    llvm/trunk/test/CodeGen/X86/add-trick64.ll
Modified:
    llvm/trunk/CMakeLists.txt
    llvm/trunk/Makefile.rules
    llvm/trunk/lib/Target/X86/X86Instr64bit.td
    llvm/trunk/lib/Target/X86/X86InstrInfo.td
    llvm/trunk/test/TableGen/2006-09-18-LargeInt.td
    llvm/trunk/utils/TableGen/DAGISelEmitter.cpp
    llvm/trunk/utils/TableGen/Record.cpp
    llvm/trunk/utils/TableGen/Record.h
    llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp
    llvm/trunk/utils/TableGen/TGLexer.cpp
    llvm/trunk/utils/TableGen/TGLexer.h
    llvm/trunk/utils/TableGen/TGParser.cpp

Modified: llvm/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CMakeLists.txt?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/CMakeLists.txt (original)
+++ llvm/trunk/CMakeLists.txt Thu Oct 16 20:33:43 2008
@@ -80,6 +80,7 @@
 # set(CMAKE_VERBOSE_MAKEFILE true)
 
 add_definitions( -D__STDC_LIMIT_MACROS )
+add_definitions( -D__STDC_CONSTANT_MACROS )
 
 if( LLVM_ON_UNIX )
   add_definitions( -DLLVM_ON_UNIX )

Modified: llvm/trunk/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/Makefile.rules (original)
+++ llvm/trunk/Makefile.rules Thu Oct 16 20:33:43 2008
@@ -483,7 +483,7 @@
 endif
 
 LD.Flags      += -L$(LibDir) -L$(LLVMLibDir) 
-CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS
+CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
 # All -I flags should go here, so that they don't confuse llvm-config.
 CPP.Flags     += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \
 	         $(patsubst %,-I%/include,\

Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original)
+++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Thu Oct 16 20:33:43 2008
@@ -61,13 +61,6 @@
   return (int64_t)N->getZExtValue() == (int8_t)N->getZExtValue();
 }]>;
 
-def i64immFFFFFFFF  : PatLeaf<(i64 imm), [{
-  // i64immFFFFFFFF - True if this is a specific constant we can't write in
-  // tblgen files.
-  return N->getZExtValue() == 0x00000000FFFFFFFFULL;
-}]>;
-
-
 def sextloadi64i8  : PatFrag<(ops node:$ptr), (i64 (sextloadi8 node:$ptr))>;
 def sextloadi64i16 : PatFrag<(ops node:$ptr), (i64 (sextloadi16 node:$ptr))>;
 def sextloadi64i32 : PatFrag<(ops node:$ptr), (i64 (sextloadi32 node:$ptr))>;
@@ -1323,8 +1316,22 @@
 // Some peepholes
 //===----------------------------------------------------------------------===//
 
+// Odd encoding trick: -128 fits into an 8-bit immediate field while
+// +128 doesn't, so in this special case use a sub instead of an add.
+def : Pat<(add GR64:$src1, 128),
+          (SUB64ri8 GR64:$src1, -128)>;
+def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst),
+          (SUB64mi8 addr:$dst, -128)>;
+
+// The same trick applies for 32-bit immediate fields in 64-bit
+// instructions.
+def : Pat<(add GR64:$src1, 0x0000000080000000),
+          (SUB64ri32 GR64:$src1, 0xffffffff80000000)>;
+def : Pat<(store (add (loadi64 addr:$dst), 0x00000000800000000), addr:$dst),
+          (SUB64mi32 addr:$dst, 0xffffffff80000000)>;
+
 // r & (2^32-1) ==> movz
-def : Pat<(and GR64:$src, i64immFFFFFFFF),
+def : Pat<(and GR64:$src, 0x00000000FFFFFFFF),
           (MOVZX64rr32 (i32 (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit)))>;
 // r & (2^16-1) ==> movz
 def : Pat<(and GR64:$src, 0xffff),

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Thu Oct 16 20:33:43 2008
@@ -2911,6 +2911,17 @@
 // Some peepholes
 //===----------------------------------------------------------------------===//
 
+// Odd encoding trick: -128 fits into an 8-bit immediate field while
+// +128 doesn't, so in this special case use a sub instead of an add.
+def : Pat<(add GR16:$src1, 128),
+          (SUB16ri8 GR16:$src1, -128)>;
+def : Pat<(store (add (loadi16 addr:$dst), 128), addr:$dst),
+          (SUB16mi8 addr:$dst, -128)>;
+def : Pat<(add GR32:$src1, 128),
+          (SUB32ri8 GR32:$src1, -128)>;
+def : Pat<(store (add (loadi32 addr:$dst), 128), addr:$dst),
+          (SUB32mi8 addr:$dst, -128)>;
+
 // r & (2^16-1) ==> movz
 def : Pat<(and GR32:$src1, 0xffff),
           (MOVZX32rr16 (i16 (EXTRACT_SUBREG GR32:$src1, x86_subreg_16bit)))>;

Added: llvm/trunk/test/CodeGen/X86/add-trick32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/add-trick32.ll?rev=57663&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/add-trick32.ll (added)
+++ llvm/trunk/test/CodeGen/X86/add-trick32.ll Thu Oct 16 20:33:43 2008
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llc -march=x86 > %t
+; RUN: not grep add %t
+; RUN: grep subl %t | count 1
+
+; The immediate can be encoded in a smaller way if the
+; instruction is a sub instead of an add.
+
+define i32 @foo(i32 inreg %a) nounwind {
+  %b = add i32 %a, 128
+  ret i32 %b
+}

Added: llvm/trunk/test/CodeGen/X86/add-trick64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/add-trick64.ll?rev=57663&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/add-trick64.ll (added)
+++ llvm/trunk/test/CodeGen/X86/add-trick64.ll Thu Oct 16 20:33:43 2008
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -march=x86-64 > %t
+; RUN: not grep add %t
+; RUN: grep subq %t | count 2
+
+; The immediate can be encoded in a smaller way if the
+; instruction is a sub instead of an add.
+
+define i64 @foo(i64 inreg %a) nounwind {
+  %b = add i64 %a, 2147483648
+  ret i64 %b
+}
+define i64 @bar(i64 inreg %a) nounwind {
+  %b = add i64 %a, 128
+  ret i64 %b
+}

Modified: llvm/trunk/test/TableGen/2006-09-18-LargeInt.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/2006-09-18-LargeInt.td?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/test/TableGen/2006-09-18-LargeInt.td (original)
+++ llvm/trunk/test/TableGen/2006-09-18-LargeInt.td Thu Oct 16 20:33:43 2008
@@ -1,4 +1,4 @@
-// RUN: tblgen %s | grep -- -65536
+// RUN: tblgen %s | grep -- 4294901760
 
 def X {
   int Y = 0xFFFF0000;

Modified: llvm/trunk/utils/TableGen/DAGISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelEmitter.cpp?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelEmitter.cpp Thu Oct 16 20:33:43 2008
@@ -734,7 +734,8 @@
         emitCode("int64_t CN"+utostr(CTmp)+" = cast<ConstantSDNode>("+
                  RootName + ")->getSExtValue();");
         
-        emitCheck("CN" + utostr(CTmp) + " == " +itostr(II->getValue()));
+        emitCheck("CN" + utostr(CTmp) + " == "
+                  "INT64_C(" +itostr(II->getValue()) + ")");
       } else {
 #ifndef NDEBUG
         Child->dump();

Modified: llvm/trunk/utils/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/Record.cpp (original)
+++ llvm/trunk/utils/TableGen/Record.cpp Thu Oct 16 20:33:43 2008
@@ -35,7 +35,7 @@
 }
 
 Init *BitRecTy::convertValue(IntInit *II) {
-  int Val = II->getValue();
+  int64_t Val = II->getValue();
   if (Val != 0 && Val != 1) return 0;  // Only accept 0 or 1 for a bit!
 
   return new BitInit(Val != 0);
@@ -116,7 +116,7 @@
 }
 
 Init *IntRecTy::convertValue(BitsInit *BI) {
-  int Result = 0;
+  int64_t Result = 0;
   for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
     if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) {
       Result |= Bit->getValue() << i;
@@ -262,7 +262,7 @@
 
 bool BitsInit::printInHex(std::ostream &OS) const {
   // First, attempt to convert the value into an integer value...
-  int Result = 0;
+  int64_t Result = 0;
   for (unsigned i = 0, e = getNumBits(); i != e; ++i)
     if (BitInit *Bit = dynamic_cast<BitInit*>(getBit(i))) {
       Result |= Bit->getValue() << i;
@@ -338,11 +338,11 @@
   BitsInit *BI = new BitsInit(Bits.size());
 
   for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
-    if (Bits[i] >= 32) {
+    if (Bits[i] >= 64) {
       delete BI;
       return 0;
     }
-    BI->setBit(i, new BitInit(Value & (1 << Bits[i])));
+    BI->setBit(i, new BitInit(Value & (INT64_C(1) << Bits[i])));
   }
   return BI;
 }
@@ -443,13 +443,13 @@
     IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
     IntInit *RHSi = dynamic_cast<IntInit*>(RHS);
     if (LHSi && RHSi) {
-      int LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
-      int Result;
+      int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
+      int64_t Result;
       switch (getOpcode()) {
       default: assert(0 && "Bad opcode!");
       case SHL: Result = LHSv << RHSv; break;
       case SRA: Result = LHSv >> RHSv; break;
-      case SRL: Result = (unsigned)LHSv >> (unsigned)RHSv; break;
+      case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
       }
       return new IntInit(Result);
     }
@@ -861,10 +861,10 @@
 }
 
 /// getValueAsInt - This method looks up the specified field and returns its
-/// value as an int, throwing an exception if the field does not exist or if
+/// value as an int64_t, throwing an exception if the field does not exist or if
 /// the value is not the right type.
 ///
-int Record::getValueAsInt(const std::string &FieldName) const {
+int64_t Record::getValueAsInt(const std::string &FieldName) const {
   const RecordVal *R = getValue(FieldName);
   if (R == 0 || R->getValue() == 0)
     throw "Record `" + getName() + "' does not have a field named `" +
@@ -880,10 +880,10 @@
 /// its value as a vector of integers, throwing an exception if the field does
 /// not exist or if the value is not the right type.
 ///
-std::vector<int> 
+std::vector<int64_t> 
 Record::getValueAsListOfInts(const std::string &FieldName) const {
   ListInit *List = getValueAsListInit(FieldName);
-  std::vector<int> Ints;
+  std::vector<int64_t> Ints;
   for (unsigned i = 0; i < List->getSize(); i++) {
     if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
       Ints.push_back(II->getValue());

Modified: llvm/trunk/utils/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/Record.h (original)
+++ llvm/trunk/utils/TableGen/Record.h Thu Oct 16 20:33:43 2008
@@ -565,11 +565,11 @@
 /// IntInit - 7 - Represent an initalization by a literal integer value.
 ///
 class IntInit : public Init {
-  int Value;
+  int64_t Value;
 public:
-  explicit IntInit(int V) : Value(V) {}
+  explicit IntInit(int64_t V) : Value(V) {}
 
-  int getValue() const { return Value; }
+  int64_t getValue() const { return Value; }
 
   virtual Init *convertInitializerTo(RecTy *Ty) {
     return Ty->convertValue(this);
@@ -1082,7 +1082,7 @@
   /// its value as a vector of integers, throwing an exception if the field does
   /// not exist or if the value is not the right type.
   ///
-  std::vector<int> getValueAsListOfInts(const std::string &FieldName) const;
+  std::vector<int64_t> getValueAsListOfInts(const std::string &FieldName) const;
   
   /// getValueAsDef - This method looks up the specified field and returns its
   /// value as a Record, throwing an exception if the field does not exist or if
@@ -1097,10 +1097,10 @@
   bool getValueAsBit(const std::string &FieldName) const;
 
   /// getValueAsInt - This method looks up the specified field and returns its
-  /// value as an int, throwing an exception if the field does not exist or if
-  /// the value is not the right type.
+  /// value as an int64_t, throwing an exception if the field does not exist or
+  /// if the value is not the right type.
   ///
-  int getValueAsInt(const std::string &FieldName) const;
+  int64_t getValueAsInt(const std::string &FieldName) const;
 
   /// getValueAsDag - This method looks up the specified field and returns its
   /// value as an Dag, throwing an exception if the field does not exist or if

Modified: llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/RegisterInfoEmitter.cpp Thu Oct 16 20:33:43 2008
@@ -422,7 +422,7 @@
   std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs;
   std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases;
   std::map<Record*, std::vector<std::pair<int, Record*> > > SubRegVectors;
-  typedef std::map<Record*, std::vector<int>, LessRecord> DwarfRegNumsMapTy;
+  typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
   DwarfRegNumsMapTy DwarfRegNums;
   
   const std::vector<CodeGenRegister> &Regs = Target.getRegisters();
@@ -685,7 +685,7 @@
   unsigned maxLength = 0;
   for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
     Record *Reg = Registers[i].TheDef;
-    std::vector<int> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+    std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
     maxLength = std::max((size_t)maxLength, RegNums.size());
     if (DwarfRegNums.count(Reg))
       cerr << "Warning: DWARF numbers for register " << getQualifiedName(Reg)

Modified: llvm/trunk/utils/TableGen/TGLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGLexer.cpp?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGLexer.cpp (original)
+++ llvm/trunk/utils/TableGen/TGLexer.cpp Thu Oct 16 20:33:43 2008
@@ -20,6 +20,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#include <cerrno>
 using namespace llvm;
 
 TGLexer::TGLexer(MemoryBuffer *StartBuf) : CurLineNo(1), CurBuf(StartBuf) {
@@ -343,7 +344,18 @@
       if (CurPtr == NumStart)
         return ReturnError(CurPtr-2, "Invalid hexadecimal number");
 
+      errno = 0;
       CurIntVal = strtoll(NumStart, 0, 16);
+      if (errno == EINVAL)
+        return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+      if (errno == ERANGE) {
+        errno = 0;
+        CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
+        if (errno == EINVAL)
+          return ReturnError(CurPtr-2, "Invalid hexadecimal number");
+        if (errno == ERANGE)
+          return ReturnError(CurPtr-2, "Hexadecimal number out of range");
+      }
       return tgtok::IntVal;
     } else if (CurPtr[0] == 'b') {
       ++CurPtr;

Modified: llvm/trunk/utils/TableGen/TGLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGLexer.h?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGLexer.h (original)
+++ llvm/trunk/utils/TableGen/TGLexer.h Thu Oct 16 20:33:43 2008
@@ -62,7 +62,7 @@
   const char *TokStart;
   tgtok::TokKind CurCode;
   std::string CurStrVal;  // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT
-  int CurIntVal;          // This is valid for INTVAL.
+  int64_t CurIntVal;      // This is valid for INTVAL.
   
   /// IncludeRec / IncludeStack - This captures the current set of include
   /// directives we are nested within.
@@ -98,7 +98,7 @@
            "This token doesn't have a string value");
     return CurStrVal;
   }
-  int getCurIntVal() const {
+  int64_t getCurIntVal() const {
     assert(CurCode == tgtok::IntVal && "This token isn't an integer");
     return CurIntVal;
   }

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=57663&r1=57662&r2=57663&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Thu Oct 16 20:33:43 2008
@@ -294,8 +294,8 @@
     TokError("expected integer or bitrange");
     return true;
   }
-  int Start = Lex.getCurIntVal();
-  int End;
+  int64_t Start = Lex.getCurIntVal();
+  int64_t End;
   
   if (Start < 0)
     return TokError("invalid range, cannot be negative");
@@ -426,7 +426,7 @@
       TokError("expected integer in bits<n> type");
       return 0;
     }
-    unsigned Val = Lex.getCurIntVal();
+    uint64_t Val = Lex.getCurIntVal();
     if (Lex.Lex() != tgtok::greater) {  // Eat count.
       TokError("expected '>' at end of bits<n> type");
       return 0;





More information about the llvm-commits mailing list