const DataLayout &MDL = Preheader->getModule()->getDataLayout();
- bool IsKnownThreadLocalObject = false;
if (SafetyInfo->anyBlockMayThrow()) {
// If a loop can throw, we have to insert a store along each unwind edge.
// That said, we can't actually make the unwind edge explicit. Therefore,
Value *Object = getUnderlyingObject(SomePtr);
if (!isNotVisibleOnUnwindInLoop(Object, CurLoop, DT))
return false;
- // Subtlety: Alloca's aren't visible to callers, but *are* potentially
- // visible to other threads if captured and used during their lifetimes.
- IsKnownThreadLocalObject = !isa<AllocaInst>(Object);
}
// Check that all accesses to pointers in the alias set use the same type.
// stores along paths which originally didn't have them without violating the
// memory model.
if (!SafeToInsertStore) {
- if (IsKnownThreadLocalObject)
- SafeToInsertStore = true;
- else {
- Value *Object = getUnderlyingObject(SomePtr);
- SafeToInsertStore =
- (isNoAliasCall(Object) || isa<AllocaInst>(Object)) &&
- isNotCapturedBeforeOrInLoop(Object, CurLoop, DT);
- }
+ Value *Object = getUnderlyingObject(SomePtr);
+ SafeToInsertStore =
+ (isNoAliasCall(Object) || isa<AllocaInst>(Object) ||
+ (isa<Argument>(Object) && cast<Argument>(Object)->hasByValAttr())) &&
+ isNotCapturedBeforeOrInLoop(Object, CurLoop, DT);
}
// If we've still failed to prove we can sink the store, hoist the load
ret void
}
-; FIXME: Should not get promoted, because the pointer is captured and may not
+; Should not get promoted, because the pointer is captured and may not
; be thread-local.
define void @test_captured_before_loop_byval(i32* byval(i32) align 4 %count, i32 %len) {
; CHECK-LABEL: @test_captured_before_loop_byval(
; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[LATCH]]
; CHECK: if:
; CHECK-NEXT: [[C_INC:%.*]] = add i32 [[C_INC2]], 1
+; CHECK-NEXT: store i32 [[C_INC]], i32* [[COUNT]], align 4
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[C_INC1]] = phi i32 [ [[C_INC]], [[IF]] ], [ [[C_INC2]], [[LOOP]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[LEN:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
-; CHECK-NEXT: [[C_INC1_LCSSA:%.*]] = phi i32 [ [[C_INC1]], [[LATCH]] ]
-; CHECK-NEXT: store i32 [[C_INC1_LCSSA]], i32* [[COUNT]], align 4
; CHECK-NEXT: ret void
;
entry:
; CHECK-LABEL: @test_captured_after_loop_byval(
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 0, i32* [[COUNT:%.*]], align 4
-; CHECK-NEXT: call void @capture(i32* [[COUNT]])
; CHECK-NEXT: [[COUNT_PROMOTED:%.*]] = load i32, i32* [[COUNT]], align 4
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK: exit:
; CHECK-NEXT: [[C_INC1_LCSSA:%.*]] = phi i32 [ [[C_INC1]], [[LATCH]] ]
; CHECK-NEXT: store i32 [[C_INC1_LCSSA]], i32* [[COUNT]], align 4
+; CHECK-NEXT: call void @capture(i32* [[COUNT]])
; CHECK-NEXT: ret void
;
entry:
store i32 0, i32* %count
- call void @capture(i32* %count)
br label %loop
loop:
br i1 %cmp, label %exit, label %loop
exit:
+ call void @capture(i32* %count)
ret void
}