From: Reid Kleckner Date: Wed, 22 Oct 2014 17:26:00 +0000 (+0000) Subject: MS ABI: Emit more canonical vbptr stores and loads X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b7f05872636b6eaf6f0b11b177b812dee891c19f;p=clang MS ABI: Emit more canonical vbptr stores and loads This eliminates some i8* GEPs and makes the IR that clang emits a bit more canonical. More work is needed for vftables, but that isn't a clear win so I plan to send it for review. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220398 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index dd0846958f..9e5bbd130b 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -457,6 +457,7 @@ private: int32_t VBPtrOffset, int32_t VBTableOffset, llvm::Value **VBPtr = nullptr) { + assert(VBTableOffset % 4 == 0 && "should be byte offset into table of i32s"); llvm::Value *VBPOffset = llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), *VBTOffset = llvm::ConstantInt::get(CGM.IntTy, VBTableOffset); return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); @@ -917,9 +918,10 @@ void MicrosoftCXXABI::EmitVBPtrStores(CodeGenFunction &CGF, Offs += Layout.getVBaseClassOffset(VBT->getVBaseWithVPtr()); llvm::Value *VBPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ThisInt8Ptr, Offs.getQuantity()); - VBPtr = CGF.Builder.CreateBitCast(VBPtr, GV->getType()->getPointerTo(0), + llvm::Value *GVPtr = CGF.Builder.CreateConstInBoundsGEP2_32(GV, 0, 0); + VBPtr = CGF.Builder.CreateBitCast(VBPtr, GVPtr->getType()->getPointerTo(0), "vbptr." + VBT->ReusingBase->getName()); - CGF.Builder.CreateStore(GV, VBPtr); + CGF.Builder.CreateStore(GVPtr, VBPtr); } } @@ -2237,11 +2239,17 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value *VBPtr = Builder.CreateInBoundsGEP(This, VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; - VBPtr = Builder.CreateBitCast(VBPtr, CGM.Int8PtrTy->getPointerTo(0)); + VBPtr = Builder.CreateBitCast(VBPtr, + CGM.Int32Ty->getPointerTo(0)->getPointerTo(0)); llvm::Value *VBTable = Builder.CreateLoad(VBPtr, "vbtable"); + // Translate from byte offset to table index. It improves analyzability. + llvm::Value *VBTableIndex = Builder.CreateAShr( + VBTableOffset, llvm::ConstantInt::get(VBTableOffset->getType(), 2), + "vbtindex", /*isExact=*/true); + // Load an i32 offset from the vb-table. - llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableOffset); + llvm::Value *VBaseOffs = Builder.CreateInBoundsGEP(VBTable, VBTableIndex); VBaseOffs = Builder.CreateBitCast(VBaseOffs, CGM.Int32Ty->getPointerTo(0)); return Builder.CreateLoad(VBaseOffs, "vbase_offs"); } diff --git a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp index 225407b7fa..f2e9da7cca 100644 --- a/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp +++ b/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp @@ -20,11 +20,10 @@ T* test1(V* x) { return &dynamic_cast(*x); } T* test2(A* x) { return &dynamic_cast(*x); } // CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) // CHECK: [[CAST:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[VBOFFS]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1) // CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T* @@ -34,11 +33,10 @@ T* test3(B* x) { return &dynamic_cast(*x); } // CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) // CHECK: [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR:%.*]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[DELTA]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 1) @@ -57,11 +55,10 @@ T* test5(A* x) { return dynamic_cast(x); } // CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) // CHECK-NEXT: [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T* @@ -75,11 +72,10 @@ T* test6(B* x) { return dynamic_cast(x); } // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUT@@@8" to i8*), i32 0) @@ -99,11 +95,10 @@ void* test8(A* x) { return dynamic_cast(x); } // CHECK: [[CHECK:%.*]] = icmp eq %struct.A* %x, null // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[VOIDP:%.*]] = bitcast %struct.A* %x to i8* -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast %struct.A* %x to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = getelementptr inbounds %struct.A* %x, i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32 [[VBOFFS]] // CHECK-NEXT: [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) // CHECK-NEXT: br label @@ -116,11 +111,10 @@ void* test9(B* x) { return dynamic_cast(x); } // CHECK-NEXT: br i1 [[CHECK]] // CHECK: [[CAST:%.*]] = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 // CHECK-NEXT: [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]], i32 4 -// CHECK-NEXT: [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4 -// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32* -// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4 +// CHECK-NEXT: [[VBPTRPTR:%.*]] = bitcast i8* [[VBPTR]] to i32** +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBPTRPTR]], align 4 +// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBOFFS:%.*]] = load i32* [[VBOFFP]], align 4 // CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32 [[DELTA]] // CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]]) diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index c574bf7c3f..f403aff294 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -275,11 +275,11 @@ int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) { // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1 // CHECK: %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8* // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %[[v6]], i32 0 -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr1]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr1_shr:.*]] = ashr exact i32 %[[memptr1]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr1_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[v10:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // CHECK: %[[offset:.*]] = getelementptr inbounds i8* %[[v10]], i32 %[[memptr0]] // CHECK: %[[v11:.*]] = bitcast i8* %[[offset]] to i32* @@ -309,11 +309,11 @@ int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) { // // CHECK: [[vadjust]] // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %[[base]], i32 %[[memptr1]] -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr2]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr2_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[base_adj:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // // CHECK: [[skip]] @@ -360,11 +360,11 @@ void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) { // CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1 // CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2 // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8* %{{.*}}, i32 0 -// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i8** -// CHECK: %[[vbtable:.*]] = load i8** %[[vbptr_a:.*]] -// CHECK: %[[v7:.*]] = getelementptr inbounds i8* %[[vbtable]], i32 %[[memptr2]] -// CHECK: %[[v8:.*]] = bitcast i8* %[[v7]] to i32* -// CHECK: %[[vbase_offs:.*]] = load i32* %[[v8]] +// CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32** +// CHECK: %[[vbtable:.*]] = load i32** %[[vbptr_a:.*]] +// CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2 +// CHECK: %[[v7:.*]] = getelementptr inbounds i32* %[[vbtable]], i32 %[[memptr2_shr]] +// CHECK: %[[vbase_offs:.*]] = load i32* %[[v7]] // CHECK: %[[v10:.*]] = getelementptr inbounds i8* %[[vbptr]], i32 %[[vbase_offs]] // CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8* %[[v10]], i32 %[[memptr1]] // CHECK: %[[fptr:.*]] = bitcast i8* %[[memptr0]] to void ({{.*}}) diff --git a/test/CodeGenCXX/microsoft-abi-structors.cpp b/test/CodeGenCXX/microsoft-abi-structors.cpp index 7d3992b994..c8633527d6 100644 --- a/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -229,8 +229,8 @@ C::C() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::C"* %{{.*}} to i8* // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8C@constructors@@7B@", [2 x i32]** %[[vbptr]] + // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8C@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::C"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* @@ -264,8 +264,8 @@ D::D() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::D"* %{{.*}} to i8* // CHECK-NEXT: %[[vbptr_off:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8D@constructors@@7B@", [2 x i32]** %[[vbptr]] + // CHECK-NEXT: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8D@constructors@@7B@", i32 0, i32 0), i32** %[[vbptr]] // CHECK-NEXT: bitcast %"struct.constructors::D"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* @@ -291,11 +291,11 @@ E::E() { // CHECK: [[INIT_VBASES]] // CHECK-NEXT: %[[this_i8:.*]] = bitcast %"struct.constructors::E"* %{{.*}} to i8* // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 0 - // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to [3 x i32]** - // CHECK-NEXT: store [3 x i32]* @"\01??_8E@constructors@@7B01@@", [3 x i32]** %[[vbptr_E]] + // CHECK-NEXT: %[[vbptr_E:.*]] = bitcast i8* %[[offs]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([3 x i32]* @"\01??_8E@constructors@@7B01@@", i32 0, i32 0), i32** %[[vbptr_E]] // CHECK-NEXT: %[[offs:.*]] = getelementptr inbounds i8* %[[this_i8]], i64 4 - // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to [2 x i32]** - // CHECK-NEXT: store [2 x i32]* @"\01??_8E@constructors@@7BC@1@@", [2 x i32]** %[[vbptr_C]] + // CHECK-NEXT: %[[vbptr_C:.*]] = bitcast i8* %[[offs]] to i32** + // CHECK-NEXT: store i32* getelementptr inbounds ([2 x i32]* @"\01??_8E@constructors@@7BC@1@@", i32 0, i32 0), i32** %[[vbptr_C]] // CHECK-NEXT: bitcast %"struct.constructors::E"* %{{.*}} to i8* // CHECK-NEXT: getelementptr inbounds i8* %{{.*}}, i64 4 // CHECK-NEXT: bitcast i8* %{{.*}} to %"struct.constructors::A"* diff --git a/test/CodeGenCXX/microsoft-abi-thunks.cpp b/test/CodeGenCXX/microsoft-abi-thunks.cpp index c755b30006..f1602c8064 100644 --- a/test/CodeGenCXX/microsoft-abi-thunks.cpp +++ b/test/CodeGenCXX/microsoft-abi-thunks.cpp @@ -128,10 +128,9 @@ I::I() {} // Emits vftable and forces thunk generation. // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"\01?goo@I@@UAEPAUF@@XZ" // CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8* // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[ORIG_RET_i8]], i32 4 -// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8** -// CODEGEN: %[[VBTABLE:.*]] = load i8** %[[VBPTR]] -// CODEGEN: %[[VBASE_OFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 8 -// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = bitcast i8* %[[VBASE_OFFSET_PTR_i8]] to i32* +// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32** +// CODEGEN: %[[VBTABLE:.*]] = load i32** %[[VBPTR]] +// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 2 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32* %[[VBASE_OFFSET_PTR]] // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]] // CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F* diff --git a/test/CodeGenCXX/microsoft-abi-typeid.cpp b/test/CodeGenCXX/microsoft-abi-typeid.cpp index 4ee004d51d..1beb211812 100644 --- a/test/CodeGenCXX/microsoft-abi-typeid.cpp +++ b/test/CodeGenCXX/microsoft-abi-typeid.cpp @@ -31,11 +31,10 @@ const std::type_info* test3_typeid() { return &typeid(*fn()); } // CHECK: tail call i8* @__RTtypeid(i8* null) // CHECK-NEXT: unreachable // CHECK: [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8* -// CHECK-NEXT: [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8** -// CHECK-NEXT: [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4 -// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i8* [[VBTBL]], i32 4 -// CHECK-NEXT: [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32* -// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4 +// CHECK-NEXT: [[VBTBLP:%.*]] = getelementptr inbounds %struct.A* [[CALL]], i32 0, i32 0 +// CHECK-NEXT: [[VBTBL:%.*]] = load i32** [[VBTBLP]], align 4 +// CHECK-NEXT: [[VBSLOT:%.*]] = getelementptr inbounds i32* [[VBTBL]], i32 1 +// CHECK-NEXT: [[VBASE_OFFS:%.*]] = load i32* [[VBSLOT]], align 4 // CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]], i32 [[VBASE_OFFS]] // CHECK-NEXT: [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]]) // CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info* diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp index a6fcdea749..26eb01205c 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp @@ -72,10 +72,9 @@ G::G() {} // Forces vftable emission. // CHECK: %[[VTORDISP_NEG:.*]] = sub i32 0, %[[VTORDISP]] // CHECK: %[[VTORDISP_ADJUSTED_i8:.*]] = getelementptr i8* %[[ECX_i8]], i32 %[[VTORDISP_NEG]] // CHECK: %[[VBPTR_i8:.*]] = getelementptr inbounds i8* %[[VTORDISP_ADJUSTED_i8]], i32 -16 -// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR]] -// CHECK: %[[VBOFFSET_PTR_i8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 12 -// CHECK: %[[VBOFFSET_PTR:.*]] = bitcast i8* %[[VBOFFSET_PTR_i8]] to i32* +// CHECK: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR]] +// CHECK: %[[VBOFFSET_PTR:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 3 // CHECK: %[[VBASE_OFFSET:.*]] = load i32* %[[VBOFFSET_PTR]] // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]] // CHECK: %[[ARG_i8:.*]] = getelementptr i8* %[[VBASE]], i32 8 diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 2f0fffee69..18d47cea48 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -122,10 +122,9 @@ void B::foo() { // CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]] // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8* @@ -147,10 +146,9 @@ void call_vbase_bar(B *obj) { // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] @@ -161,10 +159,9 @@ void call_vbase_bar(B *obj) { // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] @@ -181,10 +178,9 @@ void delete_B(B *obj) { delete obj; // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] @@ -195,10 +191,9 @@ void delete_B(B *obj) { // // CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8* // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0 -// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8** -// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]] -// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4 -// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32* +// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i32** +// CHECK: %[[VBTABLE:.*]] = load i32** %[[VBPTR8]] +// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32* %[[VBTABLE]], i32 1 // CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]] // CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]] // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]] diff --git a/test/CodeGenCXX/virtual-base-cast.cpp b/test/CodeGenCXX/virtual-base-cast.cpp index 6a4894b63b..0dcf319d7d 100644 --- a/test/CodeGenCXX/virtual-base-cast.cpp +++ b/test/CodeGenCXX/virtual-base-cast.cpp @@ -20,11 +20,10 @@ A* a() { return x; } // MSVC: @"\01?a@@YAPAUA@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 4 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 1 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -38,11 +37,10 @@ B* b() { return x; } // Same as 'a' except we use a different vbtable offset. // MSVC: @"\01?b@@YAPAUB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 8 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 2 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -58,11 +56,10 @@ BB* c() { return x; } // Same as 'a' except we use a different vbtable offset. // MSVC: @"\01?c@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 0 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 4 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 0, %[[offset]] // MSVC: } @@ -78,11 +75,10 @@ BB* d() { return y; } // final add. // MSVC: @"\01?d@@YAPAUBB@@XZ"() [[NUW:#[0-9]+]] { // MSVC: %[[vbptr_off:.*]] = getelementptr inbounds i8* {{.*}}, i32 4 -// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i8** -// MSVC: %[[vbtable:.*]] = load i8** %[[vbptr]] -// MSVC: %[[entry:.*]] = getelementptr inbounds i8* {{.*}}, i32 16 -// MSVC: %[[entry_i32:.*]] = bitcast i8* %[[entry]] to i32* -// MSVC: %[[offset:.*]] = load i32* %[[entry_i32]] +// MSVC: %[[vbptr:.*]] = bitcast i8* %[[vbptr_off]] to i32** +// MSVC: %[[vbtable:.*]] = load i32** %[[vbptr]] +// MSVC: %[[entry:.*]] = getelementptr inbounds i32* {{.*}}, i32 4 +// MSVC: %[[offset:.*]] = load i32* %[[entry]] // MSVC: add nsw i32 4, %[[offset]] // MSVC: }