Index: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp @@ -90,6 +90,11 @@ cl::desc("Allow exactly one expensive instruction to be speculatively " "executed")); +static cl::opt 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 @@ 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(V); if (!I) { // Non-instructions all dominate instructions, but not all constantexprs Index: llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll =================================================================== --- llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll +++ llvm/trunk/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll @@ -1302,3 +1302,35 @@ ; 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 +} +