Index: llvm/docs/ReleaseNotes.rst
===================================================================
--- llvm/docs/ReleaseNotes.rst
+++ llvm/docs/ReleaseNotes.rst
@@ -65,6 +65,14 @@
 Changes to building LLVM
 ------------------------
 
+Changes to TableGen
+-------------------
+
+* The syntax for specifying an integer range in a range list has changed.
+  The old syntax used a hyphen in the range (e.g., ``{0-9}``). The new syntax
+  uses the "`..`" range punctuator (e.g., ``{0..9}``). The hyphen syntax
+  is deprecated. The "TableGen Language Reference" document has been updated.
+
 Changes to the ARM Backend
 --------------------------
 
Index: llvm/docs/TableGen/LangRef.rst
===================================================================
--- llvm/docs/TableGen/LangRef.rst
+++ llvm/docs/TableGen/LangRef.rst
@@ -197,16 +197,18 @@
               :| "." `TokIdentifier`
    RangeList: `RangePiece` ("," `RangePiece`)*
    RangePiece: `TokInteger`
+             :| `TokInteger` ".." `TokInteger`
              :| `TokInteger` "-" `TokInteger`
              :| `TokInteger` `TokInteger`
 
-The peculiar last form of :token:`RangePiece` is due to the fact that the
-"``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as
-two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``,
-instead of "1", "-", and "5".
 The :token:`RangeList` can be thought of as specifying "list slice" in some
 contexts.
 
+.. warning::
+  The peculiar last two forms of :token:`RangePiece` are due to the fact that the
+  "``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as
+  two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``,
+  instead of "1", "-", and "5". This hyphen form of ranges is deprecated.
 
 :token:`SimpleValue` has a number of forms:
 
Index: llvm/lib/TableGen/TGLexer.h
===================================================================
--- llvm/lib/TableGen/TGLexer.h
+++ llvm/lib/TableGen/TGLexer.h
@@ -43,6 +43,7 @@
     comma, period,      // , .
     equal, question,    // = ?
     paste,              // #
+    range,              // ..
 
     // Keywords. ('ElseKW' is named to distinguish it from the existing 'Else'
     // that means the preprocessor #else.)
Index: llvm/lib/TableGen/TGLexer.cpp
===================================================================
--- llvm/lib/TableGen/TGLexer.cpp
+++ llvm/lib/TableGen/TGLexer.cpp
@@ -161,7 +161,6 @@
 
   case ':': return tgtok::colon;
   case ';': return tgtok::semi;
-  case '.': return tgtok::period;
   case ',': return tgtok::comma;
   case '<': return tgtok::less;
   case '>': return tgtok::greater;
@@ -181,6 +180,16 @@
 
     return tgtok::paste;
 
+  // The period is a separate case so we can recognize the ".."
+  // range punctuator.
+  case '.':
+    if (peekNextChar(0) == '.') {
+      ++CurPtr; // Eat second period.
+      return tgtok::range;
+    } else {
+      return tgtok::period;
+    }
+
   case '\r':
     PrintFatalError("getNextChar() must never return '\r'");
     return tgtok::Error;
Index: llvm/lib/TableGen/TGParser.cpp
===================================================================
--- llvm/lib/TableGen/TGParser.cpp
+++ llvm/lib/TableGen/TGParser.cpp
@@ -671,8 +671,10 @@
 
 /// ParseRangePiece - Parse a bit/value range.
 ///   RangePiece ::= INTVAL
+///   RangePiece ::= INTVAL '..' INTVAL
 ///   RangePiece ::= INTVAL '-' INTVAL
-///   RangePiece ::= INTVAL INTVAL
+///   RangePiece ::= INTVAL INTVAL 
+// The last two forms are deprecated.
 bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
                                TypedInit *FirstItem) {
   Init *CurVal = FirstItem;
@@ -693,6 +695,8 @@
   default:
     Ranges.push_back(Start);
     return false;
+
+  case tgtok::range:
   case tgtok::minus: {
     Lex.Lex(); // eat
 
Index: llvm/test/TableGen/range-lists.td
===================================================================
--- /dev/null
+++ llvm/test/TableGen/range-lists.td
@@ -0,0 +1,77 @@
+// RUN: llvm-tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+// This file has tests for range lists and range pieces.
+
+// These are tests for bits ranges.
+
+def bit_range_hyphen {
+  bits<16> field1;
+  let field1{15, 14, 13, 12} = {1, 0, 1, 0};
+  let field1{11-8} = {1, 0, 1, 1};
+  let field1{+7-4} = {1, 1, 0, 0};
+  let field1{+3-+0} = {1, 1, 0, 1};
+  bit hyphen_field1_ok = !eq(field1, 0xABCD);
+}
+
+def bit_range_dotdot {
+  bits<16> field1;
+  let field1{15, 14, 13, 12} = {1, 0, 1, 0};
+  let field1{11..8} = {1, 0, 1, 1};
+  let field1{+7..4} = {1, 1, 0, 0};
+  let field1{+3..+0} = {1, 1, 0, 1};
+  bit dotdot_field1_ok = !eq(field1, 0xABCD);
+}
+
+if !eq(bit_range_hyphen.field1, bit_range_dotdot.field1) then
+  def bit_range_ok {}
+else
+  def bit_range_not_ok {}
+
+// These are tests for lists.
+
+def list_range_hyphen {
+  list<string> field1 = ["foo", "bar", "baz", "snork", "quux", "quuux",
+                         "bazola", "ztesch", "bletch", "flarp"];
+  list<string> subfielda = field1[0, 1, 2, 3];
+  list<string> subfieldb = field1[4-5];
+  list<string> subfieldc = field1[+6-7];
+  list<string> subfieldd = field1[+8-+9];
+  bit hyphen_subfields_ok = !and(!eq(subfieldb[0], "quux"), !eq(subfieldd[1], "flarp"));
+}
+
+def list_range_dotdot {
+  list<string> field1 = ["foo", "bar", "baz", "snork", "quux", "quuux",
+                         "bazola", "ztesch", "bletch", "flarp"];
+  list<string> subfielda = field1[0, 1, 2, 3];
+  list<string> subfieldb = field1[4..5];
+  list<string> subfieldc = field1[+6..7];
+  list<string> subfieldd = field1[+8..+9];
+  bit dotdot_subfields_ok = !and(!eq(subfieldb[0], "quux"), !eq(subfieldd[1], "flarp"));
+}
+
+if !eq(!head(list_range_hyphen.subfieldd), !head(list_range_dotdot.subfieldd)) then
+  def list_range_ok {}
+else
+  def list_range_not_ok {}
+
+// This is a test of foreach.
+
+foreach i = {0-3} in 
+  foreach j = {4..5} in
+    def eachrec#i#j {
+      int fi = i;
+      int fj = j;
+    }
+
+//CHECK: bit dotdot_field1_ok = 1
+//CHECK: bit hyphen_field1_ok = 1
+//CHECK: def bit_range_ok {
+
+//CHECK: def eachrec04 {
+//CHECK: def eachrec35 {
+
+//CHECK: bit dotdot_subfields_ok = 1
+//CHECK: bit hyphen_subfields_ok = 1
+//CHECK: def list_range_ok {
+