Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -1996,3 +1996,10 @@
   let SemaHandler = 0;
   let Documentation = [Undocumented];
 }
+
+def ImpossibleEnum : Attr {
+  let Spellings = [CXX11<"clang","impossible_enum">];
+  let Subjects = SubjectList<[EnumConstant], ErrorDiag>;
+  let Documentation = [ImpossibleEnumDocs];
+}
+
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -1421,3 +1421,17 @@
 cannot point to the private address space.
   }];
 }
+
+def ImpossibleEnumDocs : Documentation {
+  let Category = DocCatVariable;
+  let Heading = "[[clang::impossible_enum]]";
+  let Content = [{
+The impossible_enum attribute specifies to the compiler that enum values with
+this attribute are never valid. This allows the compiler to treat branches based
+on this enum value as dead code. This attribute only impacts the behavior of
+switch statements and conditional expressions. In switch statements any case
+labels which are based on an impossible_enum are not emitted to the IR. In
+conditional expressions equality against impossible_enum values is always false,
+all other boolean operators are true.
+  }];
+}
Index: include/clang/Sema/AttributeList.h
===================================================================
--- include/clang/Sema/AttributeList.h
+++ include/clang/Sema/AttributeList.h
@@ -823,6 +823,7 @@
   ExpectedFunctionMethodOrParameter,
   ExpectedClass,
   ExpectedEnum,
+  ExpectedEnumConstant,
   ExpectedVariable,
   ExpectedMethod,
   ExpectedVariableFunctionOrLabel,
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2770,9 +2770,23 @@
 Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
                                       unsigned SICmpOpc, unsigned FCmpOpc) {
   TestAndClearIgnoreResultAssign();
-  Value *Result;
+  Value *Result = nullptr;
   QualType LHSTy = E->getLHS()->getType();
   QualType RHSTy = E->getRHS()->getType();
+
+  auto *LHSDeclRef = dyn_cast<DeclRefExpr>(E->getLHS()->IgnoreCasts());
+  auto *RHSDeclRef = dyn_cast<DeclRefExpr>(E->getRHS()->IgnoreCasts());
+  bool impossibleEnum =
+      (LHSDeclRef && LHSDeclRef->getDecl()->hasAttr<ImpossibleEnumAttr>()) ||
+      (RHSDeclRef && RHSDeclRef->getDecl()->hasAttr<ImpossibleEnumAttr>());
+  if (impossibleEnum) {
+    if (E->getOpcode() == BO_EQ)
+      Result = llvm::ConstantInt::getFalse(ConvertType(E->getType()));
+    else
+      Result = llvm::ConstantInt::getTrue(ConvertType(E->getType()));
+    return EmitScalarConversion(Result, CGF.getContext().BoolTy, E->getType());
+  }
+
   if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) {
     assert(E->getOpcode() == BO_EQ ||
            E->getOpcode() == BO_NE);
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -13,6 +13,7 @@
 
 #include "CodeGenFunction.h"
 #include "CGDebugInfo.h"
+#include "CGBuilder.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
 #include "clang/AST/StmtVisitor.h"
@@ -1252,11 +1253,21 @@
     }
   }
 
-  llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
-  EmitBlockWithFallThrough(CaseDest, CaseCnt);
+  const DeclRefExpr *EnumDeclExpr =
+      dyn_cast<DeclRefExpr>(S.getLHS()->IgnoreCasts());
+  bool isCaseImpossible =
+      EnumDeclExpr && EnumDeclExpr->getDecl()->hasAttr<ImpossibleEnumAttr>();
+
+  llvm::BasicBlock *CaseDest = nullptr;
   if (SwitchWeights)
     SwitchWeights->push_back(CaseCnt.getCount());
-  SwitchInsn->addCase(CaseVal, CaseDest);
+  if (!isCaseImpossible) {
+    if (!CaseDest) {
+      CaseDest = createBasicBlock("sw.bb");
+      EmitBlockWithFallThrough(CaseDest, CaseCnt);
+    }
+    SwitchInsn->addCase(CaseVal, CaseDest);
+  }
 
   // Recursively emitting the statement is acceptable, but is not wonderful for
   // code where we have many case statements nested together, i.e.:
@@ -1276,6 +1287,10 @@
     llvm::ConstantInt *CaseVal =
       Builder.getInt(CurCase->getLHS()->EvaluateKnownConstInt(getContext()));
 
+    EnumDeclExpr = dyn_cast<DeclRefExpr>(CurCase->getLHS()->IgnoreCasts());
+    isCaseImpossible =
+        EnumDeclExpr && EnumDeclExpr->getDecl()->hasAttr<ImpossibleEnumAttr>();
+
     CaseCnt = getPGORegionCounter(NextCase);
     if (SwitchWeights)
       SwitchWeights->push_back(CaseCnt.getCount());
