With codegen prior to this patch, truly indirect arguments -- i.e.
those that are not `byval` -- can have their debug information lost even
at O0. Because indirect arguments are passed by pointer, and this
pointer is likely placed in a register as per the function call ABI,
debug information is lost as soon as the register gets clobbered.
This patch solves the issue by storing the address of the parameter on
the stack, using a similar strategy employed when C++ references are
passed. In other words, this patch changes codegen from:
```
define @foo(ptr %arg) {
call void @llvm.dbg.declare(%arg, [...], metadata !DIExpression())
```
To:
```
define @foo(ptr %arg) {
%ptr_storage = alloca ptr
store ptr %arg, ptr %ptr_storage
call void @llvm.dbg.declare(%ptr_storage, [...], metadata !DIExpression(DW_OP_deref))
```
Some common cases where this may happen with C or C++ function calls:
1. "Big enough" trivial structures passed by value under the ARM ABI.
2. Structures that are non-trivial for the purposes of call (as per
the Itanium ABI) when passed by value.
A few tests were matching the wrong alloca (matching against the new
alloca, instead of the old one), so they were updated to either match
both allocas or include a `,` right after the alloca type, to prevent
matching against a pointer type.
Differential Revision: https://reviews.llvm.org/D141381
- Clang can now generate a PCH when using ``-fdelayed-template-parsing`` for
code with templates containing loop hint pragmas, OpenMP pragmas, and
``#pragma unused``.
+- Clang now saves the address of ABI-indirect function parameters on the stack,
+ improving the debug information available in programs compiled without
+ optimizations.
New Compiler Flags
llvm::DILocalVariable *
CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder) {
+ unsigned ArgNo, CGBuilderTy &Builder,
+ const bool UsePointerValue) {
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
- return EmitDeclare(VD, AI, ArgNo, Builder);
+ return EmitDeclare(VD, AI, ArgNo, Builder, UsePointerValue);
}
namespace {
/// Emit call to \c llvm.dbg.declare for an argument variable
/// declaration.
- llvm::DILocalVariable *EmitDeclareOfArgVariable(const VarDecl *Decl,
- llvm::Value *AI,
- unsigned ArgNo,
- CGBuilderTy &Builder);
+ llvm::DILocalVariable *
+ EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, unsigned ArgNo,
+ CGBuilderTy &Builder, bool UsePointerValue = false);
/// Emit call to \c llvm.dbg.declare for the block-literal argument
/// to a block invocation function.
Address AllocaPtr = Address::invalid();
bool DoStore = false;
bool IsScalar = hasScalarEvaluationKind(Ty);
+ bool UseIndirectDebugAddress = false;
+
// If we already have a pointer to the argument, reuse the input pointer.
if (Arg.isIndirect()) {
// If we have a prettier pointer type at this point, bitcast to that.
auto AllocaAS = CGM.getASTAllocaAddressSpace();
auto *V = DeclPtr.getPointer();
AllocaPtr = DeclPtr;
+
+ // For truly ABI indirect arguments -- those that are not `byval` -- store
+ // the address of the argument on the stack to preserve debug information.
+ ABIArgInfo ArgInfo = CurFnInfo->arguments()[ArgNo - 1].info;
+ if (ArgInfo.isIndirect())
+ UseIndirectDebugAddress = !ArgInfo.getIndirectByVal();
+ if (UseIndirectDebugAddress) {
+ auto PtrTy = getContext().getPointerType(Ty);
+ AllocaPtr = CreateMemTemp(PtrTy, getContext().getTypeAlignInChars(PtrTy),
+ D.getName() + ".indirect_addr");
+ EmitStoreOfScalar(V, AllocaPtr, /* Volatile */ false, PtrTy);
+ }
+
auto SrcLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : AllocaAS;
auto DestLangAS =
getLangOpts().OpenCL ? LangAS::opencl_private : LangAS::Default;
if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk &&
!NoDebugInfo) {
llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable(
- &D, AllocaPtr.getPointer(), ArgNo, Builder);
+ &D, AllocaPtr.getPointer(), ArgNo, Builder, UseIndirectDebugAddress);
if (const auto *Var = dyn_cast_or_null<ParmVarDecl>(&D))
DI->getParamDbgMappings().insert({Var, DILocalVar});
}
// CHECK-C-LABEL: define {{[^@]+}}@test_st64b(
// CHECK-C-NEXT: entry:
// CHECK-C-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-C-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-C-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-C-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-C-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[BYVAL_TEMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-C-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-C-NEXT: store ptr [[BYVAL_TEMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-C-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-C-NEXT: [[TMP2:%.*]] = load i64, ptr [[BYVAL_TEMP]], align 8
// CHECK-C-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[BYVAL_TEMP]], i32 1
// CHECK-CXX-LABEL: define {{[^@]+}}@test_st64b(
// CHECK-CXX-NEXT: entry:
// CHECK-CXX-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-CXX-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-CXX-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-CXX-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-CXX-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-CXX-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-CXX-NEXT: store ptr [[AGG_TMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-CXX-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-CXX-NEXT: [[TMP2:%.*]] = load i64, ptr [[AGG_TMP]], align 8
// CHECK-CXX-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[AGG_TMP]], i32 1
// CHECK-C-LABEL: define {{[^@]+}}@test_st64bv(
// CHECK-C-NEXT: entry:
// CHECK-C-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-C-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-C-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-C-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-C-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[BYVAL_TEMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-C-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-C-NEXT: store ptr [[BYVAL_TEMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-C-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-C-NEXT: [[TMP2:%.*]] = load i64, ptr [[BYVAL_TEMP]], align 8
// CHECK-C-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[BYVAL_TEMP]], i32 1
// CHECK-CXX-LABEL: define {{[^@]+}}@test_st64bv(
// CHECK-CXX-NEXT: entry:
// CHECK-CXX-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-CXX-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-CXX-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-CXX-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-CXX-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-CXX-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-CXX-NEXT: store ptr [[AGG_TMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-CXX-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-CXX-NEXT: [[TMP2:%.*]] = load i64, ptr [[AGG_TMP]], align 8
// CHECK-CXX-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[AGG_TMP]], i32 1
// CHECK-C-LABEL: define {{[^@]+}}@test_st64bv0(
// CHECK-C-NEXT: entry:
// CHECK-C-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-C-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-C-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-C-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-C-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[BYVAL_TEMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-C-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-C-NEXT: store ptr [[BYVAL_TEMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-C-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-C-NEXT: [[TMP2:%.*]] = load i64, ptr [[BYVAL_TEMP]], align 8
// CHECK-C-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[BYVAL_TEMP]], i32 1
// CHECK-CXX-LABEL: define {{[^@]+}}@test_st64bv0(
// CHECK-CXX-NEXT: entry:
// CHECK-CXX-NEXT: [[__ADDR_ADDR_I:%.*]] = alloca ptr, align 8
+// CHECK-CXX-NEXT: [[VALUE_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK-CXX-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8
// CHECK-CXX-NEXT: [[TMP0:%.*]] = load ptr, ptr @addr, align 8
// CHECK-CXX-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_TMP]], ptr align 8 @val, i64 64, i1 false)
// CHECK-CXX-NEXT: store ptr [[TMP0]], ptr [[__ADDR_ADDR_I]], align 8
+// CHECK-CXX-NEXT: store ptr [[AGG_TMP]], ptr [[VALUE_INDIRECT_ADDR]], align 8
// CHECK-CXX-NEXT: [[TMP1:%.*]] = load ptr, ptr [[__ADDR_ADDR_I]], align 8
// CHECK-CXX-NEXT: [[TMP2:%.*]] = load i64, ptr [[AGG_TMP]], align 8
// CHECK-CXX-NEXT: [[TMP3:%.*]] = getelementptr i64, ptr [[AGG_TMP]], i32 1
}
// CHECK-LABEL:define{{.*}} void @test4(
-// CHECK: [[TEMP:%.*]] = alloca [[QUAD_T:%.*]], align 8
+// CHECK-SAME: ptr noundef [[QUAD:%.*]])
+// CHECK: [[QUAD_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[TEMP:%.*]] = alloca [[QUAD_T:%.*]], align 8
+// CHECK-NEXT: store ptr [[QUAD]], ptr [[QUAD_INDIRECT_ADDR]]
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TEMP]], ptr align 8 {{%.*}}, i64 32, i1 false)
// CHECK-NEXT: call void @__atomic_store(i64 noundef 32, ptr noundef @a_pointer_quad, ptr noundef [[TEMP]], i32 noundef 5)
void test4(pointer_quad_t quad) {
void func_with_ref_arg(B &b);
// CHECK-LABEL: @_Z22func_with_indirect_arg1A(
+// CHECK-SAME: ptr addrspace(5) noundef [[ARG:%.*]])
// CHECK-NEXT: entry:
+// CHECK-NEXT: [[INDIRECT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
// CHECK-NEXT: [[P:%.*]] = alloca ptr, align 8, addrspace(5)
+// CHECK-NEXT: [[INDIRECT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[INDIRECT_ADDR]] to ptr
// CHECK-NEXT: [[P_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P]] to ptr
+// CHECK-NEXT: store ptr addrspace(5) [[ARG]], ptr [[INDIRECT_ADDR_ASCAST]]
// CHECK-NEXT: [[A_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A:%.*]] to ptr
// CHECK-NEXT: store ptr [[A_ASCAST]], ptr [[P_ASCAST]], align 8
// CHECK-NEXT: ret void
// CHECK: @_ZN6pr96081xE ={{.*}} global ptr null, align 8, !dbg [[X:![0-9]+]]
// CHECK: define{{.*}} void @_ZN7pr147634funcENS_3fooE
-// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata !DIExpression())
+// CHECK-SAME: ptr noundef [[param:%.*]])
+// CHECK-NEXT: entry:
+// CHECK-NEXT: alloca ptr, align 8
+// CHECK-NEXT: [[param_addr_storage:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: store
+// CHECK-NEXT: store ptr [[param]], ptr [[param_addr_storage]], align 8
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[param_addr_storage]], metadata ![[F:[0-9]+]], metadata !DIExpression(DW_OP_deref))
// !llvm.dbg.cu pulls in globals and their types first.
// CHECK-NOT: !DIGlobalVariable(name: "c"
void test0(X x) {
test0_helper(x);
// CHECK-LABEL: define{{.*}} void @_Z5test01X(
- // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align
+ // CHECK-SAME: ptr noundef [[ARG:%.*]])
+ // CHECK: [[ARG_ADDR:%.*]] = alloca ptr
+ // CHECK-NEXT: [[TMP:%.*]] = alloca [[A:%.*]], align
+ // CHECK-NEXT: store ptr [[ARG]], ptr [[ARG_ADDR]]
// CHECK-NEXT: [[T0:%.*]] = call noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN1XcvR1BEv(
// CHECK-NEXT: call void @_ZN1AC1ERKS_(ptr {{[^,]*}} [[TMP]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[T0]])
// CHECK-NEXT: call void @_Z12test0_helper1A(ptr noundef [[TMP]])
// TODO: Add support for CopyOnly params
// CHECK: define{{.*}} void @_Z1fi8MoveOnly11MoveAndCopy(i32 noundef %val, %struct.MoveOnly* noundef %[[MoParam:.+]], %struct.MoveAndCopy* noundef %[[McParam:.+]]) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*
void f(int val, MoveOnly moParam, MoveAndCopy mcParam) {
- // CHECK: %[[MoCopy:.+]] = alloca %struct.MoveOnly
- // CHECK: %[[McCopy:.+]] = alloca %struct.MoveAndCopy
+ // CHECK: %[[MoCopy:.+]] = alloca %struct.MoveOnly,
+ // CHECK: %[[McCopy:.+]] = alloca %struct.MoveAndCopy,
// CHECK: store i32 %val, i32* %[[ValAddr:.+]]
// CHECK: call i8* @llvm.coro.begin(
// CHECK-LABEL: void @_Z16dependent_paramsI1A1BEvT_T0_S3_(%struct.A* noundef %x, %struct.B* noundef %0, %struct.B* noundef %y)
template <typename T, typename U>
void dependent_params(T x, U, U y) {
- // CHECK: %[[x_copy:.+]] = alloca %struct.A
+ // CHECK: %[[x_copy:.+]] = alloca %struct.A,
// CHECK-NEXT: %[[unnamed_copy:.+]] = alloca %struct.B
// CHECK-NEXT: %[[y_copy:.+]] = alloca %struct.B
// TODO: Add support for CopyOnly params
// CHECK: define{{.*}} void @_Z1fi8MoveOnly11MoveAndCopy(i32 noundef %val, %struct.MoveOnly* noundef %[[MoParam:.+]], %struct.MoveAndCopy* noundef %[[McParam:.+]]) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*
void f(int val, MoveOnly moParam, MoveAndCopy mcParam) {
- // CHECK: %[[MoCopy:.+]] = alloca %struct.MoveOnly
- // CHECK: %[[McCopy:.+]] = alloca %struct.MoveAndCopy
+ // CHECK: %[[MoCopy:.+]] = alloca %struct.MoveOnly,
+ // CHECK: %[[McCopy:.+]] = alloca %struct.MoveAndCopy,
// CHECK: store i32 %val, i32* %[[ValAddr:.+]]
// CHECK: call i8* @llvm.coro.begin(
// CHECK-LABEL: void @_Z16dependent_paramsI1A1BEvT_T0_S3_(%struct.A* noundef %x, %struct.B* noundef %0, %struct.B* noundef %y)
template <typename T, typename U>
void dependent_params(T x, U, U y) {
- // CHECK: %[[x_copy:.+]] = alloca %struct.A
+ // CHECK: %[[x_copy:.+]] = alloca %struct.A,
// CHECK-NEXT: %[[unnamed_copy:.+]] = alloca %struct.B
// CHECK-NEXT: %[[y_copy:.+]] = alloca %struct.B
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK13-NEXT: entry:
// CHECK13-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK13-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK13-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK13-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK13-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK13-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK13-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]]) #[[ATTR4]]
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK15-NEXT: entry:
// CHECK15-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK15-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK15-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK15-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK15-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK15-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK15-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK1-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK1-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK1-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK1-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK1-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK3-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], ptr noundef nonnull align 4 dereferenceable(4) [[TMP0]], ptr noundef [[T]])
// CHECK3-NEXT: entry:
// CHECK3-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK3-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK3-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK3-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK3-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK3-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK3-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK9-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK9-NEXT: entry:
// CHECK9-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 8
+// CHECK9-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 8
// CHECK9-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 8
+// CHECK9-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 8
// CHECK9-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK9-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK9-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 8
// CHECK11-NEXT: entry:
// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK11-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK11-NEXT: call void @_ZN1SIfEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK11-NEXT: entry:
// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK11-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK11-NEXT: entry:
// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK11-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4
// CHECK11-NEXT: call void @_ZN1SIiEC2ERKS0_2St(ptr nonnull align 4 dereferenceable(4) [[THIS1]], ptr nonnull align 4 dereferenceable(4) [[TMP0]], ptr [[T]])
// CHECK11-NEXT: entry:
// CHECK11-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: [[S_ADDR:%.*]] = alloca ptr, align 4
+// CHECK11-NEXT: [[T_INDIRECT_ADDR:%.*]] = alloca ptr, align 4
// CHECK11-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: store ptr [[S]], ptr [[S_ADDR]], align 4
+// CHECK11-NEXT: store ptr [[T]], ptr [[T_INDIRECT_ADDR]], align 4
// CHECK11-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
// CHECK11-NEXT: [[F:%.*]] = getelementptr inbounds [[STRUCT_S_0:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK11-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S_ADDR]], align 4