[CGCall] Make findDominatingStoreToReturnValue() more robust

This was skipping specific lifetime + bitcast patterns, but with
opaque pointers the bitcast will not be present, and we did not
perform this fold.

Instead skip over lifetime.end and bitcasts generally, without
trying to correlate them.
This commit is contained in:
Nikita Popov 2022-04-08 15:16:03 +02:00
parent 0e0b0feff1
commit 692a147bf4
2 changed files with 39 additions and 20 deletions

View File

@ -3242,28 +3242,19 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
if (!CGF.ReturnValue.getPointer()->hasOneUse()) {
llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock();
if (IP->empty()) return nullptr;
llvm::Instruction *I = &IP->back();
// Skip lifetime markers
for (llvm::BasicBlock::reverse_iterator II = IP->rbegin(),
IE = IP->rend();
II != IE; ++II) {
if (llvm::IntrinsicInst *Intrinsic =
dyn_cast<llvm::IntrinsicInst>(&*II)) {
if (Intrinsic->getIntrinsicID() == llvm::Intrinsic::lifetime_end) {
const llvm::Value *CastAddr = Intrinsic->getArgOperand(1);
++II;
if (II == IE)
break;
if (isa<llvm::BitCastInst>(&*II) && (CastAddr == &*II))
continue;
}
}
I = &*II;
break;
// Look at directly preceding instruction, skipping bitcasts and lifetime
// markers.
for (llvm::Instruction &I : make_range(IP->rbegin(), IP->rend())) {
if (isa<llvm::BitCastInst>(&I))
continue;
if (auto *II = dyn_cast<llvm::IntrinsicInst>(&I))
if (II->getIntrinsicID() == llvm::Intrinsic::lifetime_end)
continue;
return GetStoreIfValid(&I);
}
return GetStoreIfValid(I);
return nullptr;
}
llvm::StoreInst *store =

View File

@ -0,0 +1,28 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -opaque-pointers -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix=NO-LIFETIME
// RUN: %clang_cc1 -opaque-pointers -O1 -disable-llvm-optzns -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix=LIFETIME
// NO-LIFETIME-LABEL: @main(
// NO-LIFETIME-NEXT: entry:
// NO-LIFETIME-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
// NO-LIFETIME-NEXT: [[FOO:%.*]] = alloca i32, align 4
// NO-LIFETIME-NEXT: [[FOO2:%.*]] = alloca i32, align 4
// NO-LIFETIME-NEXT: store i32 0, ptr [[RETVAL]], align 4
// NO-LIFETIME-NEXT: ret i32 0
//
// LIFETIME-LABEL: @main(
// LIFETIME-NEXT: entry:
// LIFETIME-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
// LIFETIME-NEXT: [[FOO:%.*]] = alloca i32, align 4
// LIFETIME-NEXT: [[FOO2:%.*]] = alloca i32, align 4
// LIFETIME-NEXT: store i32 0, ptr [[RETVAL]], align 4
// LIFETIME-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[FOO]]) #[[ATTR2:[0-9]+]]
// LIFETIME-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[FOO2]]) #[[ATTR2]]
// LIFETIME-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[FOO2]]) #[[ATTR2]]
// LIFETIME-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[FOO]]) #[[ATTR2]]
// LIFETIME-NEXT: ret i32 0
//
int main() {
unsigned foo, foo2;
return 0;
}