llvm-project/llvm/test/Transforms/InstCombine/invariant-metadata-propagation.ll
Vedant Paranjape 44df9826f3
[InstCombine] Propagate invariant.load metadata across unpacked loads (#152186)
For loads that operate on aggregate type, instcombine unpacks the loads.
It does not preserve the invariant.load metadata. This patch fixes that,
it looks for the metadata in the parent load and attaches the metadata
to the unpacked loads.

```
%struct.double2 = type { double, double }
%struct.double1 = type { double }

define %struct.double2 @func1(ptr %a) {
  %1 = load %struct.double2, ptr %a, align 16, !invariant.load !1
  ret %struct.double2 %1
}

!1 = !{}
```
Reproducer: https://godbolt.org/z/hcY8MMvYh
2025-08-14 10:08:26 -07:00

47 lines
2.2 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S < %s -passes=instcombine | FileCheck %s
%struct.double2 = type { double, double }
%struct.double1 = type { double }
define %struct.double2 @func1(ptr addrspace(1) %a) {
; CHECK-LABEL: define %struct.double2 @func1(
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr addrspace(1) [[A]], align 16, !invariant.load [[META0:![0-9]+]]
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE2:%.*]] poison, double [[DOTUNPACK]], 0
; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[A]], i64 8
; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load double, ptr addrspace(1) [[DOTELT1]], align 8, !invariant.load [[META0]]
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[STRUCT_DOUBLE2]] [[TMP1]], double [[DOTUNPACK2]], 1
; CHECK-NEXT: ret [[STRUCT_DOUBLE2]] [[TMP2]]
;
%1 = load %struct.double2, ptr addrspace(1) %a, align 16, !invariant.load !1
ret %struct.double2 %1
}
define %struct.double2 @func2(ptr %a) {
; CHECK-LABEL: define %struct.double2 @func2(
; CHECK-SAME: ptr [[A:%.*]]) {
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr [[A]], align 16, !invariant.load [[META0]]
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE2:%.*]] poison, double [[DOTUNPACK]], 0
; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8
; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load double, ptr [[DOTELT1]], align 8, !invariant.load [[META0]]
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[STRUCT_DOUBLE2]] [[TMP1]], double [[DOTUNPACK2]], 1
; CHECK-NEXT: ret [[STRUCT_DOUBLE2]] [[TMP2]]
;
%1 = load %struct.double2, ptr %a, align 16, !invariant.load !1
ret %struct.double2 %1
}
define %struct.double1 @func3(ptr %a) {
; CHECK-LABEL: define %struct.double1 @func3(
; CHECK-SAME: ptr [[A:%.*]]) {
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr [[A]], align 16, !invariant.load [[META0]]
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE1:%.*]] poison, double [[DOTUNPACK]], 0
; CHECK-NEXT: ret [[STRUCT_DOUBLE1]] [[TMP1]]
;
%1 = load %struct.double1, ptr %a, align 16, !invariant.load !1
ret %struct.double1 %1
}
!1 = !{}