Use Value::getPointerDereferenceableBytes() instead of hardcoding dereferenceable only for allocas. Allows us to infer inbounds GEPs for other Values like CallInsts and Arguments.
Fixed clang test broken in initial land.
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D153815
// CHECK-LABEL: @test_get_workgroup_size(
// CHECK: call align 4 dereferenceable(64) ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 4
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 4
// CHECK: load i16, ptr addrspace(4) %{{.*}}, align 4, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 6
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 6
// CHECK: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 8
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 8
// CHECK: load i16, ptr addrspace(4) %{{.*}}, align 4, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
void test_get_workgroup_size(int d, global int *out)
{
// CHECK-LABEL: @test_get_grid_size(
// CHECK: call align 4 dereferenceable(64) ptr addrspace(4) @llvm.amdgcn.dispatch.ptr()
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 12
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 12
// CHECK: load i32, ptr addrspace(4) %{{.*}}, align 4, !invariant.load
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 16
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 16
// CHECK: load i32, ptr addrspace(4) %{{.*}}, align 4, !invariant.load
-// CHECK: getelementptr i8, ptr addrspace(4) %{{.*}}, i64 20
+// CHECK: getelementptr inbounds i8, ptr addrspace(4) %{{.*}}, i64 20
// CHECK: load i32, ptr addrspace(4) %{{.*}}, align 4, !invariant.load
void test_get_grid_size(int d, global int *out)
{
Value *UnderlyingPtrOp =
PtrOp->stripAndAccumulateInBoundsConstantOffsets(DL,
BasePtrOffset);
- if (auto *AI = dyn_cast<AllocaInst>(UnderlyingPtrOp)) {
+ bool CanBeNull, CanBeFreed;
+ uint64_t DerefBytes = UnderlyingPtrOp->getPointerDereferenceableBytes(
+ DL, CanBeNull, CanBeFreed);
+ if (!CanBeNull && !CanBeFreed && DerefBytes != 0) {
if (GEP.accumulateConstantOffset(DL, BasePtrOffset) &&
BasePtrOffset.isNonNegative()) {
- APInt AllocSize(
- IdxWidth,
- DL.getTypeAllocSize(AI->getAllocatedType()).getKnownMinValue());
+ APInt AllocSize(IdxWidth, DerefBytes);
if (BasePtrOffset.ule(AllocSize)) {
return GetElementPtrInst::CreateInBounds(
GEP.getSourceElementType(), PtrOp, Indices, GEP.getName());
; CHECK-LABEL: @two_nonnull_mallocs_hidden(
; CHECK-NEXT: [[M:%.*]] = call nonnull dereferenceable(4) ptr @malloc(i64 4)
; CHECK-NEXT: [[N:%.*]] = call nonnull dereferenceable(4) ptr @malloc(i64 4)
-; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[M]], i64 1
-; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[N]], i64 2
+; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[M]], i64 1
+; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[N]], i64 2
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP1]], [[GEP2]]
; CHECK-NEXT: ret i1 [[CMP]]
;
define void @call2() {
; CHECK-LABEL: define void @call2() {
; CHECK-NEXT: [[A:%.*]] = call dereferenceable(8) ptr @g()
-; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 4
-; CHECK-NEXT: call void @use(ptr [[B]])
+; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 4
+; CHECK-NEXT: call void @use(ptr nonnull [[B]])
; CHECK-NEXT: ret void
;
%a = call dereferenceable(8) ptr @g()
define void @arg2(ptr dereferenceable(8) %a) {
; CHECK-LABEL: define void @arg2
; CHECK-SAME: (ptr dereferenceable(8) [[A:%.*]]) {
-; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A]], i64 4
-; CHECK-NEXT: call void @use(ptr [[B]])
+; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 4
+; CHECK-NEXT: call void @use(ptr nonnull [[B]])
; CHECK-NEXT: ret void
;
%b = getelementptr i8, ptr %a, i64 4
; SSE-LABEL: @ConvertVectors_ByVal(
; SSE-NEXT: entry:
; SSE-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[V:%.*]], align 16
-; SSE-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[V]], i64 8
+; SSE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[V]], i64 8
; SSE-NEXT: [[V_VAL421:%.*]] = load i64, ptr [[TMP1]], align 8
; SSE-NEXT: [[TMP2:%.*]] = trunc i64 [[V_VAL421]] to i32
; SSE-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; AVX-LABEL: @ConvertVectors_ByVal(
; AVX-NEXT: entry:
; AVX-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[V:%.*]], align 16
-; AVX-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[V]], i64 8
+; AVX-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[V]], i64 8
; AVX-NEXT: [[V_VAL421:%.*]] = load i64, ptr [[TMP1]], align 8
; AVX-NEXT: [[TMP2:%.*]] = trunc i64 [[V_VAL421]] to i32
; AVX-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float
; CHECK-LABEL: define nonnull ptr @parent
; CHECK-SAME: (ptr readonly returned align 8 dereferenceable(72) [[F:%.*]], half [[VAL1:%.*]], i16 [[VAL2:%.*]], i32 [[VAL3:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[F]], i64 64
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[F]], i64 64
; CHECK-NEXT: [[F_VAL:%.*]] = load ptr, ptr [[TMP0]], align 8
; CHECK-NEXT: [[CMP_NOT_NOT_I:%.*]] = icmp eq i32 [[VAL3]], 0
; CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[VAL1]] to i16
; CHECK-LABEL: define nonnull ptr @parent
; CHECK-SAME: (ptr readonly returned align 8 dereferenceable(72) [[F:%.*]], i16 [[VAL1:%.*]], i16 [[VAL2:%.*]], i32 [[VAL3:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] align 2 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[F]], i64 64
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[F]], i64 64
; CHECK-NEXT: [[F_VAL:%.*]] = load ptr, ptr [[TMP0]], align 8
; CHECK-NEXT: [[CMP_NOT_NOT_I:%.*]] = icmp eq i32 [[VAL3]], 0
; CHECK-NEXT: [[SPEC_SELECT_I:%.*]] = select i1 [[CMP_NOT_NOT_I]], i16 [[VAL1]], i16 [[VAL2]]