diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h b/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h --- a/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyCFGOptions.h @@ -29,7 +29,7 @@ bool HoistCommonInsts = false; bool SinkCommonInsts = false; bool SimplifyCondBranch = true; - bool FoldTwoEntryPHINode = true; + bool SpeculateBlocks = true; AssumptionCache *AC = nullptr; @@ -71,8 +71,8 @@ return *this; } - SimplifyCFGOptions &setFoldTwoEntryPHINode(bool B) { - FoldTwoEntryPHINode = B; + SimplifyCFGOptions &speculateBlocks(bool B) { + SpeculateBlocks = B; return *this; } }; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -776,8 +776,8 @@ std::tie(ParamName, Params) = Params.split(';'); bool Enable = !ParamName.consume_front("no-"); - if (ParamName == "fold-two-entry-phi") { - Result.setFoldTwoEntryPHINode(Enable); + if (ParamName == "speculate-blocks") { + Result.speculateBlocks(Enable); } else if (ParamName == "simplify-cond-branch") { Result.setSimplifyCondBranch(Enable); } else if (ParamName == "forward-switch-cond") { diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -348,7 +348,7 @@ OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;"; OS << (Options.HoistCommonInsts ? "" : "no-") << "hoist-common-insts;"; OS << (Options.SinkCommonInsts ? "" : "no-") << "sink-common-insts;"; - OS << (Options.FoldTwoEntryPHINode ? "" : "no-") << "fold-two-entry-phi;"; + OS << (Options.SpeculateBlocks ? "" : "no-") << "speculate-blocks;"; OS << (Options.SimplifyCondBranch ? "" : "no-") << "simplify-cond-branch"; OS << '>'; } diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2842,6 +2842,9 @@ /// \returns true if the conditional block is removed. bool SimplifyCFGOpt::SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB) { + if (!Options.SpeculateBlocks) + return false; + // Be conservative for now. FP select instruction can often be expensive. Value *BrCond = BI->getCondition(); if (isa(BrCond)) @@ -7276,7 +7279,7 @@ IRBuilder<> Builder(BB); - if (Options.FoldTwoEntryPHINode && + if (Options.SpeculateBlocks && !BB->getParent()->hasFnAttribute(Attribute::OptForFuzzing)) { // If there is a trivial two-entry PHI node in this basic block, and we can // eliminate it, do so now. diff --git a/llvm/test/Other/new-pm-print-pipeline.ll b/llvm/test/Other/new-pm-print-pipeline.ll --- a/llvm/test/Other/new-pm-print-pipeline.ll +++ b/llvm/test/Other/new-pm-print-pipeline.ll @@ -52,8 +52,8 @@ ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(print,print)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-17 ; CHECK-17: function(print,print) -; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg,simplifycfg)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18 -; CHECK-18: function(simplifycfg,simplifycfg) +; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(simplifycfg,simplifycfg)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-18 +; CHECK-18: function(simplifycfg,simplifycfg) ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(loop-vectorize,loop-vectorize)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-19 ; CHECK-19: function(loop-vectorize,loop-vectorize) diff --git a/llvm/test/Transforms/SimplifyCFG/speculate-blocks.ll b/llvm/test/Transforms/SimplifyCFG/speculate-blocks.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/speculate-blocks.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt < %s -S -passes='simplifycfg' | FileCheck %s --check-prefix=YES +; RUN: opt < %s -S -passes='simplifycfg' | FileCheck %s --check-prefix=NO + +define i32 @f(ptr %arg, ptr %arg1) { +; YES-LABEL: define i32 @f +; YES-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]]) { +; YES-NEXT: bb: +; YES-NEXT: [[ICMP:%.*]] = icmp ne ptr [[ARG1]], null +; YES-NEXT: br label [[BB5:%.*]] +; YES: bb5: +; YES-NEXT: [[PHI:%.*]] = phi ptr [ [[ARG]], [[BB:%.*]] ], [ [[SPEC_SELECT:%.*]], [[BB15:%.*]] ] +; YES-NEXT: [[PHI6:%.*]] = phi i32 [ 0, [[BB]] ], [ [[ADD:%.*]], [[BB15]] ] +; YES-NEXT: [[ICMP7:%.*]] = icmp eq ptr [[PHI]], [[ARG1]] +; YES-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i32, ptr [[PHI]], i64 1 +; YES-NEXT: [[SPEC_SELECT]] = select i1 [[ICMP7]], ptr [[PHI]], ptr [[GETELEMENTPTR]] +; YES-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[ICMP7]], ptr null, ptr [[PHI]] +; YES-NEXT: [[ICMP13:%.*]] = icmp eq ptr [[SPEC_SELECT1]], null +; YES-NEXT: br i1 [[ICMP13]], label [[BB16:%.*]], label [[BB15]] +; YES: bb15: +; YES-NEXT: [[LOAD:%.*]] = load i32, ptr [[SPEC_SELECT1]], align 4 +; YES-NEXT: [[ADD]] = add i32 [[LOAD]], [[PHI6]] +; YES-NEXT: br label [[BB5]] +; YES: bb16: +; YES-NEXT: ret i32 [[PHI6]] +; +; NO-LABEL: define i32 @f +; NO-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]]) { +; NO-NEXT: bb: +; NO-NEXT: [[ICMP:%.*]] = icmp ne ptr [[ARG1]], null +; NO-NEXT: br label [[BB5:%.*]] +; NO: bb5: +; NO-NEXT: [[PHI:%.*]] = phi ptr [ [[ARG]], [[BB:%.*]] ], [ [[PHI10:%.*]], [[BB15:%.*]] ] +; NO-NEXT: [[PHI6:%.*]] = phi i32 [ 0, [[BB]] ], [ [[ADD:%.*]], [[BB15]] ] +; NO-NEXT: [[ICMP7:%.*]] = icmp eq ptr [[PHI]], [[ARG1]] +; NO-NEXT: br i1 [[ICMP7]], label [[BB9:%.*]], label [[BB8:%.*]] +; NO: bb8: +; NO-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i32, ptr [[PHI]], i64 1 +; NO-NEXT: br label [[BB9]] +; NO: bb9: +; NO-NEXT: [[PHI10]] = phi ptr [ [[PHI]], [[BB5]] ], [ [[GETELEMENTPTR]], [[BB8]] ] +; NO-NEXT: [[PHI11:%.*]] = phi ptr [ null, [[BB5]] ], [ [[PHI]], [[BB8]] ] +; NO-NEXT: [[ICMP13:%.*]] = icmp eq ptr [[PHI11]], null +; NO-NEXT: br i1 [[ICMP13]], label [[BB16:%.*]], label [[BB15]] +; NO: bb15: +; NO-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI11]], align 4 +; NO-NEXT: [[ADD]] = add i32 [[LOAD]], [[PHI6]] +; NO-NEXT: br label [[BB5]] +; NO: bb16: +; NO-NEXT: ret i32 [[PHI6]] +; +bb: + %icmp = icmp ne ptr %arg1, null + br label %bb5 + +bb5: ; preds = %bb15, %bb + %phi = phi ptr [ %arg, %bb ], [ %phi10, %bb15 ] + %phi6 = phi i32 [ 0, %bb ], [ %add, %bb15 ] + %icmp7 = icmp eq ptr %phi, %arg1 + br i1 %icmp7, label %bb9, label %bb8 + +bb8: ; preds = %bb5 + %getelementptr = getelementptr inbounds i32, ptr %phi, i64 1 + br label %bb9 + +bb9: ; preds = %bb8, %bb5 + %phi10 = phi ptr [ %phi, %bb5 ], [ %getelementptr, %bb8 ] + %phi11 = phi ptr [ null, %bb5 ], [ %phi, %bb8 ] + %icmp13 = icmp eq ptr %phi11, null + br i1 %icmp13, label %bb16, label %bb15 + +bb15: ; preds = %bb14 + %load = load i32, ptr %phi11, align 4 + %add = add i32 %load, %phi6 + br label %bb5 + +bb16: ; preds = %bb12 + ret i32 %phi6 +}