diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | Makefile.rules | 2 | ||||
-rw-r--r-- | lib/Target/X86/X86Instr64bit.td | 23 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.td | 11 | ||||
-rw-r--r-- | test/CodeGen/X86/add-trick32.ll | 11 | ||||
-rw-r--r-- | test/CodeGen/X86/add-trick64.ll | 15 | ||||
-rw-r--r-- | test/TableGen/2006-09-18-LargeInt.td | 2 | ||||
-rw-r--r-- | utils/TableGen/DAGISelEmitter.cpp | 3 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 24 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 14 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.cpp | 12 | ||||
-rw-r--r-- | utils/TableGen/TGLexer.h | 4 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 6 |
14 files changed, 95 insertions, 37 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3411eed..91ecf01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) # 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 ) diff --git a/Makefile.rules b/Makefile.rules index 0074560..d1b3a55 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -483,7 +483,7 @@ CPP.BaseFlags += -include llvm/System/Solaris.h 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,\ diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 5085f54..d17ed1a 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -61,13 +61,6 @@ def i64immSExt8 : PatLeaf<(i64 imm), [{ 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 @@ def : Pat<(i32 (anyext GR8:$src)), // 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), diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 16dc366..f44b918 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2911,6 +2911,17 @@ def : Pat<(i32 (and (nvloadi32 addr:$src), (i32 65535))), // 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)))>; diff --git a/test/CodeGen/X86/add-trick32.ll b/test/CodeGen/X86/add-trick32.ll new file mode 100644 index 0000000..42909b4 --- /dev/null +++ b/test/CodeGen/X86/add-trick32.ll @@ -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 +} diff --git a/test/CodeGen/X86/add-trick64.ll b/test/CodeGen/X86/add-trick64.ll new file mode 100644 index 0000000..5466d9d --- /dev/null +++ b/test/CodeGen/X86/add-trick64.ll @@ -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 +} diff --git a/test/TableGen/2006-09-18-LargeInt.td b/test/TableGen/2006-09-18-LargeInt.td index 0e441c5..afd813f 100644 --- a/test/TableGen/2006-09-18-LargeInt.td +++ b/test/TableGen/2006-09-18-LargeInt.td @@ -1,4 +1,4 @@ -// RUN: tblgen %s | grep -- -65536 +// RUN: tblgen %s | grep -- 4294901760 def X { int Y = 0xFFFF0000; diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 6ca5657..78239ec 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -734,7 +734,8 @@ public: 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(); diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 06d9bf2..e173cae 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -35,7 +35,7 @@ bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const { } 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(BitInit *BI) { } 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 @@ std::string BitsInit::getAsString() const { 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 @@ Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { 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 @@ Init *BinOpInit::Fold() { 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 @@ Record::getValueAsListOfDefs(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 +/// 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 @@ int Record::getValueAsInt(const std::string &FieldName) const { /// 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()); diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 90e246e..928fd5c 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -565,11 +565,11 @@ public: /// 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 @@ public: /// 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 @@ public: 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 diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 55eb754..06f43d5 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -422,7 +422,7 @@ void RegisterInfoEmitter::run(std::ostream &OS) { 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 @@ void RegisterInfoEmitter::run(std::ostream &OS) { 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) diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index e7465de..0d83e7c 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -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 @@ tgtok::TokKind TGLexer::LexNumber() { 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; diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index b4fa97c..2c5a852 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -62,7 +62,7 @@ class TGLexer { 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 @@ public: "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; } diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index 68a1cba..4ff108d 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -294,8 +294,8 @@ bool TGParser::ParseRangePiece(std::vector<unsigned> &Ranges) { 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 @@ RecTy *TGParser::ParseType() { 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; |