From f50ab0ffce8fdb58a0859e070ecd660c0ed8f6cd Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Tue, 8 Sep 2015 10:36:42 +0000 Subject: [PATCH] findDominatingStoreToReturn in CGCall.cpp didn't check if a candidate store instruction used the ReturnValue as pointer operand or value operand. This led to wrong code gen - in later stages (load-store elision code) the found store and its operand would be erased, causing ReturnValue to become a . The patch adds a check that makes sure that ReturnValue is a pointer operand of store instruction. Regression test is also added. This fixes PR24386. Differential Revision: http://reviews.llvm.org/D12400 llvm-svn: 247003 --- clang/lib/CodeGen/CGCall.cpp | 25 ++++++++++++---------- clang/test/CodeGen/arm_function_epilog.cpp | 17 +++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 clang/test/CodeGen/arm_function_epilog.cpp diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index e8760111f01a..ef9095291cdf 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2259,6 +2259,18 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { + // Check if a User is a store which pointerOperand is the ReturnValue. + // We are looking for stores to the ReturnValue, not for stores of the + // ReturnValue to some other location. + auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { + auto *SI = dyn_cast(U); + if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer()) + return nullptr; + // These aren't actually possible for non-coerced returns, and we + // only care about non-coerced returns on this code path. + assert(!SI->isAtomic() && !SI->isVolatile()); + return SI; + }; // If there are multiple uses of the return-value slot, just check // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen @@ -2287,22 +2299,13 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { break; } - llvm::StoreInst *store = dyn_cast(I); - if (!store) return nullptr; - if (store->getPointerOperand() != CGF.ReturnValue.getPointer()) - return nullptr; - assert(!store->isAtomic() && !store->isVolatile()); // see below - return store; + return GetStoreIfValid(I); } llvm::StoreInst *store = - dyn_cast(CGF.ReturnValue.getPointer()->user_back()); + GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); if (!store) return nullptr; - // These aren't actually possible for non-coerced returns, and we - // only care about non-coerced returns on this code path. - assert(!store->isAtomic() && !store->isVolatile()); - // Now do a first-and-dirty dominance check: just walk up the // single-predecessors chain from the current insertion point. llvm::BasicBlock *StoreBB = store->getParent(); diff --git a/clang/test/CodeGen/arm_function_epilog.cpp b/clang/test/CodeGen/arm_function_epilog.cpp new file mode 100644 index 000000000000..00895078b1f8 --- /dev/null +++ b/clang/test/CodeGen/arm_function_epilog.cpp @@ -0,0 +1,17 @@ +// REQUIRES: arm-registered-target +// RUN: %clang_cc1 -triple armv7-none-linux-androideabi -target-abi aapcs-linux -mfloat-abi hard -x c++ -emit-llvm %s -o - | FileCheck %s + +struct Vec2 { + union { struct { float x, y; }; + float data[2]; + }; +}; + +// CHECK: define arm_aapcs_vfpcc %struct.Vec2 @_Z7getVec2v() +// CHECK: ret %struct.Vec2 +Vec2 getVec2() { + Vec2 out; + union { Vec2* v; unsigned char* u; } x; + x.v = &out; + return out; +}