CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
211 lines
7.4 KiB
LLVM
211 lines
7.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
; Test merging GEP of GEP with constant indices.
|
|
|
|
target datalayout = "i24:8:8"
|
|
|
|
%struct.A = type { [123 x i8], i32 }
|
|
%struct.B = type { i8, [3 x i16], %struct.A, float }
|
|
%struct.C = type { i8, i32, i32 }
|
|
|
|
; result = (ptr) p + 3
|
|
define ptr @mergeBasic(ptr %p) {
|
|
; CHECK-LABEL: @mergeBasic(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 12
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i32, ptr %p, i64 1
|
|
%2 = getelementptr inbounds i32, ptr %1, i64 2
|
|
ret ptr %2
|
|
}
|
|
|
|
; Converted to ptr and merged.
|
|
; result = (ptr) p + 10
|
|
define ptr @mergeDifferentTypes(ptr %p) {
|
|
; CHECK-LABEL: @mergeDifferentTypes(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 10
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i8, ptr %p, i64 2
|
|
%2 = getelementptr inbounds i64, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; Converted to ptr and merged.
|
|
; result = (ptr) p + 10
|
|
define ptr @mergeReverse(ptr %p) {
|
|
; CHECK-LABEL: @mergeReverse(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 10
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i64, ptr %p, i64 1
|
|
%2 = getelementptr inbounds i8, ptr %1, i64 2
|
|
ret ptr %2
|
|
}
|
|
|
|
; Offsets of first and last GEP cancel out.
|
|
; result = p
|
|
define ptr @zeroSum(ptr %p) {
|
|
; CHECK-LABEL: @zeroSum(
|
|
; CHECK-NEXT: ret ptr [[P:%.*]]
|
|
;
|
|
%1 = getelementptr inbounds i32, ptr %p, i64 1
|
|
%2 = getelementptr inbounds i8, ptr %1, i64 -4
|
|
ret ptr %2
|
|
}
|
|
|
|
; result = (ptr) ((ptr) p + 1) + 17
|
|
define ptr @array1(ptr %p) {
|
|
; CHECK-LABEL: @array1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 37
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds [20 x i8], ptr %p, i64 1, i64 1
|
|
%2 = getelementptr inbounds i64, ptr %1, i64 2
|
|
ret ptr %2
|
|
}
|
|
|
|
; Converted to ptr and merged.
|
|
; result = (ptr) p + 20
|
|
define ptr @array2(ptr %p) {
|
|
; CHECK-LABEL: @array2(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 20
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i64, ptr %p, i64 2
|
|
%2 = getelementptr inbounds [3 x i8], ptr %1, i64 1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; Converted to ptr and merged.
|
|
; result = (ptr) p + 36
|
|
define ptr @struct1(ptr %p) {
|
|
; CHECK-LABEL: @struct1(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 36
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i64, ptr %p, i64 3
|
|
%2 = getelementptr inbounds %struct.C, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; result = &((struct.A*) p - 1).member1
|
|
define ptr @struct2(ptr %p) {
|
|
; CHECK-LABEL: @struct2(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 -4
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.A, ptr %p, i64 0, i32 1
|
|
%2 = getelementptr inbounds i8, ptr %1, i64 -128
|
|
ret ptr %2
|
|
}
|
|
|
|
; result = (ptr) &((struct.B) p)[0].member2.member0 + 7
|
|
define ptr @structStruct(ptr %p) {
|
|
; CHECK-LABEL: @structStruct(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 15
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.B, ptr %p, i64 0, i32 2, i32 0, i64 3
|
|
%2 = getelementptr inbounds %struct.A, ptr %1, i64 0, i32 0, i64 4
|
|
ret ptr %2
|
|
}
|
|
|
|
; First GEP offset is not divisible by last GEP's source element size, but first
|
|
; GEP points to an array such that the last GEP offset is divisible by the
|
|
; array's element size, so the first GEP can be rewritten with an extra index.
|
|
; result = (ptr) &((struct.B*) p)[i].member1 + 2
|
|
define ptr @appendIndex(ptr %p, i64 %i) {
|
|
; CHECK-LABEL: @appendIndex(
|
|
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [140 x i8], ptr [[P:%.*]], i64 [[I:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 6
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.B, ptr %p, i64 %i, i32 1
|
|
%2 = getelementptr inbounds i32, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; Offset of either GEP is not divisible by the other's size, converted to ptr
|
|
; and merged.
|
|
; Here i24 is 8-bit aligned.
|
|
; result = (ptr) p + 7
|
|
define ptr @notDivisible(ptr %p) {
|
|
; CHECK-LABEL: @notDivisible(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 7
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds i24, ptr %p, i64 1
|
|
%2 = getelementptr inbounds i32, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
define ptr @partialConstant2(ptr %p, i64 %a) {
|
|
; CHECK-LABEL: @partialConstant2(
|
|
; CHECK-NEXT: [[DOTIDX:%.*]] = shl nsw i64 [[A:%.*]], 5
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 20
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[TMP1]], i64 [[DOTIDX]]
|
|
; CHECK-NEXT: ret ptr [[TMP2]]
|
|
;
|
|
%1 = getelementptr inbounds i32, ptr %p, i64 1
|
|
%2 = getelementptr inbounds [4 x i64], ptr %1, i64 %a, i64 2
|
|
ret ptr %2
|
|
}
|
|
|
|
define ptr @partialConstant3(ptr %p) {
|
|
; CHECK-LABEL: @partialConstant3(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[P:%.*]], i64 4
|
|
; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
|
|
; CHECK-NEXT: [[DOTIDX:%.*]] = shl nsw i64 [[TMP2]], 5
|
|
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[TMP1]], i64 [[DOTIDX]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP4]], i64 16
|
|
; CHECK-NEXT: ret ptr [[TMP3]]
|
|
;
|
|
%1 = getelementptr inbounds i32, ptr %p, i64 1
|
|
%2 = ptrtoint ptr %1 to i64
|
|
%3 = getelementptr inbounds [4 x i64], ptr %1, i64 %2, i64 2
|
|
ret ptr %3
|
|
}
|
|
|
|
; Two GEP instructions can be merged if one is constant-indexed and the other
|
|
; is an aggregate type with a constant last index, and the resulting pointer
|
|
; address by adding the constant offset aliases the address of another member.
|
|
; result = &((struct.C*) p + a).member2
|
|
define ptr @partialConstantMemberAliasing1(ptr %p, i64 %a) {
|
|
; CHECK-LABEL: @partialConstantMemberAliasing1(
|
|
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [12 x i8], ptr [[P:%.*]], i64 [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 8
|
|
; CHECK-NEXT: ret ptr [[TMP1]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
|
|
%2 = getelementptr inbounds i32, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; Negative test. Similar to above, but the new address does not alias the
|
|
; address of another member.
|
|
define ptr @partialConstantMemberAliasing2(ptr %p, i64 %a) {
|
|
; CHECK-LABEL: @partialConstantMemberAliasing2(
|
|
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [12 x i8], ptr [[P:%.*]], i64 [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 5
|
|
; CHECK-NEXT: ret ptr [[TMP2]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
|
|
%2 = getelementptr inbounds i8, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|
|
|
|
; Negative test. Similar to above, but the new address falls outside the address
|
|
; range of the object currently pointed by the non-constant GEP.
|
|
define ptr @partialConstantMemberAliasing3(ptr %p, i64 %a) {
|
|
; CHECK-LABEL: @partialConstantMemberAliasing3(
|
|
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [12 x i8], ptr [[P:%.*]], i64 [[A:%.*]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 12
|
|
; CHECK-NEXT: ret ptr [[TMP2]]
|
|
;
|
|
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 2
|
|
%2 = getelementptr inbounds i32, ptr %1, i64 1
|
|
ret ptr %2
|
|
}
|