summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp12
-rw-r--r--llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll32
2 files changed, 44 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index fefe448d239..8370968065d 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -90,6 +90,11 @@ static cl::opt<bool> SpeculateOneExpensiveInst(
cl::desc("Allow exactly one expensive instruction to be speculatively "
"executed"));
+static cl::opt<unsigned> MaxSpeculationDepth(
+ "max-speculation-depth", cl::Hidden, cl::init(10),
+ cl::desc("Limit maximum recursion depth when calculating costs of "
+ "speculatively executed instructions"));
+
STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
STATISTIC(NumLinearMaps, "Number of switch instructions turned into linear mapping");
STATISTIC(NumLookupTables, "Number of switch instructions turned into lookup tables");
@@ -269,6 +274,13 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
unsigned &CostRemaining,
const TargetTransformInfo &TTI,
unsigned Depth = 0) {
+ // It is possible to hit a zero-cost cycle (phi/gep instructions for example),
+ // so limit the recursion depth.
+ // TODO: While this recursion limit does prevent pathological behavior, it
+ // would be better to track visited instructions to avoid cycles.
+ if (Depth == MaxSpeculationDepth)
+ return false;
+
Instruction *I = dyn_cast<Instruction>(V);
if (!I) {
// Non-instructions all dominate instructions, but not all constantexprs
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
index cae1a91bd43..6953cf9c8b3 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll
@@ -1302,3 +1302,35 @@ l6:
; CHECK: entry
; CHECK-NEXT: switch
}
+
+; Speculation depth must be limited to avoid a zero-cost instruction cycle.
+
+; CHECK-LABEL: @PR26308(
+; CHECK: cleanup4:
+; CHECK-NEXT: br label %cleanup4
+
+define i32 @PR26308(i1 %B, i64 %load) {
+entry:
+ br label %while.body
+
+while.body:
+ br label %cleanup
+
+cleanup:
+ %cleanup.dest.slot.0 = phi i1 [ false, %while.body ]
+ br i1 %cleanup.dest.slot.0, label %for.cond, label %cleanup4
+
+for.cond:
+ %e.0 = phi i64* [ undef, %cleanup ], [ %incdec.ptr, %for.cond2 ]
+ %pi = ptrtoint i64* %e.0 to i64
+ %incdec.ptr = getelementptr inbounds i64, i64* %e.0, i64 1
+ br label %for.cond2
+
+for.cond2:
+ %storemerge = phi i64 [ %pi, %for.cond ], [ %load, %for.cond2 ]
+ br i1 %B, label %for.cond2, label %for.cond
+
+cleanup4:
+ br label %while.body
+}
+
OpenPOWER on IntegriCloud