Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -506,7 +506,8 @@ ATTR_KIND_SWIFT_ERROR = 47, ATTR_KIND_NO_RECURSE = 48, ATTR_KIND_INACCESSIBLEMEM_ONLY = 49, - ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50 + ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50, + ATTR_KIND_NO_USE_JUMP_TABLE = 51 }; enum ComdatSelectionKindCodes { Index: include/llvm/IR/Attributes.td =================================================================== --- include/llvm/IR/Attributes.td +++ include/llvm/IR/Attributes.td @@ -60,6 +60,9 @@ /// Build jump-instruction tables and replace refs. def JumpTable : EnumAttr<"jumptable">; +/// Function body does not use JumpTables +def NoUseJumpTable : EnumAttr<"nousejumptable">; + /// Function must be optimized for size first. def MinSize : EnumAttr<"minsize">; Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -631,6 +631,7 @@ KEYWORD(nonnull); KEYWORD(noredzone); KEYWORD(noreturn); + KEYWORD(nousejumptable); KEYWORD(nounwind); KEYWORD(optnone); KEYWORD(optsize); Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -1034,6 +1034,7 @@ case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; + case lltok::kw_nousejumptable: B.addAttribute(Attribute::NoUseJumpTable); break; case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; @@ -1363,6 +1364,7 @@ case lltok::kw_noredzone: case lltok::kw_noreturn: case lltok::kw_nounwind: + case lltok::kw_nousejumptable: case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: @@ -1452,6 +1454,7 @@ case lltok::kw_noredzone: case lltok::kw_noreturn: case lltok::kw_nounwind: + case lltok::kw_nousejumptable: case lltok::kw_optnone: case lltok::kw_optsize: case lltok::kw_returns_twice: Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -136,6 +136,7 @@ kw_nonnull, kw_noredzone, kw_noreturn, + kw_nousejumptable, kw_nounwind, kw_optnone, kw_optsize, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1293,6 +1293,8 @@ return Attribute::NoReturn; case bitc::ATTR_KIND_NO_UNWIND: return Attribute::NoUnwind; + case bitc::ATTR_KIND_NO_USE_JUMP_TABLE: + return Attribute::NoUseJumpTable; case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE: return Attribute::OptimizeForSize; case bitc::ATTR_KIND_OPTIMIZE_NONE: Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -228,6 +228,8 @@ return bitc::ATTR_KIND_NO_RETURN; case Attribute::NoUnwind: return bitc::ATTR_KIND_NO_UNWIND; + case Attribute::NoUseJumpTable: + return bitc::ATTR_KIND_NO_USE_JUMP_TABLE; case Attribute::OptimizeForSize: return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE; case Attribute::OptimizeNone: Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7927,6 +7927,10 @@ CaseCluster &JTCluster) { assert(First <= Last); + //Give up if function containing SI has NoUseJumpTable attr + if (SI->getParent()->getParent()->hasFnAttribute(Attribute::NoUseJumpTable)) + return false; + auto Prob = BranchProbability::getZero(); unsigned NumCmps = 0; std::vector Table; Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -237,6 +237,8 @@ return "norecurse"; if (hasAttribute(Attribute::NoUnwind)) return "nounwind"; + if (hasAttribute(Attribute::NoUseJumpTable)) + return "nousejumptable"; if (hasAttribute(Attribute::OptimizeNone)) return "optnone"; if (hasAttribute(Attribute::OptimizeForSize)) @@ -448,6 +450,7 @@ case Attribute::NoRecurse: return 1ULL << 48; case Attribute::InaccessibleMemOnly: return 1ULL << 49; case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50; + case Attribute::NoUseJumpTable: return 1ULL << 51; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1295,6 +1295,7 @@ I->getKindAsEnum() == Attribute::Cold || I->getKindAsEnum() == Attribute::OptimizeNone || I->getKindAsEnum() == Attribute::JumpTable || + I->getKindAsEnum() == Attribute::NoUseJumpTable || I->getKindAsEnum() == Attribute::Convergent || I->getKindAsEnum() == Attribute::ArgMemOnly || I->getKindAsEnum() == Attribute::NoRecurse || Index: lib/Transforms/IPO/ForceFunctionAttrs.cpp =================================================================== --- lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -43,6 +43,7 @@ .Case("noredzone", Attribute::NoRedZone) .Case("noreturn", Attribute::NoReturn) .Case("norecurse", Attribute::NoRecurse) + .Case("nousejumptable", Attribute::NoUseJumpTable) .Case("nounwind", Attribute::NoUnwind) .Case("optnone", Attribute::OptimizeNone) .Case("optsize", Attribute::OptimizeForSize) Index: test/CodeGen/X86/switch.ll =================================================================== --- test/CodeGen/X86/switch.ll +++ test/CodeGen/X86/switch.ll @@ -30,6 +30,23 @@ ; NOOPT: jmpq } +define void @basic_nojumptable(i32 %x) nousejumptable { +entry: + switch i32 %x, label %return [ + i32 3, label %bb0 + i32 1, label %bb1 + i32 4, label %bb1 + i32 5, label %bb2 + ] +bb0: tail call void @g(i32 0) br label %return +bb1: tail call void @g(i32 1) br label %return +bb2: tail call void @g(i32 1) br label %return +return: ret void + +; Lowered as a jump table, both with and without optimization. +; CHECK-LABEL: basic_nojumptable +; CHECK-NOT: jmpq *.LJTI +} define void @simple_ranges(i32 %x) { entry: