Skip to content
This repository was archived by the owner on Oct 24, 2019. It is now read-only.

Commit 77814f8

Browse files
committed
Merge remote-tracking branch 'origin/swift-5.1-branch' into stable
2 parents c766b75 + 3d677cf commit 77814f8

File tree

6 files changed

+131
-11
lines changed

6 files changed

+131
-11
lines changed

lib/Support/Unix/Program.inc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,16 @@ static bool Execute(ProcessInfo &PI, StringRef Program,
246246
Envp = const_cast<const char **>(*_NSGetEnviron());
247247
#endif
248248

249-
// Explicitly initialized to prevent what appears to be a valgrind false
250-
// positive.
251-
pid_t PID = 0;
252-
int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
253-
/*attrp*/ nullptr, const_cast<char **>(Argv),
254-
const_cast<char **>(Envp));
249+
constexpr int maxRetries = 8;
250+
int retries = 0;
251+
pid_t PID;
252+
int Err;
253+
do {
254+
PID = 0; // Make Valgrind happy.
255+
Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
256+
/*attrp*/ nullptr, const_cast<char **>(Argv),
257+
const_cast<char **>(Envp));
258+
} while (Err == EINTR && ++retries < maxRetries);
255259

256260
if (FileActions)
257261
posix_spawn_file_actions_destroy(FileActions);

