Index: lib/Transforms/Scalar/SROA.cpp =================================================================== --- lib/Transforms/Scalar/SROA.cpp +++ lib/Transforms/Scalar/SROA.cpp @@ -1735,9 +1735,13 @@ if (!S.isSplittable()) return false; // Skip any unsplittable intrinsics. } else if (IntrinsicInst *II = dyn_cast(U->getUser())) { + // lifetime.start and lifetime.end are promotable, but we avoid + // promoting them in some cases if asan is enabled. if (II->getIntrinsicID() != Intrinsic::lifetime_start && II->getIntrinsicID() != Intrinsic::lifetime_end) return false; + if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress)) + return false; } else if (U->get()->getType()->getPointerElementType()->isStructTy()) { // Disable vector promotion when there are loads or stores of an FCA. return false; @@ -1947,9 +1951,13 @@ if (!S.isSplittable()) return false; // Skip any unsplittable intrinsics. } else if (IntrinsicInst *II = dyn_cast(U->getUser())) { + // lifetime.start and lifetime.end are promotable, but we avoid + // promoting them in some cases if asan is enabled. if (II->getIntrinsicID() != Intrinsic::lifetime_start && II->getIntrinsicID() != Intrinsic::lifetime_end) return false; + if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress)) + return false; } else { return false; } @@ -2875,6 +2883,23 @@ // Record this instruction for deletion. Pass.DeadInsts.insert(&II); + // Lifetime intrinsics are only promotable if they cover the whole alloca. + // Therefore, we drop lifetime intrinsics which don't cover the whole + // alloca. + // + // As an exception to this rule, don't drop the intrinsics if asan is + // enabled, to enable more precise lifetime tracking. + // + // (In theory, intrinsics which partially cover an alloca could be + // promoted, but PromoteMemToReg doesn't handle that case.) + // FIXME: Check whether the alloca is promotable before dropping the + // lifetime intrinsics? + bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset && + NewEndOffset == NewAllocaEndOffset; + if (!II.getFunction()->hasFnAttribute(Attribute::SanitizeAddress) && + !IsWholeAlloca) + return true; + ConstantInt *Size = ConstantInt::get(cast(II.getArgOperand(0)->getType()), NewEndOffset - NewBeginOffset); @@ -2888,11 +2913,6 @@ (void)New; DEBUG(dbgs() << " to: " << *New << "\n"); - // Lifetime intrinsics are only promotable if they cover the whole alloca. - // (In theory, intrinsics which partially cover an alloca could be - // promoted, but PromoteMemToReg doesn't handle that case.) - bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset && - NewEndOffset == NewAllocaEndOffset; return IsWholeAlloca; } Index: test/Transforms/SROA/basictest.ll =================================================================== --- test/Transforms/SROA/basictest.ll +++ test/Transforms/SROA/basictest.ll @@ -1672,6 +1672,20 @@ define void @PR27999() unnamed_addr { ; CHECK-LABEL: @PR27999( +; CHECK: entry-block: +; CHECK-NEXT: ret void +entry-block: + %0 = alloca [2 x i64], align 8 + %1 = bitcast [2 x i64]* %0 to i8* + call void @llvm.lifetime.start(i64 16, i8* %1) + %2 = getelementptr inbounds [2 x i64], [2 x i64]* %0, i32 0, i32 1 + %3 = bitcast i64* %2 to i8* + call void @llvm.lifetime.end(i64 8, i8* %3) + ret void +} + +define void @PR27999_asan() sanitize_address { +; CHECK-LABEL: @PR27999_asan( ; CHECK: alloca [2 x i64], align 8 ; CHECK: call void @llvm.lifetime.start(i64 16, ; CHECK: call void @llvm.lifetime.end(i64 8, @@ -1684,3 +1698,27 @@ call void @llvm.lifetime.end(i64 8, i8* %3) ret void } + +define void @PR29139() { +; CHECK-LABEL: @PR29139( +; CHECK: bb1: +; CHECK-NEXT: ret void +bb1: + %e.7.sroa.6.i = alloca i32, align 1 + %e.7.sroa.6.0.load81.i = load i32, i32* %e.7.sroa.6.i, align 1 + %0 = bitcast i32* %e.7.sroa.6.i to i8* + call void @llvm.lifetime.end(i64 2, i8* %0) + ret void +} + +define void @PR29139_asan() sanitize_address { +; CHECK-LABEL: @PR29139_asan( +; CHECK: alloca i32 +; CHECK: call void @llvm.lifetime.end(i64 2 +bb1: + %e.7.sroa.6.i = alloca i32, align 1 + %e.7.sroa.6.0.load81.i = load i32, i32* %e.7.sroa.6.i, align 1 + %0 = bitcast i32* %e.7.sroa.6.i to i8* + call void @llvm.lifetime.end(i64 2, i8* %0) + ret void +}