[IR] Change representation of getelementptr inrange (#84341)
As part of the migration to ptradd (https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699), we need to change the representation of the `inrange` attribute, which is used for vtable splitting. Currently, inrange is specified as follows: ``` getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @vt, i64 0, inrange i32 1, i64 2) ``` The `inrange` is placed on a GEP index, and all accesses must be "in range" of that index. The new representation is as follows: ``` getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @vt, i64 0, i32 1, i64 2) ``` This specifies which offsets are "in range" of the GEP result. The new representation will continue working when canonicalizing to ptradd representation: ``` getelementptr inbounds inrange(-16, 16) (i8, ptr @vt, i64 48) ``` The inrange offsets are relative to the return value of the GEP. An alternative design could make them relative to the source pointer instead. The result-relative format was chosen on the off-chance that we want to extend support to non-constant GEPs in the future, in which case this variant is more expressive. This implementation "upgrades" the old inrange representation in bitcode by simply dropping it. This is a very niche feature, and I don't think trying to upgrade it is worthwhile. Let me know if you disagree.
This commit is contained in:
parent
1f63a56ced
commit
0f46e31cfb
@ -77,9 +77,18 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
|
||||
llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
|
||||
};
|
||||
|
||||
// Add inrange attribute to indicate that only the VTableIndex can be
|
||||
// accessed.
|
||||
unsigned ComponentSize =
|
||||
CGM.getDataLayout().getTypeAllocSize(getVTableComponentType());
|
||||
unsigned VTableSize = CGM.getDataLayout().getTypeAllocSize(
|
||||
cast<llvm::StructType>(VTable->getValueType())
|
||||
->getElementType(AddressPoint.VTableIndex));
|
||||
unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
|
||||
llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
|
||||
llvm::APInt(32, VTableSize - Offset, true));
|
||||
llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
|
||||
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true,
|
||||
/*InRangeIndex=*/1);
|
||||
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
|
||||
|
||||
VTTComponents.push_back(Init);
|
||||
}
|
||||
|
||||
@ -1885,19 +1885,27 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
|
||||
|
||||
// Find the appropriate vtable within the vtable group, and the address point
|
||||
// within that vtable.
|
||||
const VTableLayout &Layout =
|
||||
CGM.getItaniumVTableContext().getVTableLayout(VTableClass);
|
||||
VTableLayout::AddressPointLocation AddressPoint =
|
||||
CGM.getItaniumVTableContext()
|
||||
.getVTableLayout(VTableClass)
|
||||
.getAddressPoint(Base);
|
||||
Layout.getAddressPoint(Base);
|
||||
llvm::Value *Indices[] = {
|
||||
llvm::ConstantInt::get(CGM.Int32Ty, 0),
|
||||
llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
|
||||
llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
|
||||
};
|
||||
|
||||
return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable,
|
||||
Indices, /*InBounds=*/true,
|
||||
/*InRangeIndex=*/1);
|
||||
// Add inrange attribute to indicate that only the VTableIndex can be
|
||||
// accessed.
|
||||
unsigned ComponentSize =
|
||||
CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType());
|
||||
unsigned VTableSize =
|
||||
ComponentSize * Layout.getVTableSize(AddressPoint.VTableIndex);
|
||||
unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
|
||||
llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
|
||||
llvm::APInt(32, VTableSize - Offset, true));
|
||||
return llvm::ConstantExpr::getGetElementPtr(
|
||||
VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
|
||||
}
|
||||
|
||||
// Check whether all the non-inline virtual methods for the class have the
|
||||
|
||||
@ -9,19 +9,19 @@
|
||||
// CHECK: @_ZTV1B.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 8, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4
|
||||
|
||||
// VTT for B
|
||||
// CHECK: @_ZTT1B ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, inrange i32 1, i32 3)], align 8
|
||||
// CHECK: @_ZTT1B ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3)], align 8
|
||||
|
||||
// VTable for C
|
||||
// CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 8, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4
|
||||
|
||||
// VTT for C
|
||||
// CHECK: @_ZTT1C ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, inrange i32 1, i32 3)], align 8
|
||||
// CHECK: @_ZTT1C ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3)], align 8
|
||||
|
||||
// VTable for D
|
||||
// CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32], [4 x i32] } { [5 x i32] [i32 16, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 8, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -16, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3) to i64)) to i32)] }, align 4
|
||||
|
||||
// VTT for D
|
||||
// CHECK: @_ZTT1D ={{.*}} unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 1, i32 3)], align 8
|
||||
// CHECK: @_ZTT1D ={{.*}} unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds inrange(-12, 8) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3)], align 8
|
||||
|
||||
// Construction vtable for B-in-D
|
||||
// CHECK: @_ZTC1D0_1B.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 16, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -16, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4
|
||||
|
||||
@ -1345,7 +1345,7 @@ TEST_UNINIT(base, base);
|
||||
// PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]]
|
||||
// ZERO-LABEL: @test_base_uninit()
|
||||
// ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]]
|
||||
// ZERO-O1: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, inrange i32 0, i64 2), {{.*}}, align 8
|
||||
// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, i32 0, i64 2), {{.*}}, align 8
|
||||
// ZERO-O1-NOT: !annotation
|
||||
|
||||
TEST_BRACES(base, base);
|
||||
@ -1366,7 +1366,7 @@ TEST_UNINIT(derived, derived);
|
||||
// ZERO-LABEL: @test_derived_uninit()
|
||||
// ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]]
|
||||
// ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]]
|
||||
// ZERO-O1: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, inrange i32 0, i64 2), {{.*}} align 8
|
||||
// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, i32 0, i64 2), {{.*}} align 8
|
||||
|
||||
TEST_BRACES(derived, derived);
|
||||
// CHECK-LABEL: @test_derived_braces()
|
||||
|
||||
@ -344,13 +344,13 @@ namespace VirtualMembers {
|
||||
constexpr E() : B(3), c{'b','y','e'} {}
|
||||
char c[3];
|
||||
};
|
||||
// CHECK: @_ZN14VirtualMembers1eE ={{.*}} global { ptr, double, i32, ptr, double, [5 x i8], i16, ptr, double, [5 x i8], [3 x i8] } { ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 0, i32 2), double 1.000000e+00, i32 64, ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" }
|
||||
// CHECK: @_ZN14VirtualMembers1eE ={{.*}} global { ptr, double, i32, ptr, double, [5 x i8], i16, ptr, double, [5 x i8], [3 x i8] } { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 0, i32 2), double 1.000000e+00, i32 64, ptr getelementptr inbounds inrange(-16, 16) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, ptr getelementptr inbounds inrange(-16, 16) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" }
|
||||
E e;
|
||||
|
||||
struct nsMemoryImpl {
|
||||
virtual void f();
|
||||
};
|
||||
// CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global %"struct.VirtualMembers::nsMemoryImpl" { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, inrange i32 0, i32 2) }
|
||||
// CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global %"struct.VirtualMembers::nsMemoryImpl" { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, i32 0, i32 2) }
|
||||
__attribute__((used))
|
||||
static nsMemoryImpl sGlobalMemory;
|
||||
|
||||
@ -361,7 +361,7 @@ namespace VirtualMembers {
|
||||
|
||||
T t;
|
||||
};
|
||||
// CHECK: @_ZN14VirtualMembers1tE ={{.*}} global { ptr, i32 } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, inrange i32 0, i32 2), i32 42 }
|
||||
// CHECK: @_ZN14VirtualMembers1tE ={{.*}} global { ptr, i32 } { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, i32 0, i32 2), i32 42 }
|
||||
TemplateClass<int> t;
|
||||
}
|
||||
|
||||
|
||||
@ -94,20 +94,20 @@ namespace InitVTable {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN10InitVTable1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr [[THIS:%.*]],
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr [[THIS:%.*]],
|
||||
// CHECK: [[VTBL:%.*]] = load ptr, ptr {{%.*}}
|
||||
// CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds ptr, ptr [[VTBL]], i64 0
|
||||
// CHECK-NEXT: [[FN:%.*]] = load ptr, ptr [[FNP]]
|
||||
// CHECK-NEXT: [[ARG:%.*]] = call noundef i32 [[FN]](ptr {{[^,]*}} [[THIS]])
|
||||
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei(ptr {{[^,]*}} {{%.*}}, i32 noundef [[ARG]])
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr [[THIS]]
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr [[THIS]]
|
||||
// CHECK-NEXT: ret void
|
||||
B::B() : A(foo()) {}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN10InitVTable1BC2Ei(ptr {{[^,]*}} %this, i32 noundef %x) unnamed_addr
|
||||
// CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5
|
||||
// CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei(ptr {{[^,]*}} {{%.*}}, i32 noundef [[ARG]])
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr {{%.*}}
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr {{%.*}}
|
||||
// CHECK-NEXT: ret void
|
||||
B::B(int x) : A(x + 5) {}
|
||||
}
|
||||
|
||||
@ -24,4 +24,4 @@ struct A { virtual void a(); };
|
||||
A x(A& y) { return y; }
|
||||
|
||||
// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(ptr {{.*}}%this, ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %0) unnamed_addr
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2)
|
||||
|
||||
@ -163,7 +163,7 @@ void f(B b1) {
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_(
|
||||
// CHECK: [[THIS:%.*]] = load ptr, ptr
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN12rdar138169401AE, i32 0, inrange i32 0, i32 2), ptr [[THIS]]
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTVN12rdar138169401AE, i32 0, i32 0, i32 2), ptr [[THIS]]
|
||||
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], ptr [[THIS]], i32 0, i32 1
|
||||
// CHECK-NEXT: [[OTHER:%.*]] = load ptr, ptr
|
||||
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], ptr [[OTHER]], i32 0, i32 1
|
||||
|
||||
@ -23,7 +23,7 @@ B *exact_single(A *a) {
|
||||
|
||||
// CHECK: [[LABEL_NOTNULL]]:
|
||||
// CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 1, i32 2)
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2)
|
||||
// CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -8
|
||||
// CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]
|
||||
|
||||
@ -42,7 +42,7 @@ B &exact_ref(A &a) {
|
||||
|
||||
// CHECK: [[LABEL_NOTNULL]]:
|
||||
// CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 1, i32 2)
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2)
|
||||
// CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -8
|
||||
// CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]
|
||||
|
||||
@ -66,7 +66,7 @@ H *exact_multi(A *a) {
|
||||
// CHECK: %[[OFFSET_TO_TOP:.*]] = load i64, ptr %[[OFFSET_TO_TOP_SLOT]]
|
||||
// CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 %[[OFFSET_TO_TOP]]
|
||||
// CHECK: %[[DERIVED_VPTR:.*]] = load ptr, ptr %[[RESULT]]
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[DERIVED_VPTR]], getelementptr inbounds ({ [5 x ptr], [4 x ptr], [4 x ptr], [6 x ptr], [6 x ptr] }, ptr @_ZTV1H, i32 0, inrange i32 0, i32 3)
|
||||
// CHECK: %[[MATCH:.*]] = icmp eq ptr %[[DERIVED_VPTR]], getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr], [4 x ptr], [6 x ptr], [6 x ptr] }, ptr @_ZTV1H, i32 0, i32 0, i32 3)
|
||||
// CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]
|
||||
|
||||
// CHECK: [[LABEL_FAILED]]:
|
||||
|
||||
@ -31,10 +31,10 @@ int fn() {
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1SC2Ev(ptr {{[^,]*}} %this)
|
||||
// CHECK: call x86_thiscallcc void @_ZN1IC2Ev(ptr {{[^,]*}} %{{[.0-9A-Z_a-z]+}})
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i32 0, inrange i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}}
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1S, i32 0, i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}}
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1IC2Ev(ptr {{[^,]*}} %this)
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1I, i32 0, inrange i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}}
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1I, i32 0, i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}}
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i32 @_ZN1I4testEv(ptr {{[^,]*}} %this)
|
||||
// CHECK: ret i32 1
|
||||
|
||||
@ -27,7 +27,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test21AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test21AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test21AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A() {
|
||||
f();
|
||||
}
|
||||
@ -50,7 +50,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test31AD2Ev
|
||||
// CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test31AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK-NOT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test31AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A() {
|
||||
|
||||
}
|
||||
@ -76,7 +76,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test41AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test41AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test41AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A()
|
||||
{
|
||||
}
|
||||
@ -100,7 +100,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test51AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test51AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test51AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A()
|
||||
{
|
||||
}
|
||||
@ -128,7 +128,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test61AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test61AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test61AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A()
|
||||
{
|
||||
}
|
||||
@ -154,7 +154,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test71AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test71AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test71AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A()
|
||||
{
|
||||
}
|
||||
@ -180,7 +180,7 @@ struct A {
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN5Test81AD2Ev
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test81AE, i32 0, inrange i32 0, i32 2), ptr
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test81AE, i32 0, i32 0, i32 2), ptr
|
||||
A::~A()
|
||||
{
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}}
|
||||
// CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16
|
||||
// CHECK98: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" zeroinitializer, comdat, align 8
|
||||
// CHECK11: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test49HasVTableE, i32 0, inrange i32 0, i32 2) }, comdat, align 8
|
||||
// CHECK11: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test49HasVTableE, i32 0, i32 0, i32 2) }, comdat, align 8
|
||||
|
||||
struct A {
|
||||
A();
|
||||
|
||||
@ -154,10 +154,10 @@ struct DynamicDerivedMultiple;
|
||||
// CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
|
||||
// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0
|
||||
|
||||
// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2), {{.*}} %[[THIS0]]
|
||||
// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 0, i32 2), ptr %[[THIS0]]
|
||||
// CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, ptr %[[THIS0]], i64 16
|
||||
|
||||
// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2), {{.*}} %[[THIS_ADD]]
|
||||
// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 1, i32 2), ptr %[[THIS_ADD]]
|
||||
// CHECK-CTORS-LABEL: {{^}}}
|
||||
|
||||
struct DynamicFromStatic;
|
||||
|
||||
@ -207,7 +207,7 @@ namespace test27 {
|
||||
// CHECK-HIDDEN: @_ZGVZN6test681fC1EvE4test = linkonce_odr hidden global
|
||||
|
||||
// CHECK-HIDDEN: @_ZTVN6test701DE = linkonce_odr hidden unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZTIN6test701DE] }, align 8
|
||||
// CHECK-HIDDEN: @_ZTTN6test701DE = linkonce_odr hidden unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN6test701DE, i32 0, inrange i32 0, i32 3)], align 8
|
||||
// CHECK-HIDDEN: @_ZTTN6test701DE = linkonce_odr hidden unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @_ZTVN6test701DE, i32 0, i32 0, i32 3)], align 8
|
||||
|
||||
// CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global
|
||||
// CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global
|
||||
|
||||
@ -25,7 +25,7 @@ void g(A *a) { a->foo(); }
|
||||
// CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv()
|
||||
// CHECK1: call void @_ZN5test11AC1Ev(ptr
|
||||
// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}}
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, i32 0, i32 2)
|
||||
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK1-LABEL: {{^}}}
|
||||
|
||||
@ -37,7 +37,7 @@ void fooA() {
|
||||
// CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv()
|
||||
// CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}})
|
||||
// CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}}
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, i32 0, i32 2)
|
||||
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK1-LABEL: {{^}}}
|
||||
|
||||
@ -71,12 +71,12 @@ void h(B *b) { b->bar(); }
|
||||
// CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv()
|
||||
// CHECK2: call void @_ZN5test21CC1Ev(ptr
|
||||
// CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}}
|
||||
// CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 0, i32 2)
|
||||
// CHECK2: call void @llvm.assume(i1 %[[CMP]])
|
||||
|
||||
// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8
|
||||
// CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %[[ADD_PTR]]
|
||||
// CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2)
|
||||
// CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 1, i32 2)
|
||||
// CHECK2: call void @llvm.assume(i1 %[[CMP2]])
|
||||
|
||||
// CHECK2: call void @_ZN5test21gEPNS_1AE(
|
||||
@ -107,7 +107,7 @@ void g(B *a) { a->foo(); }
|
||||
|
||||
// CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv()
|
||||
// CHECK3: call void @_ZN5test31CC1Ev(ptr
|
||||
// CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3)
|
||||
// CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, i32 0, i32 3)
|
||||
// CHECK3: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK3-LABLEL: }
|
||||
void test() {
|
||||
@ -136,11 +136,11 @@ void g(C *c) { c->foo(); }
|
||||
// CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv()
|
||||
// CHECK4: call void @_ZN5test41CC1Ev(ptr
|
||||
// CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}}
|
||||
// CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
|
||||
// CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4)
|
||||
// CHECK4: call void @llvm.assume(i1 %[[CMP]]
|
||||
|
||||
// CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %{{.*}}
|
||||
// CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
|
||||
// CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4)
|
||||
// CHECK4: call void @llvm.assume(i1 %[[CMP2]])
|
||||
// CHECK4-LABEL: {{^}}}
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ void g(A *a) { a->foo(); }
|
||||
// CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv()
|
||||
// CHECK1: call void @_ZN5test11AC1Ev(ptr
|
||||
// CHECK1: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test11AE, i32 0, i32 0, i32 2)
|
||||
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK1-LABEL: {{^}}}
|
||||
|
||||
@ -39,7 +39,7 @@ void fooA() {
|
||||
// CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv()
|
||||
// CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}})
|
||||
// CHECK1: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test11BE, i32 0, i32 0, i32 2)
|
||||
// CHECK1: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK1-LABEL: {{^}}}
|
||||
|
||||
@ -73,12 +73,12 @@ void h(B *b) { b->bar(); }
|
||||
// CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv()
|
||||
// CHECK2: call void @_ZN5test21CC1Ev(ptr
|
||||
// CHECK2: %[[VTABLE:.*]] = load ptr, ptr {{.*}}
|
||||
// CHECK2: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK2: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, i32 0, i32 2)
|
||||
// CHECK2: call void @llvm.assume(i1 %[[CMP]])
|
||||
|
||||
// CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8
|
||||
// CHECK2: %[[VTABLE2:.*]] = load ptr, ptr %[[ADD_PTR]]
|
||||
// CHECK2: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2)
|
||||
// CHECK2: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, i32 1, i32 2)
|
||||
// CHECK2: call void @llvm.assume(i1 %[[CMP2]])
|
||||
|
||||
// CHECK2: call void @_ZN5test21gEPNS_1AE(
|
||||
@ -109,7 +109,7 @@ void g(B *a) { a->foo(); }
|
||||
|
||||
// CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv()
|
||||
// CHECK3: call void @_ZN5test31CC1Ev(ptr
|
||||
// CHECK3: %[[CMP:.*]] = icmp eq ptr %{{.*}}, getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3)
|
||||
// CHECK3: %[[CMP:.*]] = icmp eq ptr %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr] }, ptr @_ZTVN5test31CE, i32 0, i32 0, i32 3)
|
||||
// CHECK3: call void @llvm.assume(i1 %[[CMP]])
|
||||
// CHECK3-LABLEL: }
|
||||
void test() {
|
||||
@ -138,11 +138,11 @@ void g(C *c) { c->foo(); }
|
||||
// CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv()
|
||||
// CHECK4: call void @_ZN5test41CC1Ev(ptr
|
||||
// CHECK4: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}
|
||||
// CHECK4: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
|
||||
// CHECK4: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, i32 0, i32 4)
|
||||
// CHECK4: call void @llvm.assume(i1 %[[CMP]]
|
||||
|
||||
// CHECK4: %[[VTABLE2:.*]] = load ptr, ptr %{{.*}}
|
||||
// CHECK4: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4)
|
||||
// CHECK4: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, i32 0, i32 4)
|
||||
// CHECK4: call void @llvm.assume(i1 %[[CMP2]])
|
||||
// CHECK4-LABEL: {{^}}}
|
||||
|
||||
|
||||
@ -21,13 +21,13 @@ struct A : Base {
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: call void @_ZN4BaseC2Ev(
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldC1Ev(
|
||||
// CHECK: ret void
|
||||
A::A() { }
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldD1Ev(
|
||||
// CHECK: call void @_ZN4BaseD2Ev(
|
||||
// CHECK: ret void
|
||||
@ -49,12 +49,12 @@ void f() { B b; }
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: call void @_ZN4BaseC2Ev(
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldC1Ev
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldD1Ev(
|
||||
// CHECK: call void @_ZN4BaseD2Ev(
|
||||
// CHECK: ret void
|
||||
|
||||
@ -21,13 +21,13 @@ struct A : Base {
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: call void @_ZN4BaseC2Ev(
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldC1Ev(
|
||||
// CHECK: ret void
|
||||
A::A() { }
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldD1Ev(
|
||||
// CHECK: call void @_ZN4BaseD2Ev(
|
||||
// CHECK: ret void
|
||||
@ -49,12 +49,12 @@ void f() { B b; }
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: call void @_ZN4BaseC2Ev(
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldC1Ev
|
||||
// CHECK: ret void
|
||||
|
||||
// CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr
|
||||
// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2)
|
||||
// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2)
|
||||
// CHECK: call void @_ZN5FieldD1Ev(
|
||||
// CHECK: call void @_ZN4BaseD2Ev(
|
||||
// CHECK: ret void
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Test {
|
||||
D d;
|
||||
}
|
||||
|
||||
// CHECK: linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 0, i32 5), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)], comdat, align 8
|
||||
// CHECK: linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-40, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 0, i32 5), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, i32 1, i32 3)], comdat, align 8
|
||||
// CHECK: call void @_ZN4Test2V2C2Ev(ptr noundef nonnull align 8 dereferenceable(20) %2, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 11))
|
||||
// CHECK: call void @_ZN4Test2C1C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this1, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 1))
|
||||
// CHECK: call void @_ZN4Test2C2C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %3, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 3))
|
||||
|
||||
@ -78,12 +78,12 @@ namespace Test6 {
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr addrspace(1) constant [1 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3)]
|
||||
// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr addrspace(1) constant [1 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test11BE, i32 0, i32 0, i32 3)]
|
||||
// CHECK: @_ZTVN5Test51AE ={{.*}} unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test51AE, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN5Test51A6anchorEv to ptr addrspace(1))] }
|
||||
// CHECK: @_ZTVN5Test61AE ={{.*}} unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test61AE, ptr addrspace(1) addrspacecast (ptr @__cxa_deleted_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN5Test61A6anchorEv to ptr addrspace(1))] }
|
||||
// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr addrspace(1) constant [2 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4)]
|
||||
// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)]
|
||||
// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr addrspace(1) constant [2 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, i32 0, i32 4)]
|
||||
// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-40, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 0, i32 5), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 1, i32 3)]
|
||||
// CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant { [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [6 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 72 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 56 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 40 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test41DE], [8 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 40 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 24 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 56 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) inttoptr (i64 -16 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE, ptr addrspace(1) addrspacecast (ptr @_ZN5Test42V31gEv to ptr addrspace(1))], [3 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -40 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE], [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) inttoptr (i64 -56 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE, ptr addrspace(1) addrspacecast (ptr @_ZN5Test42A21fEv to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -32 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -72 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE] }
|
||||
// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant [19 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3)]
|
||||
// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant [19 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-48, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 1, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 4, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 2, i32 3)]
|
||||
// CHECK: declare void @__cxa_pure_virtual() unnamed_addr
|
||||
// CHECK: declare void @__cxa_deleted_virtual() unnamed_addr
|
||||
|
||||
@ -78,12 +78,12 @@ namespace Test6 {
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3)]
|
||||
// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr] }, ptr @_ZTVN5Test11BE, i32 0, i32 0, i32 3)]
|
||||
// CHECK: @_ZTVN5Test51AE ={{.*}} unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN5Test51AE, ptr @__cxa_pure_virtual, ptr @_ZN5Test51A6anchorEv] }
|
||||
// CHECK: @_ZTVN5Test61AE ={{.*}} unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN5Test61AE, ptr @__cxa_deleted_virtual, ptr @_ZN5Test61A6anchorEv] }
|
||||
// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4)]
|
||||
// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x ptr] [ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)]
|
||||
// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, i32 0, i32 4)]
|
||||
// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x ptr] [ptr getelementptr inbounds inrange(-40, 0) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 0, i32 5), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-48, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-48, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-24, 0) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-48, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr getelementptr inbounds inrange(-48, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr getelementptr inbounds inrange(-24, 0) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 1, i32 3)]
|
||||
// CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] } { [6 x ptr] [ptr inttoptr (i64 72 to ptr), ptr inttoptr (i64 16 to ptr), ptr inttoptr (i64 56 to ptr), ptr inttoptr (i64 40 to ptr), ptr null, ptr @_ZTIN5Test41DE], [8 x ptr] [ptr inttoptr (i64 40 to ptr), ptr inttoptr (i64 24 to ptr), ptr inttoptr (i64 56 to ptr), ptr null, ptr null, ptr inttoptr (i64 -16 to ptr), ptr @_ZTIN5Test41DE, ptr @_ZN5Test42V31gEv], [3 x ptr] [ptr inttoptr (i64 16 to ptr), ptr inttoptr (i64 -40 to ptr), ptr @_ZTIN5Test41DE], [4 x ptr] [ptr null, ptr inttoptr (i64 -56 to ptr), ptr @_ZTIN5Test41DE, ptr @_ZN5Test42A21fEv], [4 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -72 to ptr), ptr @_ZTIN5Test41DE] }
|
||||
// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x ptr] [ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3)]
|
||||
// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x ptr] [ptr getelementptr inbounds inrange(-48, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-32, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-56, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr getelementptr inbounds inrange(-56, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr getelementptr inbounds inrange(-32, 0) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 1, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-24, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-56, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr getelementptr inbounds inrange(-56, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr getelementptr inbounds inrange(-32, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 4, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-32, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 2, i32 3)]
|
||||
// CHECK: declare void @__cxa_pure_virtual() unnamed_addr
|
||||
// CHECK: declare void @__cxa_deleted_virtual() unnamed_addr
|
||||
|
||||
@ -91,7 +91,7 @@ void foo() {
|
||||
// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
|
||||
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
||||
// CHECK-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]]) #[[ATTR1]]
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
// CHECK-LABEL: define {{[^@]+}}@_ZN1AC2Ev
|
||||
// CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 {
|
||||
@ -99,7 +99,7 @@ void foo() {
|
||||
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
||||
// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
|
||||
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1
|
||||
// CHECK-NEXT: store ptr null, ptr [[PTR]], align 8
|
||||
// CHECK-NEXT: ret void
|
||||
@ -168,7 +168,7 @@ void foo() {
|
||||
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
|
||||
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
||||
// CHECK1-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]]) #[[ATTR1]]
|
||||
// CHECK1-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK1-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK1-NEXT: ret void
|
||||
//
|
||||
//
|
||||
@ -178,7 +178,7 @@ void foo() {
|
||||
// CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
|
||||
// CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
|
||||
// CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
|
||||
// CHECK1-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK1-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8
|
||||
// CHECK1-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1
|
||||
// CHECK1-NEXT: store ptr null, ptr [[PTR]], align 8
|
||||
// CHECK1-NEXT: ret void
|
||||
@ -249,7 +249,7 @@ void foo() {
|
||||
// CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
|
||||
// CHECK2-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
|
||||
// CHECK2-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 4 dereferenceable(8) [[THIS1]]) #[[ATTR1]]
|
||||
// CHECK2-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 4
|
||||
// CHECK2-NEXT: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 4
|
||||
// CHECK2-NEXT: ret void
|
||||
//
|
||||
//
|
||||
@ -259,7 +259,7 @@ void foo() {
|
||||
// CHECK2-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4
|
||||
// CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4
|
||||
// CHECK2-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4
|
||||
// CHECK2-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 4
|
||||
// CHECK2-NEXT: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 4
|
||||
// CHECK2-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1
|
||||
// CHECK2-NEXT: store ptr null, ptr [[PTR]], align 4
|
||||
// CHECK2-NEXT: ret void
|
||||
|
||||
@ -36,7 +36,7 @@ entry:
|
||||
store ptr %this, ptr %this.addr
|
||||
%this1 = load ptr, ptr %this.addr
|
||||
call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this1)
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr %this1
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr %this1
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ entry:
|
||||
%this.addr = alloca ptr
|
||||
store ptr %this, ptr %this.addr
|
||||
%this1 = load ptr, ptr %this.addr
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr %this1
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr %this1
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ define linkonce_odr void @_ZN1BC2Ev(ptr %this) #0 {
|
||||
%this.addr = alloca ptr, align 8
|
||||
store ptr %this, ptr %this.addr, align 8
|
||||
%this1 = load ptr, ptr %this.addr, align 8
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr %this1, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr %this1, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ declare dso_local void @_ZNK3Cat9makeNoiseEv(ptr nonnull dereferenceable(8)) unn
|
||||
define dso_local void @_Z17useDoThingWithCatv() local_unnamed_addr {
|
||||
entry:
|
||||
%call = tail call noalias nonnull dereferenceable(8) ptr @_Znwm(i64 8)
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV3Cat, i64 0, inrange i32 0, i64 2), ptr %call, align 8, !tbaa !4
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV3Cat, i64 0, i32 0, i64 2), ptr %call, align 8, !tbaa !4
|
||||
tail call void @_Z14doThingWithCatP6Animal(ptr nonnull %call)
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ entry:
|
||||
%this.addr = alloca ptr, align 8
|
||||
store ptr %this, ptr %this.addr, align 8
|
||||
%this1 = load ptr, ptr %this.addr, align 8
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr %this1, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr %this1, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -57,14 +57,14 @@ target triple = "x86_64-apple-macosx11.0.0"
|
||||
; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable
|
||||
define void @_ZN1SC2Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable
|
||||
define void @_ZN1SC1Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -11049,9 +11049,10 @@ Syntax:
|
||||
|
||||
::
|
||||
|
||||
<result> = getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
|
||||
<result> = getelementptr <ty>, <N x ptr> <ptrval>, [inrange] <vector index type> <idx>
|
||||
<result> = getelementptr <ty>, ptr <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <ty>, ptr <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inrange(S,E) <ty>, ptr <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr <ty>, <N x ptr> <ptrval>, <vector index type> <idx>
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
@ -11196,16 +11197,15 @@ These rules are based on the assumption that no allocated object may cross
|
||||
the unsigned address space boundary, and no allocated object may be larger
|
||||
than half the pointer index type space.
|
||||
|
||||
If the ``inrange`` keyword is present before any index, loading from or
|
||||
If the ``inrange(Start, End)`` attribute is present, loading from or
|
||||
storing to any pointer derived from the ``getelementptr`` has undefined
|
||||
behavior if the load or store would access memory outside of the bounds of
|
||||
the element selected by the index marked as ``inrange``. The result of a
|
||||
pointer comparison or ``ptrtoint`` (including ``ptrtoint``-like operations
|
||||
behavior if the load or store would access memory outside the half-open range
|
||||
``[Start, End)`` from the ``getelementptr`` expression result. The result of
|
||||
a pointer comparison or ``ptrtoint`` (including ``ptrtoint``-like operations
|
||||
involving memory) involving a pointer derived from a ``getelementptr`` with
|
||||
the ``inrange`` keyword is undefined, with the exception of comparisons
|
||||
in the case where both operands are in the range of the element selected
|
||||
by the ``inrange`` keyword, inclusive of the address one past the end of
|
||||
that element. Note that the ``inrange`` keyword is currently only allowed
|
||||
in the case where both operands are in the closed range ``[Start, End]``.
|
||||
Note that the ``inrange`` keyword is currently only allowed
|
||||
in constant ``getelementptr`` expressions.
|
||||
|
||||
The getelementptr instruction is often confusing. For some more insight
|
||||
|
||||
@ -563,8 +563,7 @@ namespace llvm {
|
||||
Type *ExpectedTy = nullptr);
|
||||
bool parseGlobalValue(Type *Ty, Constant *&C);
|
||||
bool parseGlobalTypeAndValue(Constant *&V);
|
||||
bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts,
|
||||
std::optional<unsigned> *InRangeOp = nullptr);
|
||||
bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts);
|
||||
bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
|
||||
bool parseSanitizer(GlobalVariable *GV);
|
||||
bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS);
|
||||
|
||||
@ -399,18 +399,19 @@ enum ConstantsCodes {
|
||||
CST_CODE_DATA = 22, // DATA: [n x elements]
|
||||
CST_CODE_INLINEASM_OLD2 = 23, // INLINEASM: [sideeffect|alignstack|
|
||||
// asmdialect,asmstr,conststr]
|
||||
CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands]
|
||||
CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval]
|
||||
CST_CODE_POISON = 26, // POISON
|
||||
CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv]
|
||||
CST_CODE_INLINEASM_OLD3 = 28, // INLINEASM: [sideeffect|alignstack|
|
||||
// asmdialect|unwind,
|
||||
// asmstr,conststr]
|
||||
CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ]
|
||||
CST_CODE_INLINEASM = 30, // INLINEASM: [fnty,
|
||||
// sideeffect|alignstack|
|
||||
// asmdialect|unwind,
|
||||
// asmstr,conststr]
|
||||
CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD = 24, // [opty, flags, n x operands]
|
||||
CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval]
|
||||
CST_CODE_POISON = 26, // POISON
|
||||
CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv]
|
||||
CST_CODE_INLINEASM_OLD3 = 28, // INLINEASM: [sideeffect|alignstack|
|
||||
// asmdialect|unwind,
|
||||
// asmstr,conststr]
|
||||
CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ]
|
||||
CST_CODE_INLINEASM = 30, // INLINEASM: [fnty,
|
||||
// sideeffect|alignstack|
|
||||
// asmdialect|unwind,
|
||||
// asmstr,conststr]
|
||||
CST_CODE_CE_GEP_WITH_INRANGE = 31, // [opty, flags, range, n x operands]
|
||||
};
|
||||
|
||||
/// CastOpcodes - These are values used in the bitcode files to encode which
|
||||
|
||||
@ -53,7 +53,7 @@ namespace llvm {
|
||||
Constant *ConstantFoldCompareInstruction(CmpInst::Predicate Predicate,
|
||||
Constant *C1, Constant *C2);
|
||||
Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool InBounds,
|
||||
std::optional<unsigned> InRangeIndex,
|
||||
std::optional<ConstantRange> InRange,
|
||||
ArrayRef<Value *> Idxs);
|
||||
} // End llvm namespace
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/OperandTraits.h"
|
||||
@ -1195,31 +1196,31 @@ public:
|
||||
/// Getelementptr form. Value* is only accepted for convenience;
|
||||
/// all elements must be Constants.
|
||||
///
|
||||
/// \param InRangeIndex the inrange index if present or std::nullopt.
|
||||
/// \param InRange the inrange range if present or std::nullopt.
|
||||
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
|
||||
static Constant *
|
||||
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList,
|
||||
bool InBounds = false,
|
||||
std::optional<unsigned> InRangeIndex = std::nullopt,
|
||||
std::optional<ConstantRange> InRange = std::nullopt,
|
||||
Type *OnlyIfReducedTy = nullptr) {
|
||||
return getGetElementPtr(
|
||||
Ty, C, ArrayRef((Value *const *)IdxList.data(), IdxList.size()),
|
||||
InBounds, InRangeIndex, OnlyIfReducedTy);
|
||||
InBounds, InRange, OnlyIfReducedTy);
|
||||
}
|
||||
static Constant *
|
||||
getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false,
|
||||
std::optional<unsigned> InRangeIndex = std::nullopt,
|
||||
std::optional<ConstantRange> InRange = std::nullopt,
|
||||
Type *OnlyIfReducedTy = nullptr) {
|
||||
// This form of the function only exists to avoid ambiguous overload
|
||||
// warnings about whether to convert Idx to ArrayRef<Constant *> or
|
||||
// ArrayRef<Value *>.
|
||||
return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, InRangeIndex,
|
||||
return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, InRange,
|
||||
OnlyIfReducedTy);
|
||||
}
|
||||
static Constant *
|
||||
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList,
|
||||
bool InBounds = false,
|
||||
std::optional<unsigned> InRangeIndex = std::nullopt,
|
||||
std::optional<ConstantRange> InRange = std::nullopt,
|
||||
Type *OnlyIfReducedTy = nullptr);
|
||||
|
||||
/// Create an "inbounds" getelementptr. See the documentation for the
|
||||
|
||||
@ -404,7 +404,6 @@ class GEPOperator
|
||||
|
||||
enum {
|
||||
IsInBounds = (1 << 0),
|
||||
// InRangeIndex: bits 1-6
|
||||
};
|
||||
|
||||
void setIsInBounds(bool B) {
|
||||
@ -423,11 +422,7 @@ public:
|
||||
|
||||
/// Returns the offset of the index with an inrange attachment, or
|
||||
/// std::nullopt if none.
|
||||
std::optional<unsigned> getInRangeIndex() const {
|
||||
if (SubclassOptionalData >> 1 == 0)
|
||||
return std::nullopt;
|
||||
return (SubclassOptionalData >> 1) - 1;
|
||||
}
|
||||
std::optional<ConstantRange> getInRange() const;
|
||||
|
||||
inline op_iterator idx_begin() { return op_begin()+1; }
|
||||
inline const_op_iterator idx_begin() const { return op_begin()+1; }
|
||||
|
||||
@ -828,7 +828,7 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1,
|
||||
/// that they aren't implicitly casted by the getelementptr.
|
||||
Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
|
||||
Type *ResultTy, bool InBounds,
|
||||
std::optional<unsigned> InRangeIndex,
|
||||
std::optional<ConstantRange> InRange,
|
||||
const DataLayout &DL, const TargetLibraryInfo *TLI) {
|
||||
Type *IntIdxTy = DL.getIndexType(ResultTy);
|
||||
Type *IntIdxScalarTy = IntIdxTy->getScalarType();
|
||||
@ -856,8 +856,8 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
|
||||
if (!Any)
|
||||
return nullptr;
|
||||
|
||||
Constant *C = ConstantExpr::getGetElementPtr(
|
||||
SrcElemTy, Ops[0], NewIdxs, InBounds, InRangeIndex);
|
||||
Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs,
|
||||
InBounds, InRange);
|
||||
return ConstantFoldConstant(C, DL, TLI);
|
||||
}
|
||||
|
||||
@ -866,7 +866,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
|
||||
ArrayRef<Constant *> Ops,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
const GEPOperator *InnermostGEP = GEP;
|
||||
bool InBounds = GEP->isInBounds();
|
||||
|
||||
Type *SrcElemTy = GEP->getSourceElementType();
|
||||
@ -875,9 +874,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
|
||||
if (!SrcElemTy->isSized() || isa<ScalableVectorType>(SrcElemTy))
|
||||
return nullptr;
|
||||
|
||||
if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy,
|
||||
GEP->isInBounds(), GEP->getInRangeIndex(),
|
||||
DL, TLI))
|
||||
if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy, GEP->isInBounds(),
|
||||
GEP->getInRange(), DL, TLI))
|
||||
return C;
|
||||
|
||||
Constant *Ptr = Ops[0];
|
||||
@ -896,9 +894,12 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
|
||||
DL.getIndexedOffsetInType(
|
||||
SrcElemTy, ArrayRef((Value *const *)Ops.data() + 1, Ops.size() - 1)));
|
||||
|
||||
std::optional<ConstantRange> InRange = GEP->getInRange();
|
||||
if (InRange)
|
||||
InRange = InRange->sextOrTrunc(BitWidth);
|
||||
|
||||
// If this is a GEP of a GEP, fold it all into a single GEP.
|
||||
while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) {
|
||||
InnermostGEP = GEP;
|
||||
InBounds &= GEP->isInBounds();
|
||||
|
||||
SmallVector<Value *, 4> NestedOps(llvm::drop_begin(GEP->operands()));
|
||||
@ -913,6 +914,14 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
|
||||
if (!AllConstantInt)
|
||||
break;
|
||||
|
||||
// TODO: Try to intersect two inrange attributes?
|
||||
if (!InRange) {
|
||||
InRange = GEP->getInRange();
|
||||
if (InRange)
|
||||
// Adjust inrange by offset until now.
|
||||
InRange = InRange->sextOrTrunc(BitWidth).subtract(Offset);
|
||||
}
|
||||
|
||||
Ptr = cast<Constant>(GEP->getOperand(0));
|
||||
SrcElemTy = GEP->getSourceElementType();
|
||||
Offset += APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps));
|
||||
@ -971,21 +980,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
|
||||
NewIdxs.push_back(ConstantInt::get(
|
||||
Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index));
|
||||
|
||||
// Preserve the inrange index from the innermost GEP if possible. We must
|
||||
// have calculated the same indices up to and including the inrange index.
|
||||
std::optional<unsigned> InRangeIndex;
|
||||
if (std::optional<unsigned> LastIRIndex = InnermostGEP->getInRangeIndex())
|
||||
if (SrcElemTy == InnermostGEP->getSourceElementType() &&
|
||||
NewIdxs.size() > *LastIRIndex) {
|
||||
InRangeIndex = LastIRIndex;
|
||||
for (unsigned I = 0; I <= *LastIRIndex; ++I)
|
||||
if (NewIdxs[I] != InnermostGEP->getOperand(I + 1))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a GEP.
|
||||
return ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds,
|
||||
InRangeIndex);
|
||||
InRange);
|
||||
}
|
||||
|
||||
/// Attempt to constant fold an instruction with the
|
||||
@ -1033,8 +1029,7 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
|
||||
return C;
|
||||
|
||||
return ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], Ops.slice(1),
|
||||
GEP->isInBounds(),
|
||||
GEP->getInRangeIndex());
|
||||
GEP->isInBounds(), GEP->getInRange());
|
||||
}
|
||||
|
||||
if (auto *CE = dyn_cast<ConstantExpr>(InstOrCE)) {
|
||||
|
||||
@ -4169,11 +4169,32 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
unsigned Opc = Lex.getUIntVal();
|
||||
SmallVector<Constant*, 16> Elts;
|
||||
bool InBounds = false;
|
||||
bool HasInRange = false;
|
||||
APSInt InRangeStart;
|
||||
APSInt InRangeEnd;
|
||||
Type *Ty;
|
||||
Lex.Lex();
|
||||
|
||||
if (Opc == Instruction::GetElementPtr)
|
||||
if (Opc == Instruction::GetElementPtr) {
|
||||
InBounds = EatIfPresent(lltok::kw_inbounds);
|
||||
if (EatIfPresent(lltok::kw_inrange)) {
|
||||
if (parseToken(lltok::lparen, "expected '('"))
|
||||
return true;
|
||||
if (Lex.getKind() != lltok::APSInt)
|
||||
return tokError("expected integer");
|
||||
InRangeStart = Lex.getAPSIntVal();
|
||||
Lex.Lex();
|
||||
if (parseToken(lltok::comma, "expected ','"))
|
||||
return true;
|
||||
if (Lex.getKind() != lltok::APSInt)
|
||||
return tokError("expected integer");
|
||||
InRangeEnd = Lex.getAPSIntVal();
|
||||
Lex.Lex();
|
||||
if (parseToken(lltok::rparen, "expected ')'"))
|
||||
return true;
|
||||
HasInRange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseToken(lltok::lparen, "expected '(' in constantexpr"))
|
||||
return true;
|
||||
@ -4184,9 +4205,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<unsigned> InRangeOp;
|
||||
if (parseGlobalValueVector(
|
||||
Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) ||
|
||||
if (parseGlobalValueVector(Elts) ||
|
||||
parseToken(lltok::rparen, "expected ')' in constantexpr"))
|
||||
return true;
|
||||
|
||||
@ -4196,6 +4215,17 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
return error(ID.Loc, "base of getelementptr must be a pointer");
|
||||
|
||||
Type *BaseType = Elts[0]->getType();
|
||||
std::optional<ConstantRange> InRange;
|
||||
if (HasInRange) {
|
||||
unsigned IndexWidth =
|
||||
M->getDataLayout().getIndexTypeSizeInBits(BaseType);
|
||||
InRangeStart = InRangeStart.extOrTrunc(IndexWidth);
|
||||
InRangeEnd = InRangeEnd.extOrTrunc(IndexWidth);
|
||||
if (InRangeStart.sge(InRangeEnd))
|
||||
return error(ID.Loc, "expected end to be larger than start");
|
||||
InRange = ConstantRange::getNonEmpty(InRangeStart, InRangeEnd);
|
||||
}
|
||||
|
||||
unsigned GEPWidth =
|
||||
BaseType->isVectorTy()
|
||||
? cast<FixedVectorType>(BaseType)->getNumElements()
|
||||
@ -4225,15 +4255,8 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
|
||||
if (!GetElementPtrInst::getIndexedType(Ty, Indices))
|
||||
return error(ID.Loc, "invalid getelementptr indices");
|
||||
|
||||
if (InRangeOp) {
|
||||
if (*InRangeOp == 0)
|
||||
return error(ID.Loc,
|
||||
"inrange keyword may not appear on pointer operand");
|
||||
--*InRangeOp;
|
||||
}
|
||||
|
||||
ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices,
|
||||
InBounds, InRangeOp);
|
||||
InBounds, InRange);
|
||||
} else if (Opc == Instruction::ShuffleVector) {
|
||||
if (Elts.size() != 3)
|
||||
return error(ID.Loc, "expected three operands to shufflevector");
|
||||
@ -4309,9 +4332,8 @@ bool LLParser::parseOptionalComdat(StringRef GlobalName, Comdat *&C) {
|
||||
|
||||
/// parseGlobalValueVector
|
||||
/// ::= /*empty*/
|
||||
/// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)*
|
||||
bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts,
|
||||
std::optional<unsigned> *InRangeOp) {
|
||||
/// ::= TypeAndValue (',' TypeAndValue)*
|
||||
bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts) {
|
||||
// Empty list.
|
||||
if (Lex.getKind() == lltok::rbrace ||
|
||||
Lex.getKind() == lltok::rsquare ||
|
||||
@ -4320,8 +4342,9 @@ bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts,
|
||||
return false;
|
||||
|
||||
do {
|
||||
if (InRangeOp && !*InRangeOp && EatIfPresent(lltok::kw_inrange))
|
||||
*InRangeOp = Elts.size();
|
||||
// Let the caller deal with inrange.
|
||||
if (Lex.getKind() == lltok::kw_inrange)
|
||||
return false;
|
||||
|
||||
Constant *C;
|
||||
if (parseGlobalTypeAndValue(C))
|
||||
|
||||
@ -520,25 +520,31 @@ public:
|
||||
struct ExtraInfo {
|
||||
uint8_t Opcode;
|
||||
uint8_t Flags;
|
||||
unsigned Extra;
|
||||
Type *SrcElemTy;
|
||||
unsigned BlockAddressBB = 0;
|
||||
Type *SrcElemTy = nullptr;
|
||||
std::optional<ConstantRange> InRange;
|
||||
|
||||
ExtraInfo(uint8_t Opcode, uint8_t Flags = 0, unsigned Extra = 0,
|
||||
Type *SrcElemTy = nullptr)
|
||||
: Opcode(Opcode), Flags(Flags), Extra(Extra), SrcElemTy(SrcElemTy) {}
|
||||
ExtraInfo(uint8_t Opcode, uint8_t Flags = 0, Type *SrcElemTy = nullptr,
|
||||
std::optional<ConstantRange> InRange = std::nullopt)
|
||||
: Opcode(Opcode), Flags(Flags), SrcElemTy(SrcElemTy),
|
||||
InRange(std::move(InRange)) {}
|
||||
|
||||
ExtraInfo(uint8_t Opcode, uint8_t Flags, unsigned BlockAddressBB)
|
||||
: Opcode(Opcode), Flags(Flags), BlockAddressBB(BlockAddressBB) {}
|
||||
};
|
||||
|
||||
uint8_t Opcode;
|
||||
uint8_t Flags;
|
||||
unsigned NumOperands;
|
||||
unsigned Extra; // GEP inrange index or blockaddress BB id.
|
||||
unsigned BlockAddressBB;
|
||||
Type *SrcElemTy; // GEP source element type.
|
||||
std::optional<ConstantRange> InRange; // GEP inrange attribute.
|
||||
|
||||
private:
|
||||
BitcodeConstant(Type *Ty, const ExtraInfo &Info, ArrayRef<unsigned> OpIDs)
|
||||
: Value(Ty, SubclassID), Opcode(Info.Opcode), Flags(Info.Flags),
|
||||
NumOperands(OpIDs.size()), Extra(Info.Extra),
|
||||
SrcElemTy(Info.SrcElemTy) {
|
||||
NumOperands(OpIDs.size()), BlockAddressBB(Info.BlockAddressBB),
|
||||
SrcElemTy(Info.SrcElemTy), InRange(Info.InRange) {
|
||||
std::uninitialized_copy(OpIDs.begin(), OpIDs.end(),
|
||||
getTrailingObjects<unsigned>());
|
||||
}
|
||||
@ -560,11 +566,9 @@ public:
|
||||
return ArrayRef(getTrailingObjects<unsigned>(), NumOperands);
|
||||
}
|
||||
|
||||
std::optional<unsigned> getInRangeIndex() const {
|
||||
std::optional<ConstantRange> getInRange() const {
|
||||
assert(Opcode == Instruction::GetElementPtr);
|
||||
if (Extra == (unsigned)-1)
|
||||
return std::nullopt;
|
||||
return Extra;
|
||||
return InRange;
|
||||
}
|
||||
|
||||
const char *getOpcodeName() const {
|
||||
@ -1559,7 +1563,7 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
|
||||
// If the function is already parsed we can insert the block address
|
||||
// right away.
|
||||
BasicBlock *BB;
|
||||
unsigned BBID = BC->Extra;
|
||||
unsigned BBID = BC->BlockAddressBB;
|
||||
if (!BBID)
|
||||
// Invalid reference to entry block.
|
||||
return error("Invalid ID");
|
||||
@ -1602,7 +1606,7 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
|
||||
case Instruction::GetElementPtr:
|
||||
C = ConstantExpr::getGetElementPtr(BC->SrcElemTy, ConstOps[0],
|
||||
ArrayRef(ConstOps).drop_front(),
|
||||
BC->Flags, BC->getInRangeIndex());
|
||||
BC->Flags, BC->getInRange());
|
||||
break;
|
||||
case Instruction::ExtractElement:
|
||||
C = ConstantExpr::getExtractElement(ConstOps[0], ConstOps[1]);
|
||||
@ -3308,22 +3312,34 @@ Error BitcodeReader::parseConstants() {
|
||||
}
|
||||
case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
|
||||
case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
|
||||
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX: { // [ty, flags, n x
|
||||
// operands]
|
||||
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD: // [ty, flags, n x
|
||||
// operands]
|
||||
case bitc::CST_CODE_CE_GEP_WITH_INRANGE: { // [ty, flags, start, end, n x
|
||||
// operands]
|
||||
if (Record.size() < 2)
|
||||
return error("Constant GEP record must have at least two elements");
|
||||
unsigned OpNum = 0;
|
||||
Type *PointeeType = nullptr;
|
||||
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX ||
|
||||
Record.size() % 2)
|
||||
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD ||
|
||||
BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE || Record.size() % 2)
|
||||
PointeeType = getTypeByID(Record[OpNum++]);
|
||||
|
||||
bool InBounds = false;
|
||||
std::optional<unsigned> InRangeIndex;
|
||||
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX) {
|
||||
std::optional<ConstantRange> InRange;
|
||||
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD) {
|
||||
uint64_t Op = Record[OpNum++];
|
||||
InBounds = Op & 1;
|
||||
InRangeIndex = Op >> 1;
|
||||
unsigned InRangeIndex = Op >> 1;
|
||||
// "Upgrade" inrange by dropping it. The feature is too niche to
|
||||
// bother.
|
||||
(void)InRangeIndex;
|
||||
} else if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE) {
|
||||
uint64_t Op = Record[OpNum++];
|
||||
InBounds = Op & 1;
|
||||
Expected<ConstantRange> MaybeInRange = readConstantRange(Record, OpNum);
|
||||
if (!MaybeInRange)
|
||||
return MaybeInRange.takeError();
|
||||
InRange = MaybeInRange.get();
|
||||
} else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
|
||||
InBounds = true;
|
||||
|
||||
@ -3356,10 +3372,9 @@ Error BitcodeReader::parseConstants() {
|
||||
return error("Missing element type for old-style constant GEP");
|
||||
}
|
||||
|
||||
V = BitcodeConstant::create(Alloc, CurTy,
|
||||
{Instruction::GetElementPtr, InBounds,
|
||||
InRangeIndex.value_or(-1), PointeeType},
|
||||
Elts);
|
||||
V = BitcodeConstant::create(
|
||||
Alloc, CurTy,
|
||||
{Instruction::GetElementPtr, InBounds, PointeeType, InRange}, Elts);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]
|
||||
|
||||
@ -2751,9 +2751,10 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
|
||||
Code = bitc::CST_CODE_CE_GEP;
|
||||
const auto *GO = cast<GEPOperator>(C);
|
||||
Record.push_back(VE.getTypeID(GO->getSourceElementType()));
|
||||
if (std::optional<unsigned> Idx = GO->getInRangeIndex()) {
|
||||
Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX;
|
||||
Record.push_back((*Idx << 1) | GO->isInBounds());
|
||||
if (std::optional<ConstantRange> Range = GO->getInRange()) {
|
||||
Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE;
|
||||
Record.push_back(GO->isInBounds());
|
||||
emitConstantRange(Record, *Range);
|
||||
} else if (GO->isInBounds())
|
||||
Code = bitc::CST_CODE_CE_INBOUNDS_GEP;
|
||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
|
||||
|
||||
@ -1414,6 +1414,10 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
|
||||
} else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
|
||||
if (GEP->isInBounds())
|
||||
Out << " inbounds";
|
||||
if (auto InRange = GEP->getInRange()) {
|
||||
Out << " inrange(" << InRange->getLower() << ", " << InRange->getUpper()
|
||||
<< ")";
|
||||
}
|
||||
} else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(U)) {
|
||||
if (NNI->hasNonNeg())
|
||||
Out << " nneg";
|
||||
@ -1691,18 +1695,13 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
|
||||
Out << ' ' << static_cast<CmpInst::Predicate>(CE->getPredicate());
|
||||
Out << " (";
|
||||
|
||||
std::optional<unsigned> InRangeOp;
|
||||
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) {
|
||||
WriterCtx.TypePrinter->print(GEP->getSourceElementType(), Out);
|
||||
Out << ", ";
|
||||
InRangeOp = GEP->getInRangeIndex();
|
||||
if (InRangeOp)
|
||||
++*InRangeOp;
|
||||
}
|
||||
|
||||
for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) {
|
||||
if (InRangeOp && unsigned(OI - CE->op_begin()) == *InRangeOp)
|
||||
Out << "inrange ";
|
||||
for (User::const_op_iterator OI = CE->op_begin(); OI != CE->op_end();
|
||||
++OI) {
|
||||
WriterCtx.TypePrinter->print((*OI)->getType(), Out);
|
||||
Out << ' ';
|
||||
WriteAsOperandInternal(Out, *OI, WriterCtx);
|
||||
|
||||
@ -1468,6 +1468,10 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds,
|
||||
if (PointeeTy != GEP->getResultElementType())
|
||||
return nullptr;
|
||||
|
||||
// Leave inrange handling to DL-aware constant folding.
|
||||
if (GEP->getInRange())
|
||||
return nullptr;
|
||||
|
||||
Constant *Idx0 = cast<Constant>(Idxs[0]);
|
||||
if (Idx0->isNullValue()) {
|
||||
// Handle the simple case of a zero index.
|
||||
@ -1477,7 +1481,7 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds,
|
||||
NewIndices.append(Idxs.begin() + 1, Idxs.end());
|
||||
return ConstantExpr::getGetElementPtr(
|
||||
GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()),
|
||||
NewIndices, InBounds && GEP->isInBounds(), GEP->getInRangeIndex());
|
||||
NewIndices, InBounds && GEP->isInBounds());
|
||||
}
|
||||
|
||||
gep_type_iterator LastI = gep_type_end(GEP);
|
||||
@ -1526,21 +1530,14 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds,
|
||||
NewIndices.push_back(ConstantExpr::get(Instruction::Add, Idx0, LastIdx));
|
||||
NewIndices.append(Idxs.begin() + 1, Idxs.end());
|
||||
|
||||
// The combined GEP normally inherits its index inrange attribute from
|
||||
// the inner GEP, but if the inner GEP's last index was adjusted by the
|
||||
// outer GEP, any inbounds attribute on that index is invalidated.
|
||||
std::optional<unsigned> IRIndex = GEP->getInRangeIndex();
|
||||
if (IRIndex && *IRIndex == GEP->getNumIndices() - 1)
|
||||
IRIndex = std::nullopt;
|
||||
|
||||
return ConstantExpr::getGetElementPtr(
|
||||
GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()),
|
||||
NewIndices, InBounds && GEP->isInBounds(), IRIndex);
|
||||
NewIndices, InBounds && GEP->isInBounds());
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
bool InBounds,
|
||||
std::optional<unsigned> InRangeIndex,
|
||||
std::optional<ConstantRange> InRange,
|
||||
ArrayRef<Value *> Idxs) {
|
||||
if (Idxs.empty()) return C;
|
||||
|
||||
@ -1556,7 +1553,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
|
||||
auto IsNoOp = [&]() {
|
||||
// Avoid losing inrange information.
|
||||
if (InRangeIndex)
|
||||
if (InRange)
|
||||
return false;
|
||||
|
||||
return all_of(Idxs, [](Value *Idx) {
|
||||
@ -1594,12 +1591,6 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
if (!isa<ConstantInt>(Idxs[i - 1]) && !isa<ConstantDataVector>(Idxs[i - 1]))
|
||||
// Skip if the type of the previous index is not supported.
|
||||
continue;
|
||||
if (InRangeIndex && i == *InRangeIndex + 1) {
|
||||
// If an index is marked inrange, we cannot apply this canonicalization to
|
||||
// the following index, as that will cause the inrange index to point to
|
||||
// the wrong element.
|
||||
continue;
|
||||
}
|
||||
if (isa<StructType>(Ty)) {
|
||||
// The verify makes sure that GEPs into a struct are in range.
|
||||
continue;
|
||||
@ -1621,16 +1612,16 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
}
|
||||
} else {
|
||||
auto *CV = cast<ConstantDataVector>(Idxs[i]);
|
||||
bool InRange = true;
|
||||
bool IsInRange = true;
|
||||
for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) {
|
||||
auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I));
|
||||
InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI);
|
||||
IsInRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI);
|
||||
if (CI->isNegative()) {
|
||||
Unknown = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (InRange || Unknown)
|
||||
if (IsInRange || Unknown)
|
||||
// It's in range, skip to the next index.
|
||||
// It's out of range and negative, don't try to factor it.
|
||||
continue;
|
||||
@ -1720,7 +1711,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
|
||||
if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]);
|
||||
return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds,
|
||||
InRangeIndex);
|
||||
InRange);
|
||||
}
|
||||
|
||||
// If all indices are known integers and normalized, we can do a simple
|
||||
@ -1730,7 +1721,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
|
||||
if (!GV->hasExternalWeakLinkage() && GV->getValueType() == PointeeTy &&
|
||||
isInBoundsIndices(Idxs))
|
||||
return ConstantExpr::getGetElementPtr(PointeeTy, C, Idxs,
|
||||
/*InBounds=*/true, InRangeIndex);
|
||||
/*InBounds=*/true, InRange);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1568,7 +1568,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
|
||||
assert(SrcTy || (Ops[0]->getType() == getOperand(0)->getType()));
|
||||
return ConstantExpr::getGetElementPtr(
|
||||
SrcTy ? SrcTy : GEPO->getSourceElementType(), Ops[0], Ops.slice(1),
|
||||
GEPO->isInBounds(), GEPO->getInRangeIndex(), OnlyIfReducedTy);
|
||||
GEPO->isInBounds(), GEPO->getInRange(), OnlyIfReducedTy);
|
||||
}
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
@ -2349,17 +2349,16 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1,
|
||||
|
||||
Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
|
||||
ArrayRef<Value *> Idxs, bool InBounds,
|
||||
std::optional<unsigned> InRangeIndex,
|
||||
std::optional<ConstantRange> InRange,
|
||||
Type *OnlyIfReducedTy) {
|
||||
assert(Ty && "Must specify element type");
|
||||
assert(isSupportedGetElementPtr(Ty) && "Element type is unsupported!");
|
||||
|
||||
if (Constant *FC =
|
||||
ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs))
|
||||
return FC; // Fold a few common cases.
|
||||
if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, InRange, Idxs))
|
||||
return FC; // Fold a few common cases.
|
||||
|
||||
assert(GetElementPtrInst::getIndexedType(Ty, Idxs) &&
|
||||
"GEP indices invalid!");;
|
||||
assert(GetElementPtrInst::getIndexedType(Ty, Idxs) && "GEP indices invalid!");
|
||||
;
|
||||
|
||||
// Get the result type of the getelementptr!
|
||||
Type *ReqTy = GetElementPtrInst::getGEPReturnType(C, Idxs);
|
||||
@ -2392,10 +2391,9 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
|
||||
}
|
||||
|
||||
unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0;
|
||||
if (InRangeIndex && *InRangeIndex < 63)
|
||||
SubClassOptionalData |= (*InRangeIndex + 1) << 1;
|
||||
const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
|
||||
SubClassOptionalData, std::nullopt, Ty);
|
||||
SubClassOptionalData, std::nullopt, Ty,
|
||||
InRange);
|
||||
|
||||
LLVMContextImpl *pImpl = C->getContext().pImpl;
|
||||
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
|
||||
@ -2691,13 +2689,15 @@ const char *ConstantExpr::getOpcodeName() const {
|
||||
}
|
||||
|
||||
GetElementPtrConstantExpr::GetElementPtrConstantExpr(
|
||||
Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy)
|
||||
Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy,
|
||||
std::optional<ConstantRange> InRange)
|
||||
: ConstantExpr(DestTy, Instruction::GetElementPtr,
|
||||
OperandTraits<GetElementPtrConstantExpr>::op_end(this) -
|
||||
(IdxList.size() + 1),
|
||||
IdxList.size() + 1),
|
||||
SrcElementTy(SrcElementTy),
|
||||
ResElementTy(GetElementPtrInst::getIndexedType(SrcElementTy, IdxList)) {
|
||||
ResElementTy(GetElementPtrInst::getIndexedType(SrcElementTy, IdxList)),
|
||||
InRange(std::move(InRange)) {
|
||||
Op<0>() = C;
|
||||
Use *OperandList = getOperandList();
|
||||
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
|
||||
@ -2712,6 +2712,10 @@ Type *GetElementPtrConstantExpr::getResultElementType() const {
|
||||
return ResElementTy;
|
||||
}
|
||||
|
||||
std::optional<ConstantRange> GetElementPtrConstantExpr::getInRange() const {
|
||||
return InRange;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConstantData* implementations
|
||||
|
||||
|
||||
@ -183,25 +183,29 @@ public:
|
||||
|
||||
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
|
||||
/// used behind the scenes to implement getelementptr constant exprs.
|
||||
class GetElementPtrConstantExpr final : public ConstantExpr {
|
||||
class GetElementPtrConstantExpr : public ConstantExpr {
|
||||
Type *SrcElementTy;
|
||||
Type *ResElementTy;
|
||||
std::optional<ConstantRange> InRange;
|
||||
|
||||
GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
|
||||
ArrayRef<Constant *> IdxList, Type *DestTy);
|
||||
ArrayRef<Constant *> IdxList, Type *DestTy,
|
||||
std::optional<ConstantRange> InRange);
|
||||
|
||||
public:
|
||||
static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
|
||||
ArrayRef<Constant *> IdxList,
|
||||
Type *DestTy, unsigned Flags) {
|
||||
static GetElementPtrConstantExpr *
|
||||
Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList,
|
||||
Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) {
|
||||
GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)
|
||||
GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy);
|
||||
GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy,
|
||||
std::move(InRange));
|
||||
Result->SubclassOptionalData = Flags;
|
||||
return Result;
|
||||
}
|
||||
|
||||
Type *getSourceElementType() const;
|
||||
Type *getResultElementType() const;
|
||||
std::optional<ConstantRange> getInRange() const;
|
||||
|
||||
/// Transparently provide more efficient getOperand methods.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
@ -405,6 +409,7 @@ private:
|
||||
ArrayRef<Constant *> Ops;
|
||||
ArrayRef<int> ShuffleMask;
|
||||
Type *ExplicitTy;
|
||||
std::optional<ConstantRange> InRange;
|
||||
|
||||
static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
|
||||
if (CE->getOpcode() == Instruction::ShuffleVector)
|
||||
@ -418,22 +423,31 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::optional<ConstantRange>
|
||||
getInRangeIfValid(const ConstantExpr *CE) {
|
||||
if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
|
||||
return GEPCE->getInRange();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
public:
|
||||
ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
|
||||
unsigned short SubclassData = 0,
|
||||
unsigned short SubclassOptionalData = 0,
|
||||
ArrayRef<int> ShuffleMask = std::nullopt,
|
||||
Type *ExplicitTy = nullptr)
|
||||
Type *ExplicitTy = nullptr,
|
||||
std::optional<ConstantRange> InRange = std::nullopt)
|
||||
: Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
|
||||
SubclassData(SubclassData), Ops(Ops), ShuffleMask(ShuffleMask),
|
||||
ExplicitTy(ExplicitTy) {}
|
||||
ExplicitTy(ExplicitTy), InRange(std::move(InRange)) {}
|
||||
|
||||
ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
|
||||
: Opcode(CE->getOpcode()),
|
||||
SubclassOptionalData(CE->getRawSubclassOptionalData()),
|
||||
SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands),
|
||||
ShuffleMask(getShuffleMaskIfValid(CE)),
|
||||
ExplicitTy(getSourceElementTypeIfValid(CE)) {}
|
||||
ExplicitTy(getSourceElementTypeIfValid(CE)),
|
||||
InRange(getInRangeIfValid(CE)) {}
|
||||
|
||||
ConstantExprKeyType(const ConstantExpr *CE,
|
||||
SmallVectorImpl<Constant *> &Storage)
|
||||
@ -441,17 +455,26 @@ public:
|
||||
SubclassOptionalData(CE->getRawSubclassOptionalData()),
|
||||
SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
|
||||
ShuffleMask(getShuffleMaskIfValid(CE)),
|
||||
ExplicitTy(getSourceElementTypeIfValid(CE)) {
|
||||
ExplicitTy(getSourceElementTypeIfValid(CE)),
|
||||
InRange(getInRangeIfValid(CE)) {
|
||||
assert(Storage.empty() && "Expected empty storage");
|
||||
for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
|
||||
Storage.push_back(CE->getOperand(I));
|
||||
Ops = Storage;
|
||||
}
|
||||
|
||||
static bool rangesEqual(const std::optional<ConstantRange> &A,
|
||||
const std::optional<ConstantRange> &B) {
|
||||
if (!A.has_value() || !B.has_value())
|
||||
return A.has_value() == B.has_value();
|
||||
return A->getBitWidth() == B->getBitWidth() && A == B;
|
||||
}
|
||||
|
||||
bool operator==(const ConstantExprKeyType &X) const {
|
||||
return Opcode == X.Opcode && SubclassData == X.SubclassData &&
|
||||
SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
|
||||
ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy;
|
||||
ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy &&
|
||||
rangesEqual(InRange, X.InRange);
|
||||
}
|
||||
|
||||
bool operator==(const ConstantExpr *CE) const {
|
||||
@ -470,6 +493,8 @@ public:
|
||||
return false;
|
||||
if (ExplicitTy != getSourceElementTypeIfValid(CE))
|
||||
return false;
|
||||
if (!rangesEqual(InRange, getInRangeIfValid(CE)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -499,8 +524,8 @@ public:
|
||||
case Instruction::ShuffleVector:
|
||||
return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
|
||||
case Instruction::GetElementPtr:
|
||||
return GetElementPtrConstantExpr::Create(ExplicitTy, Ops[0], Ops.slice(1),
|
||||
Ty, SubclassOptionalData);
|
||||
return GetElementPtrConstantExpr::Create(
|
||||
ExplicitTy, Ops[0], Ops.slice(1), Ty, SubclassOptionalData, InRange);
|
||||
case Instruction::ICmp:
|
||||
return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
|
||||
Ops[0], Ops[1]);
|
||||
|
||||
@ -37,7 +37,7 @@ bool Operator::hasPoisonGeneratingFlags() const {
|
||||
case Instruction::GetElementPtr: {
|
||||
auto *GEP = cast<GEPOperator>(this);
|
||||
// Note: inrange exists on constexpr only
|
||||
return GEP->isInBounds() || GEP->getInRangeIndex() != std::nullopt;
|
||||
return GEP->isInBounds() || GEP->getInRange() != std::nullopt;
|
||||
}
|
||||
case Instruction::ZExt:
|
||||
if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this))
|
||||
@ -69,6 +69,12 @@ Type *GEPOperator::getResultElementType() const {
|
||||
return cast<GetElementPtrConstantExpr>(this)->getResultElementType();
|
||||
}
|
||||
|
||||
std::optional<ConstantRange> GEPOperator::getInRange() const {
|
||||
if (auto *CE = dyn_cast<GetElementPtrConstantExpr>(this))
|
||||
return CE->getInRange();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const {
|
||||
/// compute the worse possible offset for every level of the GEP et accumulate
|
||||
/// the minimum alignment into Result.
|
||||
|
||||
@ -801,7 +801,7 @@ Value *FatPtrConstMaterializer::materialize(Value *V) {
|
||||
Ops.push_back(cast<Constant>(U.get()));
|
||||
auto *NewGEP = ConstantExpr::getGetElementPtr(
|
||||
NewSrcTy, Ops[0], ArrayRef<Constant *>(Ops).slice(1),
|
||||
GEPO->isInBounds(), GEPO->getInRangeIndex());
|
||||
GEPO->isInBounds(), GEPO->getInRange());
|
||||
LLVM_DEBUG(dbgs() << "p7-getting GEP: " << *GEPO << " becomes " << *NewGEP
|
||||
<< "\n");
|
||||
Value *FurtherMap = materialize(NewGEP);
|
||||
|
||||
@ -47,28 +47,66 @@ static bool splitGlobal(GlobalVariable &GV) {
|
||||
if (!Init)
|
||||
return false;
|
||||
|
||||
// Verify that each user of the global is an inrange getelementptr constant.
|
||||
// From this it follows that any loads from or stores to that global must use
|
||||
// a pointer derived from an inrange getelementptr constant, which is
|
||||
// sufficient to allow us to apply the splitting transform.
|
||||
const DataLayout &DL = GV.getParent()->getDataLayout();
|
||||
const StructLayout *SL = DL.getStructLayout(Init->getType());
|
||||
ArrayRef<TypeSize> MemberOffsets = SL->getMemberOffsets();
|
||||
unsigned IndexWidth = DL.getIndexTypeSizeInBits(GV.getType());
|
||||
|
||||
// Verify that each user of the global is an inrange getelementptr constant,
|
||||
// and collect information on how it relates to the global.
|
||||
struct GEPInfo {
|
||||
GEPOperator *GEP;
|
||||
unsigned MemberIndex;
|
||||
APInt MemberRelativeOffset;
|
||||
|
||||
GEPInfo(GEPOperator *GEP, unsigned MemberIndex, APInt MemberRelativeOffset)
|
||||
: GEP(GEP), MemberIndex(MemberIndex),
|
||||
MemberRelativeOffset(std::move(MemberRelativeOffset)) {}
|
||||
};
|
||||
SmallVector<GEPInfo> Infos;
|
||||
for (User *U : GV.users()) {
|
||||
if (!isa<Constant>(U))
|
||||
auto *GEP = dyn_cast<GEPOperator>(U);
|
||||
if (!GEP)
|
||||
return false;
|
||||
|
||||
auto *GEP = dyn_cast<GEPOperator>(U);
|
||||
if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 ||
|
||||
!isa<ConstantInt>(GEP->getOperand(1)) ||
|
||||
!cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
|
||||
!isa<ConstantInt>(GEP->getOperand(2)))
|
||||
std::optional<ConstantRange> InRange = GEP->getInRange();
|
||||
if (!InRange)
|
||||
return false;
|
||||
|
||||
APInt Offset(IndexWidth, 0);
|
||||
if (!GEP->accumulateConstantOffset(DL, Offset))
|
||||
return false;
|
||||
|
||||
// Determine source-relative inrange.
|
||||
ConstantRange SrcInRange = InRange->sextOrTrunc(IndexWidth).add(Offset);
|
||||
|
||||
// Check that the GEP offset is in the range (treating upper bound as
|
||||
// inclusive here).
|
||||
if (!SrcInRange.contains(Offset) && SrcInRange.getUpper() != Offset)
|
||||
return false;
|
||||
|
||||
// Find which struct member the range corresponds to.
|
||||
if (SrcInRange.getLower().uge(SL->getSizeInBytes()))
|
||||
return false;
|
||||
|
||||
unsigned MemberIndex =
|
||||
SL->getElementContainingOffset(SrcInRange.getLower().getZExtValue());
|
||||
TypeSize MemberStart = MemberOffsets[MemberIndex];
|
||||
TypeSize MemberEnd = MemberIndex == MemberOffsets.size() - 1
|
||||
? SL->getSizeInBytes()
|
||||
: MemberOffsets[MemberIndex + 1];
|
||||
|
||||
// Verify that the range matches that struct member.
|
||||
if (SrcInRange.getLower() != MemberStart ||
|
||||
SrcInRange.getUpper() != MemberEnd)
|
||||
return false;
|
||||
|
||||
Infos.emplace_back(GEP, MemberIndex, Offset - MemberStart);
|
||||
}
|
||||
|
||||
SmallVector<MDNode *, 2> Types;
|
||||
GV.getMetadata(LLVMContext::MD_type, Types);
|
||||
|
||||
const DataLayout &DL = GV.getParent()->getDataLayout();
|
||||
const StructLayout *SL = DL.getStructLayout(Init->getType());
|
||||
|
||||
IntegerType *Int32Ty = Type::getInt32Ty(GV.getContext());
|
||||
|
||||
std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands());
|
||||
@ -114,21 +152,13 @@ static bool splitGlobal(GlobalVariable &GV) {
|
||||
SplitGV->setVCallVisibilityMetadata(GV.getVCallVisibility());
|
||||
}
|
||||
|
||||
for (User *U : GV.users()) {
|
||||
auto *GEP = cast<GEPOperator>(U);
|
||||
unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue();
|
||||
if (I >= SplitGlobals.size())
|
||||
continue;
|
||||
|
||||
SmallVector<Value *, 4> Ops;
|
||||
Ops.push_back(ConstantInt::get(Int32Ty, 0));
|
||||
for (unsigned I = 3; I != GEP->getNumOperands(); ++I)
|
||||
Ops.push_back(GEP->getOperand(I));
|
||||
|
||||
for (const GEPInfo &Info : Infos) {
|
||||
assert(Info.MemberIndex < SplitGlobals.size() && "Invalid member");
|
||||
auto *NewGEP = ConstantExpr::getGetElementPtr(
|
||||
SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops,
|
||||
GEP->isInBounds());
|
||||
GEP->replaceAllUsesWith(NewGEP);
|
||||
Type::getInt8Ty(GV.getContext()), SplitGlobals[Info.MemberIndex],
|
||||
ConstantInt::get(GV.getContext(), Info.MemberRelativeOffset),
|
||||
Info.GEP->isInBounds());
|
||||
Info.GEP->replaceAllUsesWith(NewGEP);
|
||||
}
|
||||
|
||||
// Finally, remove the original global. Any remaining uses refer to invalid
|
||||
|
||||
@ -426,9 +426,19 @@ int FunctionComparator::cmpConstants(const Constant *L,
|
||||
return Res;
|
||||
if (int Res = cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds()))
|
||||
return Res;
|
||||
if (int Res = cmpNumbers(GEPL->getInRangeIndex().value_or(unsigned(-1)),
|
||||
GEPR->getInRangeIndex().value_or(unsigned(-1))))
|
||||
return Res;
|
||||
|
||||
std::optional<ConstantRange> InRangeL = GEPL->getInRange();
|
||||
std::optional<ConstantRange> InRangeR = GEPR->getInRange();
|
||||
if (InRangeL) {
|
||||
if (!InRangeR)
|
||||
return 1;
|
||||
if (int Res = cmpAPInts(InRangeL->getLower(), InRangeR->getLower()))
|
||||
return Res;
|
||||
if (int Res = cmpAPInts(InRangeL->getUpper(), InRangeR->getUpper()))
|
||||
return Res;
|
||||
} else if (InRangeR) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (auto *OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
|
||||
auto *OBOR = cast<OverflowingBinaryOperator>(RE);
|
||||
|
||||
@ -23,24 +23,26 @@
|
||||
@PR23753_b = global ptr getelementptr (i8, ptr @PR23753_a, i64 ptrtoint (ptr @PR23753_a to i64))
|
||||
; CHECK: @PR23753_b = global ptr getelementptr (i8, ptr @PR23753_a, i64 ptrtoint (ptr @PR23753_a to i64))
|
||||
|
||||
; Verify that inrange on an index inhibits over-indexed getelementptr folding.
|
||||
; Verify that inrange doesn't inhibit over-indexed getelementptr folding,
|
||||
; but does inhibit combining two GEPs where the inner one has inrange (this
|
||||
; will be done when DataLayout is available instead).
|
||||
|
||||
@nestedarray = global [2 x [4 x ptr]] zeroinitializer
|
||||
|
||||
; CHECK: @nestedarray.1 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i64 1, i32 0)
|
||||
@nestedarray.1 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 0, i32 4)
|
||||
; CHECK: @nestedarray.1 = alias ptr, getelementptr inbounds inrange(-32, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i64 1, i32 0)
|
||||
@nestedarray.1 = alias ptr, getelementptr inbounds inrange(-32, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0, i32 4)
|
||||
|
||||
; CHECK: @nestedarray.2 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0, i32 4)
|
||||
@nestedarray.2 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0, i32 4)
|
||||
; CHECK: @nestedarray.2 = alias ptr, getelementptr inbounds inrange(0, 1) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i64 1, i32 0)
|
||||
@nestedarray.2 = alias ptr, getelementptr inbounds inrange(0, 1) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0, i32 4)
|
||||
|
||||
; CHECK: @nestedarray.3 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0)
|
||||
@nestedarray.3 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0), i32 0, i32 0)
|
||||
; CHECK: @nestedarray.3 = alias ptr, getelementptr inbounds inrange(0, 4) ([4 x ptr], ptr @nestedarray, i32 0, i32 0)
|
||||
@nestedarray.3 = alias ptr, getelementptr inbounds inrange(0, 4) ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 0, i32 0)
|
||||
|
||||
; CHECK: @nestedarray.4 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 1, i32 0)
|
||||
@nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0), i32 1, i32 0)
|
||||
; CHECK: @nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 4) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0)
|
||||
@nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 4) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0)
|
||||
|
||||
; CHECK: @nestedarray.5 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 1, i32 0)
|
||||
@nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 0), i32 1, i32 0)
|
||||
; CHECK: @nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0)
|
||||
@nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0)
|
||||
|
||||
; See if i92 indices work too.
|
||||
define ptr @test(ptr %t, i92 %n) {
|
||||
|
||||
46
llvm/test/Assembler/inrange-errors.ll
Normal file
46
llvm/test/Assembler/inrange-errors.ll
Normal file
@ -0,0 +1,46 @@
|
||||
; RUN: split-file %s %t
|
||||
; RUN: not llvm-as < %t/parse-error-1.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-1 %s
|
||||
; RUN: not llvm-as < %t/parse-error-2.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-2 %s
|
||||
; RUN: not llvm-as < %t/parse-error-3.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-3 %s
|
||||
; RUN: not llvm-as < %t/parse-error-4.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-4 %s
|
||||
; RUN: not llvm-as < %t/end-not-larger-start.ll -o /dev/null 2>&1 | FileCheck --check-prefix=END-NOT-LARGER-START %s
|
||||
|
||||
;--- parse-error-1.ll
|
||||
|
||||
; PARSE-ERROR-1: error: expected integer
|
||||
@g = external global i8
|
||||
define ptr @test() {
|
||||
ret ptr getelementptr inrange (i8, ptr @g, i64 8)
|
||||
}
|
||||
|
||||
;--- parse-error-2.ll
|
||||
|
||||
; PARSE-ERROR-2: error: expected ','
|
||||
@g = external global i8
|
||||
define ptr @test() {
|
||||
ret ptr getelementptr inrange(42 (i8, ptr @g, i64 8)
|
||||
}
|
||||
|
||||
;--- parse-error-3.ll
|
||||
|
||||
; PARSE-ERROR-3: error: expected integer
|
||||
@g = external global i8
|
||||
define ptr @test() {
|
||||
ret ptr getelementptr inrange(42, (i8, ptr @g, i64 8)
|
||||
}
|
||||
|
||||
;--- parse-error-4.ll
|
||||
|
||||
; PARSE-ERROR-4: error: expected ')'
|
||||
@g = external global i8
|
||||
define ptr @test() {
|
||||
ret ptr getelementptr inrange(42, 123 (i8, ptr @g, i64 8)
|
||||
}
|
||||
|
||||
;--- end-not-larger-start.ll
|
||||
|
||||
; END-NOT-LARGER-START: error: expected end to be larger than start
|
||||
@g = external global i8
|
||||
define ptr @test() {
|
||||
ret ptr getelementptr inrange(42, 42) (i8, ptr @g, i64 8)
|
||||
}
|
||||
@ -1609,7 +1609,7 @@ declare void @f.writeonly() writeonly
|
||||
;; Constant Expressions
|
||||
|
||||
define i8** @constexpr() {
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2)
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2)
|
||||
ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2)
|
||||
}
|
||||
|
||||
|
||||
@ -1624,7 +1624,7 @@ declare void @f.speculatable() speculatable
|
||||
;; Constant Expressions
|
||||
|
||||
define i8** @constexpr() {
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2)
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2)
|
||||
ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2)
|
||||
}
|
||||
|
||||
|
||||
@ -1634,7 +1634,7 @@ declare void @f.speculatable() speculatable
|
||||
;; Constant Expressions
|
||||
|
||||
define i8** @constexpr() {
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2)
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2)
|
||||
ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2)
|
||||
}
|
||||
|
||||
|
||||
@ -1941,8 +1941,8 @@ declare void @f.speculatable() speculatable
|
||||
;; Constant Expressions
|
||||
|
||||
define ptr @constexpr() {
|
||||
; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2)
|
||||
ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2)
|
||||
; CHECK: ret ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2)
|
||||
ret ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2)
|
||||
}
|
||||
|
||||
define void @instructions.strictfp() strictfp {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
; RUN: opt -O0 -S < %s | FileCheck %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
|
||||
; RUN: opt -O0 -S < %s | FileCheck %s --check-prefix=O0
|
||||
; RUN: opt -O1 -S < %s | FileCheck %s
|
||||
; RUN: opt -O2 -S < %s | FileCheck %s
|
||||
; RUN: opt -O3 -S < %s | FileCheck %s
|
||||
@ -7,12 +8,21 @@
|
||||
|
||||
target datalayout = "e-p:64:64"
|
||||
|
||||
; Make sure that optimizations do not optimize inrange GEP.
|
||||
; Make sure that optimizations do not lose inrange information.
|
||||
|
||||
@vtable = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr null] }
|
||||
|
||||
define void @foo(ptr %p) {
|
||||
;CHECK: store ptr getelementptr {{.*}} ({ [3 x ptr] }, ptr @vtable, i{{.*}} 0, inrange i32 0, i{{.*}} 3), ptr %p
|
||||
store ptr getelementptr ({ [3 x ptr] }, ptr @vtable, i32 0, inrange i32 0, i32 3), ptr %p
|
||||
; O0-LABEL: define void @foo(
|
||||
; O0-SAME: ptr [[P:%.*]]) {
|
||||
; O0-NEXT: store ptr getelementptr inrange(-24, 0) ({ [3 x ptr], [3 x ptr] }, ptr @vtable, i32 0, i32 0, i32 3), ptr [[P]], align 8
|
||||
; O0-NEXT: ret void
|
||||
;
|
||||
; CHECK-LABEL: define void @foo(
|
||||
; CHECK-SAME: ptr nocapture writeonly [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
|
||||
; CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @vtable, i64 1, i32 0, i64 0), ptr [[P]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
store ptr getelementptr inrange(-24, 0) ({ [3 x ptr], [3 x ptr] }, ptr @vtable, i32 0, i32 0, i32 3), ptr %p
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -45,13 +45,13 @@ entry:
|
||||
|
||||
define hidden void @_ZN1AC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @_ZN1BC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -65,13 +65,13 @@ entry:
|
||||
|
||||
define hidden void @_ZN1AC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @_ZN1BC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -45,13 +45,13 @@ entry:
|
||||
|
||||
define hidden void @_ZN1AC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @_ZN1BC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -67,13 +67,13 @@ entry:
|
||||
|
||||
define hidden void @_ZN1AC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
define hidden void @_ZN1BC2Ev(ptr nocapture %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -39,8 +39,8 @@ entry:
|
||||
define dso_local i32 @test_A() {
|
||||
entry:
|
||||
%call = tail call ptr @_Znwm(i64 8)
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %call, align 8
|
||||
%0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %call, align 8
|
||||
%0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9
|
||||
%1 = extractvalue { ptr, i1 } %0, 0, !nosanitize !9
|
||||
%call1 = tail call i32 %1(ptr nonnull %call)
|
||||
ret i32 %call1
|
||||
|
||||
@ -18,7 +18,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
|
||||
|
||||
define internal void @_ZN1AC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ entry:
|
||||
|
||||
define internal void @_ZN1BC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ entry:
|
||||
|
||||
define internal void @_ZN1CC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
|
||||
|
||||
define internal void @_ZN1AC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ entry:
|
||||
|
||||
define internal void @_ZN1BC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ entry:
|
||||
|
||||
define internal void @_ZN1CC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,8 @@ entry:
|
||||
define dso_local i32 @test_A() {
|
||||
entry:
|
||||
%call = tail call ptr @_Znwm(i64 8)
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %call, align 8
|
||||
%0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9
|
||||
store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %call, align 8
|
||||
%0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9
|
||||
%1 = extractvalue { ptr, i1 } %0, 0, !nosanitize !9
|
||||
%call1 = tail call i32 %1(ptr nonnull %call)
|
||||
ret i32 %call1
|
||||
|
||||
@ -16,7 +16,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
|
||||
|
||||
define internal void @_ZN1AC2Ev(ptr %this) {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
target datalayout = "e-p:64:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; CHECK: @vtt = constant [3 x ptr] [ptr @global.0, ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i32 0, i32 1), ptr @global.1]
|
||||
; CHECK: @vtt = constant [3 x ptr] [ptr @global.0, ptr getelementptr inbounds (i8, ptr @global.0, i64 8), ptr @global.1]
|
||||
@vtt = constant [3 x ptr] [
|
||||
ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0),
|
||||
ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 1),
|
||||
ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 1, i32 0)
|
||||
ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0),
|
||||
ptr getelementptr inrange(-8, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 1),
|
||||
ptr getelementptr inrange(0, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 1, i32 0)
|
||||
]
|
||||
|
||||
; CHECK-NOT: @global =
|
||||
@ -22,25 +22,25 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
; CHECK: define ptr @f1()
|
||||
define ptr @f1() {
|
||||
; CHECK-NEXT: ret ptr @global.0
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0)
|
||||
ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0)
|
||||
}
|
||||
|
||||
; CHECK: define ptr @f2()
|
||||
define ptr @f2() {
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i32 0, i32 1)
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 1)
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @global.0, i64 8)
|
||||
ret ptr getelementptr inrange(-8, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 1)
|
||||
}
|
||||
|
||||
; CHECK: define ptr @f3()
|
||||
define ptr @f3() {
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i64 1, i32 0)
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 2)
|
||||
; CHECK-NEXT: ret ptr getelementptr (i8, ptr @global.0, i64 16)
|
||||
ret ptr getelementptr inrange(-16, 0) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 2)
|
||||
}
|
||||
|
||||
; CHECK: define ptr @f4()
|
||||
define ptr @f4() {
|
||||
; CHECK-NEXT: ret ptr @global.1
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 1, i32 0)
|
||||
ret ptr getelementptr inrange(0, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 1, i32 0)
|
||||
}
|
||||
|
||||
define void @foo() {
|
||||
|
||||
@ -10,7 +10,7 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
}
|
||||
|
||||
define ptr @f() {
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0)
|
||||
ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0)
|
||||
}
|
||||
|
||||
define ptr @g() {
|
||||
|
||||
@ -10,7 +10,7 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
}
|
||||
|
||||
define ptr @f() {
|
||||
ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0)
|
||||
ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0)
|
||||
}
|
||||
|
||||
define ptr @g() {
|
||||
|
||||
@ -60,7 +60,7 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
|
||||
define linkonce_odr dso_local void @_ZN4ImplC2Ev(ptr %this) unnamed_addr align 2 {
|
||||
entry:
|
||||
call void @_ZN9InterfaceC2Ev(ptr %this)
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV4Impl, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV4Impl, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
%f = getelementptr inbounds %class.Impl, ptr %this, i64 0, i32 1
|
||||
store i32 3, ptr %f, align 8
|
||||
ret void
|
||||
@ -78,7 +78,7 @@ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
|
||||
|
||||
define linkonce_odr dso_local void @_ZN9InterfaceC2Ev(ptr %this) unnamed_addr align 2 {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV9Interface, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV9Interface, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ entry:
|
||||
|
||||
define linkonce_odr void @_ZN1AC2Ev(ptr %this) align 2 {
|
||||
entry:
|
||||
store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
@ -1093,11 +1093,11 @@ for.body:
|
||||
|
||||
define double @fmul_negated_constant_expression(double %x) {
|
||||
; CHECK-LABEL: @fmul_negated_constant_expression(
|
||||
; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, inrange i32 0, i64 2) to i64) to double)
|
||||
; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 1, i32 0, i64 0) to i64) to double)
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul double [[FSUB]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret double [[R]]
|
||||
;
|
||||
%fsub = fsub double -0.000000e+00, bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, inrange i32 0, i64 2) to i64) to double)
|
||||
%fsub = fsub double -0.000000e+00, bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, i32 0, i64 2) to i64) to double)
|
||||
%r = fmul double %x, %fsub
|
||||
ret double %r
|
||||
}
|
||||
|
||||
@ -11,21 +11,21 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define ptr @f0() {
|
||||
; CHECK-LABEL: @f0(
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds ([3 x ptr], ptr @vt, inrange i64 0, i64 2)
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-16, 8) ([3 x ptr], ptr @vt, i64 0, i64 2)
|
||||
;
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, inrange i64 0, i64 1), i64 1)
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(-8, 16) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1)
|
||||
}
|
||||
|
||||
define ptr @f1() {
|
||||
; CHECK-LABEL: @f1(
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, i64 2)
|
||||
; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-8, 0) ([3 x ptr], ptr @vt, i64 0, i64 2)
|
||||
;
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, inrange i64 1), i64 1)
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1)
|
||||
}
|
||||
|
||||
define ptr @f2() {
|
||||
; CHECK-LABEL: @f2(
|
||||
; CHECK-NEXT: ret ptr getelementptr ([3 x ptr], ptr @vt, i64 1, i64 1)
|
||||
; CHECK-NEXT: ret ptr getelementptr inrange(-24, -16) ([3 x ptr], ptr @vt, i64 1, i64 1)
|
||||
;
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, inrange i64 1), i64 3)
|
||||
ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 3)
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ entry:
|
||||
define hidden noalias nonnull ptr @_Z6make_dv() {
|
||||
entry:
|
||||
%call = tail call ptr @_Znwm(i64 8) #3
|
||||
store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_11DE, i64 0, inrange i32 0, i64 2), ptr %call, align 8
|
||||
store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_11DE, i64 0, i32 0, i64 2), ptr %call, align 8
|
||||
ret ptr %call
|
||||
}
|
||||
|
||||
|
||||
@ -66,9 +66,9 @@ define i64 @f8() unnamed_addr {
|
||||
|
||||
define ptr @f10() unnamed_addr {
|
||||
; CHECK-LABEL: define ptr @f10() unnamed_addr {
|
||||
; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1)
|
||||
; CHECK-NEXT: ret ptr getelementptr inrange(0, 4) ([4 x i32], ptr @g1, i64 0, i64 1)
|
||||
;
|
||||
ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1)
|
||||
ret ptr getelementptr inrange(0, 4) ([4 x i32], ptr @g1, i64 0, i64 1)
|
||||
}
|
||||
|
||||
define ptr @f11() unnamed_addr {
|
||||
@ -80,7 +80,7 @@ define ptr @f11() unnamed_addr {
|
||||
|
||||
define ptr @f12() unnamed_addr {
|
||||
; CHECK-LABEL: define ptr @f12() unnamed_addr {
|
||||
; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1)
|
||||
; CHECK-NEXT: ret ptr getelementptr inrange(-4, 12) ([4 x i32], ptr @g1, i64 0, i64 1)
|
||||
;
|
||||
ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1)
|
||||
ret ptr getelementptr inrange(-4, 12) ([4 x i32], ptr @g1, i64 0, i64 1)
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; M0: @global = local_unnamed_addr global
|
||||
; M1-NOT: @global
|
||||
@global = local_unnamed_addr global %struct.hoge { %struct.widget { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global.1, i32 0, inrange i32 0, i32 2) } }, align 8
|
||||
@global = local_unnamed_addr global %struct.hoge { %struct.widget { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @global.1, i32 0, i32 0, i32 2) } }, align 8
|
||||
|
||||
; M0: @global.1 = external unnamed_addr constant
|
||||
; M1: @global.1 = linkonce_odr unnamed_addr constant
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user