lib/Transforms/IPO/GlobalOpt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,8 +2289,8 @@ OptimizeFunctions(Module &M, TargetLibraryInfo *TLI,
22892289
// cold at all call sites and the callers contain no other non coldcc
22902290
// calls.
22912291
if (EnableColdCCStressTest ||
2292-
(isValidCandidateForColdCC(*F, GetBFI, AllCallsCold) &&
2293-
TTI.useColdCCForColdCall(*F))) {
2292+
(TTI.useColdCCForColdCall(*F) &&
2293+
isValidCandidateForColdCC(*F, GetBFI, AllCallsCold))) {
22942294
F->setCallingConv(CallingConv::Cold);
22952295
changeCallSitesToColdCC(F);
22962296
Changed = true;

lib/Transforms/ObjCARC/ObjCARCContract.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ using namespace llvm::objcarc;
4646
STATISTIC(NumPeeps, "Number of calls peephole-optimized");
4747
STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed");
4848

49+
static cl::opt<unsigned> MaxBBSize("arc-contract-max-bb-size", cl::Hidden,
50+
cl::desc("Maximum basic block size to discover the dominance relation of "
51+
"two instructions in the same basic block"), cl::init(65535));
52+
4953
//===----------------------------------------------------------------------===//
5054
// Declarations
5155
//===----------------------------------------------------------------------===//
@@ -568,6 +572,24 @@ bool ObjCARCContract::runOnFunction(Function &F) {
568572
// reduces register pressure.
569573
SmallPtrSet<Instruction *, 4> DependingInstructions;
570574
SmallPtrSet<const BasicBlock *, 4> Visited;
575+
576+
// Cache the basic block size.
577+
DenseMap<const BasicBlock *, unsigned> BBSizeMap;
578+
579+
// A lambda that lazily computes the size of a basic block and determines
580+
// whether the size exceeds MaxBBSize.
581+
auto IsLargeBB = [&](const BasicBlock *BB) {
582+
unsigned BBSize;
583+
auto I = BBSizeMap.find(BB);
584+
585+
if (I != BBSizeMap.end())
586+
BBSize = I->second;
587+
else
588+
BBSize = BBSizeMap[BB] = BB->size();
589+
590+
return BBSize > MaxBBSize;
591+
};
592+
571593
for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) {
572594
Instruction *Inst = &*I++;
573595

@@ -585,7 +607,7 @@ bool ObjCARCContract::runOnFunction(Function &F) {
585607
// and such; to do the replacement, the argument must have type i8*.
586608

587609
// Function for replacing uses of Arg dominated by Inst.
588-
auto ReplaceArgUses = [Inst, this](Value *Arg) {
610+
auto ReplaceArgUses = [Inst, IsLargeBB, this](Value *Arg) {
589611
// If we're compiling bugpointed code, don't get in trouble.
590612
if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
591613
return;
@@ -597,6 +619,17 @@ bool ObjCARCContract::runOnFunction(Function &F) {
597619
Use &U = *UI++;
598620
unsigned OperandNo = U.getOperandNo();
599621

622+
// Don't replace the uses if Inst and the user belong to the same basic
623+
// block and the size of the basic block is large. We don't want to call
624+
// DominatorTree::dominate in that case. We can remove this check if we
625+
// can use OrderedBasicBlock to compute the dominance relation between
626+
// two instructions, but that's not currently possible since it doesn't
627+
// recompute the instruction ordering when new instructions are inserted
628+
// to the basic block.
629+
if (Inst->getParent() == cast<Instruction>(U.getUser())->getParent() &&
630+
IsLargeBB(Inst->getParent()))
631+
continue;
632+
600633
// If the call's return value dominates a use of the call's argument
601634
// value, rewrite the use to use the return value. We check for
602635
// reachability here because an unreachable call is considered to

lib/Transforms/ObjCARC/ObjCARCOpts.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ using namespace llvm::objcarc;
7474

7575
#define DEBUG_TYPE "objc-arc-opts"
7676

77+
static cl::opt<unsigned> MaxPtrStates("arc-opt-max-ptr-states",
78+
cl::Hidden,
79+
cl::desc("Maximum number of ptr states the optimizer keeps track of"),
80+
cl::init(4095));
81+
7782
/// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.
7883
/// @{
7984

@@ -220,6 +225,10 @@ namespace {
220225
return !PerPtrTopDown.empty();
221226
}
222227

228+
unsigned top_down_ptr_list_size() const {
229+
return std::distance(top_down_ptr_begin(), top_down_ptr_end());
230+
}
231+
223232
using bottom_up_ptr_iterator = decltype(PerPtrBottomUp)::iterator;
224233
using const_bottom_up_ptr_iterator =
225234
decltype(PerPtrBottomUp)::const_iterator;
@@ -238,6 +247,10 @@ namespace {
238247
return !PerPtrBottomUp.empty();
239248
}
240249

250+
unsigned bottom_up_ptr_list_size() const {
251+
return std::distance(bottom_up_ptr_begin(), bottom_up_ptr_end());
252+
}
253+
241254
/// Mark this block as being an entry block, which has one path from the
242255
/// entry by definition.
243256
void SetAsEntry() { TopDownPathCount = 1; }
@@ -481,6 +494,10 @@ namespace {
481494
/// A flag indicating whether this optimization pass should run.
482495
bool Run;
483496

497+
/// A flag indicating whether the optimization that removes or moves
498+
/// retain/release pairs should be performed.
499+
bool DisableRetainReleasePairing = false;
500+
484501
/// Flags which determine whether each of the interesting runtime functions
485502
/// is in fact used in the current function.
486503
unsigned UsedInThisFunction;
@@ -1273,6 +1290,13 @@ bool ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
12731290
LLVM_DEBUG(dbgs() << " Visiting " << *Inst << "\n");
12741291

12751292
NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);
1293+
1294+
// Bail out if the number of pointers being tracked becomes too large so
1295+
// that this pass can complete in a reasonable amount of time.
1296+
if (MyStates.bottom_up_ptr_list_size() > MaxPtrStates) {
1297+
DisableRetainReleasePairing = true;
1298+
return false;
1299+
}
12761300
}
12771301

12781302
// If there's a predecessor with an invoke, visit the invoke as if it were
@@ -1395,6 +1419,13 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
13951419
LLVM_DEBUG(dbgs() << " Visiting " << Inst << "\n");
13961420

13971421
NestingDetected |= VisitInstructionTopDown(&Inst, Releases, MyStates);
1422+
1423+
// Bail out if the number of pointers being tracked becomes too large so
1424+
// that this pass can complete in a reasonable amount of time.
1425+
if (MyStates.top_down_ptr_list_size() > MaxPtrStates) {
1426+
DisableRetainReleasePairing = true;
1427+
return false;
1428+
}
13981429
}
13991430

14001431
LLVM_DEBUG(dbgs() << "\nState Before Checking for CFG Hazards:\n"
@@ -1501,13 +1532,19 @@ bool ObjCARCOpt::Visit(Function &F,
15011532

15021533
// Use reverse-postorder on the reverse CFG for bottom-up.
15031534
bool BottomUpNestingDetected = false;
1504-
for (BasicBlock *BB : llvm::reverse(ReverseCFGPostOrder))
1535+
for (BasicBlock *BB : llvm::reverse(ReverseCFGPostOrder)) {
15051536
BottomUpNestingDetected |= VisitBottomUp(BB, BBStates, Retains);
1537+
if (DisableRetainReleasePairing)
1538+
return false;
1539+
}
15061540

15071541
// Use reverse-postorder for top-down.
15081542
bool TopDownNestingDetected = false;
1509-
for (BasicBlock *BB : llvm::reverse(PostOrder))
1543+
for (BasicBlock *BB : llvm::reverse(PostOrder)) {
15101544
TopDownNestingDetected |= VisitTopDown(BB, BBStates, Releases);
1545+
if (DisableRetainReleasePairing)
1546+
return false;
1547+
}
15111548

15121549
return TopDownNestingDetected && BottomUpNestingDetected;
15131550
}
@@ -2003,6 +2040,9 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
20032040
// Analyze the CFG of the function, and all instructions.
20042041
bool NestingDetected = Visit(F, BBStates, Retains, Releases);
20052042

2043+
if (DisableRetainReleasePairing)
2044+
return false;
2045+
20062046
// Transform.
20072047
bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains,
20082048
Releases,
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt -objc-arc-contract -S < %s | FileCheck -check-prefix=ENABLE %s
2+
; RUN: opt -objc-arc-contract -arc-contract-max-bb-size=3 -S < %s | FileCheck -check-prefix=DISABLE %s
3+
4+
@g0 = common global i8* null, align 8
5+
6+
; ENABLE: store i8* %2, i8** @g0
7+
; DISABLE: store i8* %1, i8** @g0
8+
9+
define void @foo0() {
10+
%1 = tail call i8* @foo1()
11+
%2 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %1)
12+
store i8* %1, i8** @g0, align 8
13+
ret void
14+
}
15+
16+
declare i8* @foo1()
17+
declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: opt -objc-arc -S < %s | FileCheck -check-prefix=ENABLE -check-prefix=CHECK %s
2+
; RUN: opt -objc-arc -arc-opt-max-ptr-states=1 -S < %s | FileCheck -check-prefix=DISABLE -check-prefix=CHECK %s
3+
4+
@g0 = common global i8* null, align 8
5+
6+
; CHECK: call i8* @llvm.objc.retain
7+
; ENABLE-NOT: call i8* @llvm.objc.retain
8+
; DISABLE: call i8* @llvm.objc.retain
9+
; CHECK: call void @llvm.objc.release
10+
; ENABLE-NOT: call void @llvm.objc.release
11+
; DISABLE: call void @llvm.objc.release
12+
13+
define void @foo0(i8* %a) {
14+
%1 = tail call i8* @llvm.objc.retain(i8* %a)
15+
%2 = tail call i8* @llvm.objc.retain(i8* %a)
16+
%3 = load i8*, i8** @g0, align 8
17+
store i8* %a, i8** @g0, align 8
18+
tail call void @llvm.objc.release(i8* %3)
19+
tail call void @llvm.objc.release(i8* %a), !clang.imprecise_release !0
20+
ret void
21+
}
22+
23+
declare i8* @llvm.objc.retain(i8*)
24+
declare void @llvm.objc.release(i8*)
25+
26+
!0 = !{}

0 commit comments

Comments
 (0)