@@ -1284,7 +1299,13 @@
       EmitBlockWithFallThrough(CaseDest, CaseCnt);
     }
 
-    SwitchInsn->addCase(CaseVal, CaseDest);
+    if (!isCaseImpossible) {
+      if (!CaseDest) {
+        CaseDest = createBasicBlock("sw.bb");
+        EmitBlockWithFallThrough(CaseDest, CaseCnt);
+      }
+      SwitchInsn->addCase(CaseVal, CaseDest);
+    }
     NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt());
   }
 
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3201,6 +3201,16 @@
                               Attr.getAttributeSpellingListIndex()));
 }
 
+static void handleImpossibleEnumAttr(Sema &S, Decl *D,
+                                      const AttributeList &Attr) {
+  if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
+    return;
+
+  D->addAttr(::new (S.Context)
+            ImpossibleEnumAttr(Attr.getRange(), S.Context,
+                                Attr.getAttributeSpellingListIndex()));
+}
+
 static void handleMinSizeAttr(Sema &S, Decl *D,
                               const AttributeList &Attr) {
   if (checkAttrMutualExclusion<OptimizeNoneAttr>(S, D, Attr))
@@ -4367,6 +4377,9 @@
   case AttributeList::AT_AlwaysInline:
     handleAlwaysInlineAttr(S, D, Attr);
     break;
+  case AttributeList::AT_ImpossibleEnum:
+    handleImpossibleEnumAttr(S, D, Attr);
+    break;
   case AttributeList::AT_AnalyzerNoReturn:
     handleAnalyzerNoReturnAttr(S, D, Attr);
     break;
Index: test/CodeGenCXX/impossible_enum.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/impossible_enum.cpp
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - | FileCheck %s
+
+void printf(const char*, ...);
+
+enum ImpossibleEnum {
+  value1,
+  value2,
+  value3 [[clang::impossible_enum]]
+};
+
+// CHECK: switch
+// CHECK: label
+// CHECK: label
+// CHECK: ]
+// CHECK: call
+// CHECK: call
+// CHECK: ret void
+void foo(int i) {
+  switch(i) {
+    case value1:
+      printf("value1");
+      break;
+    case value3:
+      printf("value3");
+    case value2:
+      printf("value2");
+      break;
+    default:
+      break;
+  }
+}
+
+// CHECK: switch
+// CHECK: label
+// CHECK: label
+// CHECK: ]
+// CHECK: call
+// CHECK: call
+// CHECK: call
+// CHECK: ret void
+void bar(int i) {
+  switch(i) {
+    case value1:
+      printf("value1");
+      break;
+    case value2:
+      printf("value2");
+    case value3:
+      printf("value3");
+      break;
+    default:
+      break;
+  }
+}
+
+// CHECK: switch
+// CHECK: label
+// CHECK: label
+// CHECK: ]
+// CHECK: call
+// CHECK: call
+// CHECK: ret void
+void baz(int i) {
+  switch(i) {
+    case value1:
+      printf("value1");
+      break;
+    case value2:
+    case value3:
+      printf("value23");
+      break;
+    default:
+      break;
+  }
+}
+
+// CHECK: br i1 true
+// CHECK: br i1 false
+int main(int argc, char**) {
+  foo(argc);
+  bar(argc);
+  baz(argc);
+  if(argc != value3)
+    printf("true");
+  if(argc == value3)
+    printf("false");
+  return 0;
+}
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2186,7 +2186,8 @@
     Field = 1U << 12,
     CXXMethod = 1U << 13,
     ObjCProtocol = 1U << 14,
-    Enum = 1U << 15
+    Enum = 1U << 15,
+    EnumConstant = 1U << 16
   };
   uint32_t SubMask = 0;
 
@@ -2221,6 +2222,7 @@
                    .Case("Field", Field)
                    .Case("CXXMethod", CXXMethod)
                    .Case("Enum", Enum)
+                   .Case("EnumConstant", EnumConstant)
                    .Default(0);
     if (!V) {
       // Something wasn't in our mapping, so be helpful and let the developer
@@ -2240,6 +2242,7 @@
     case Param: return "ExpectedParameter";
     case Class: return "ExpectedClass";
     case Enum:  return "ExpectedEnum";
+    case EnumConstant:  return "ExpectedEnumConstant";
     case CXXMethod:
       // FIXME: Currently, this maps to ExpectedMethod based on existing code,
       // but should map to something a bit more accurate at some point.