Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -587,6 +587,7 @@ ATTR_KIND_SPECULATABLE = 53, ATTR_KIND_STRICT_FP = 54, ATTR_KIND_SANITIZE_HWADDRESS = 55, + ATTR_KIND_NO_SIMPLIFY_CFG = 56, }; enum ComdatSelectionKindCodes { Index: llvm/include/llvm/IR/Attributes.td =================================================================== --- llvm/include/llvm/IR/Attributes.td +++ llvm/include/llvm/IR/Attributes.td @@ -106,6 +106,9 @@ /// Mark the function as not returning. def NoReturn : EnumAttr<"noreturn">; +/// CFG simplification is disabled. +def NoSimplifyCFG : EnumAttr<"no_simplify_cfg">; + /// Function doesn't unwind stack. def NoUnwind : EnumAttr<"nounwind">; Index: llvm/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/lib/AsmParser/LLLexer.cpp +++ llvm/lib/AsmParser/LLLexer.cpp @@ -648,6 +648,7 @@ KEYWORD(nonnull); KEYWORD(noredzone); KEYWORD(noreturn); + KEYWORD(no_simplify_cfg); KEYWORD(nounwind); KEYWORD(optnone); KEYWORD(optsize); Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -1132,6 +1132,8 @@ 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_no_simplify_cfg: + B.addAttribute(Attribute::NoSimplifyCFG); 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; @@ -1468,6 +1470,7 @@ case lltok::kw_nonlazybind: case lltok::kw_noredzone: case lltok::kw_noreturn: + case lltok::kw_no_simplify_cfg: case lltok::kw_nounwind: case lltok::kw_optnone: case lltok::kw_optsize: @@ -1561,6 +1564,7 @@ case lltok::kw_nonlazybind: case lltok::kw_noredzone: case lltok::kw_noreturn: + case lltok::kw_no_simplify_cfg: case lltok::kw_nounwind: case lltok::kw_optnone: case lltok::kw_optsize: Index: llvm/lib/AsmParser/LLToken.h =================================================================== --- llvm/lib/AsmParser/LLToken.h +++ llvm/lib/AsmParser/LLToken.h @@ -199,6 +199,7 @@ kw_nonnull, kw_noredzone, kw_noreturn, + kw_no_simplify_cfg, kw_nounwind, kw_optnone, kw_optsize, Index: llvm/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1160,6 +1160,7 @@ case Attribute::Speculatable: return 1ULL << 54; case Attribute::StrictFP: return 1ULL << 55; case Attribute::SanitizeHWAddress: return 1ULL << 56; + case Attribute::NoSimplifyCFG: return 1ULL << 57; case Attribute::Dereferenceable: llvm_unreachable("dereferenceable attribute not supported in raw format"); break; @@ -1338,6 +1339,8 @@ return Attribute::NoRedZone; case bitc::ATTR_KIND_NO_RETURN: return Attribute::NoReturn; + case bitc::ATTR_KIND_NO_SIMPLIFY_CFG: + return Attribute::NoSimplifyCFG; case bitc::ATTR_KIND_NO_UNWIND: return Attribute::NoUnwind; case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE: Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -638,6 +638,8 @@ return bitc::ATTR_KIND_NO_RED_ZONE; case Attribute::NoReturn: return bitc::ATTR_KIND_NO_RETURN; + case Attribute::NoSimplifyCFG: + return bitc::ATTR_KIND_NO_SIMPLIFY_CFG; case Attribute::NoUnwind: return bitc::ATTR_KIND_NO_UNWIND; case Attribute::OptimizeForSize: Index: llvm/lib/IR/Attributes.cpp =================================================================== --- llvm/lib/IR/Attributes.cpp +++ llvm/lib/IR/Attributes.cpp @@ -301,6 +301,8 @@ return "noreturn"; if (hasAttribute(Attribute::NoRecurse)) return "norecurse"; + if (hasAttribute(Attribute::NoSimplifyCFG)) + return "no_simplify_cfg"; if (hasAttribute(Attribute::NoUnwind)) return "nounwind"; if (hasAttribute(Attribute::OptimizeNone)) Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1405,6 +1405,7 @@ case Attribute::StackProtectStrong: case Attribute::SafeStack: case Attribute::NoRedZone: + case Attribute::NoSimplifyCFG: case Attribute::NoImplicitFloat: case Attribute::Naked: case Attribute::InlineHint: Index: llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -43,6 +43,7 @@ .Case("noredzone", Attribute::NoRedZone) .Case("noreturn", Attribute::NoReturn) .Case("norecurse", Attribute::NoRecurse) + .Case("no_simplify_cfg", Attribute::NoSimplifyCFG) .Case("nounwind", Attribute::NoUnwind) .Case("optnone", Attribute::OptimizeNone) .Case("optsize", Attribute::OptimizeForSize) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -683,6 +683,7 @@ case Attribute::NoInline: case Attribute::NonLazyBind: case Attribute::NoRedZone: + case Attribute::NoSimplifyCFG: case Attribute::NoUnwind: case Attribute::OptimizeNone: case Attribute::OptimizeForSize: Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6053,6 +6053,9 @@ bool llvm::simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, const SimplifyCFGOptions &Options, SmallPtrSetImpl *LoopHeaders) { + const Function *Fn = BB->getParent(); + if (Fn && Fn->hasFnAttribute(Attribute::NoSimplifyCFG)) + return false; return SimplifyCFGOpt(TTI, BB->getModule()->getDataLayout(), LoopHeaders, Options) .run(BB); Index: llvm/test/Transforms/SimplifyCFG/no-simplify-cfg.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/SimplifyCFG/no-simplify-cfg.ll @@ -0,0 +1,49 @@ +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +define i32 @foo(i32 %x) no_simplify_cfg { +entry: + %x.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + %0 = load i32, i32* %x.addr, align 4 + %cmp = icmp sgt i32 %0, 16 + br i1 %cmp, label %land.rhs, label %land.end + +land.rhs: + %1 = load i32, i32* %x.addr, align 4 + %cmp1 = icmp slt i32 %1, 32 + br label %land.end + +land.end: + %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ] + %conv = zext i1 %2 to i32 + ret i32 %conv + +; CHECK-LABEL: define i32 @foo(i32 %x) +; CHECK: br i1 %cmp, label %land.rhs, label %land.end +; CHECK-LABEL: land.rhs: +; CHECK: br label %land.end +; CHECK-LABEL: land.end: +; CHECK: phi {{.*}} %entry {{.*}} %land.rhs +} + +define i32 @bar(i32 %x) { +entry: + %x.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + %0 = load i32, i32* %x.addr, align 4 + %cmp = icmp sgt i32 %0, 16 + br i1 %cmp, label %land.rhs, label %land.end + +land.rhs: + %1 = load i32, i32* %x.addr, align 4 + %cmp1 = icmp slt i32 %1, 32 + br label %land.end + +land.end: + %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ] + %conv = zext i1 %2 to i32 + ret i32 %conv + +; CHECK-LABEL: define i32 @bar(i32 %x) +; CHECK-NOT: br +}