Index: ../lib/Transforms/Utils/CodeExtractor.cpp =================================================================== --- ../lib/Transforms/Utils/CodeExtractor.cpp +++ ../lib/Transforms/Utils/CodeExtractor.cpp @@ -60,6 +60,33 @@ if (BB.isEHPad()) return false; + // taking the address of a basic block moved to another function is illegal + if (BB.hasAddressTaken()) + return false; + + // don't hoist code that uses another basicblock address, as it's likely to + // lead to unexpected behavior, like cross-function jumps + SmallPtrSet Visited; + SmallVector ToVisit; + + for (Instruction const &Inst : BB) + ToVisit.push_back(&Inst); + + // loop + while (!ToVisit.empty()) { + User const *Curr = ToVisit.pop_back_val(); + if (Visited.count(Curr)) + continue; + Visited.insert(Curr); + if (isa(Curr)) { + return true; // even a reference to self is likely to be not compatible + } + for (auto const &U : Curr->operands()) { + if (auto *UU = dyn_cast(U)) + ToVisit.push_back(UU); + } + } + // Don't hoist code containing allocas, invokes, or vastarts. for (BasicBlock::const_iterator I = BB.begin(), E = BB.end(); I != E; ++I) { if (isa(I) || isa(I)) Index: ../test/Transforms/CodeExtractor/BlockAddressreference.ll =================================================================== --- ../test/Transforms/CodeExtractor/BlockAddressreference.ll +++ ../test/Transforms/CodeExtractor/BlockAddressreference.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -loop-extract -S | FileCheck %s + +@label = common local_unnamed_addr global i8* null + +; CHECK: define +; no outlined function +; CHECK-NOT: define +define i32 @sterix(i32 %n) { +entry: + %tobool = icmp ne i32 %n, 0 + ; this blockaddress references a basic block that goes in the extracted loop + %cond = select i1 %tobool, i8* blockaddress(@sterix, %for.cond), i8* blockaddress(@sterix, %exit) + store i8* %cond, i8** @label + %cmp5 = icmp sgt i32 %n, 0 + br i1 %cmp5, label %for.body, label %exit + +for.cond: + %mul = shl nsw i32 %s.06, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %exit.loopexit, label %for.body + +for.body: + %i.07 = phi i32 [ %inc, %for.cond ], [ 0, %entry ] + %s.06 = phi i32 [ %mul, %for.cond ], [ 1, %entry ] + %inc = add nuw nsw i32 %i.07, 1 + br label %for.cond + +exit.loopexit: + %phitmp = icmp ne i32 %s.06, 2 + %phitmp8 = zext i1 %phitmp to i32 + br label %exit + +exit: + %s.1 = phi i32 [ 1, %entry ], [ %phitmp8, %exit.loopexit ] + ret i32 %s.1 +}