Skip to content

Commit 44df982

Browse files
[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
1 parent 45066c2 commit 44df982

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
737737
LoadInst *NewLoad = IC.combineLoadToNewType(LI, ST->getTypeAtIndex(0U),
738738
".unpack");
739739
NewLoad->setAAMetadata(LI.getAAMetadata());
740+
// Copy invariant metadata from parent load.
741+
NewLoad->copyMetadata(LI, LLVMContext::MD_invariant_load);
740742
return IC.replaceInstUsesWith(LI, IC.Builder.CreateInsertValue(
741743
PoisonValue::get(T), NewLoad, 0, Name));
742744
}
@@ -764,6 +766,8 @@ static Instruction *unpackLoadToAggregate(InstCombinerImpl &IC, LoadInst &LI) {
764766
Name + ".unpack");
765767
// Propagate AA metadata. It'll still be valid on the narrowed load.
766768
L->setAAMetadata(LI.getAAMetadata());
769+
// Copy invariant metadata from parent load.
770+
L->copyMetadata(LI, LLVMContext::MD_invariant_load);
767771
V = IC.Builder.CreateInsertValue(V, L, i);
768772
}
769773

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S < %s -passes=instcombine | FileCheck %s
3+
4+
%struct.double2 = type { double, double }
5+
%struct.double1 = type { double }
6+
7+
define %struct.double2 @func1(ptr addrspace(1) %a) {
8+
; CHECK-LABEL: define %struct.double2 @func1(
9+
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
10+
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr addrspace(1) [[A]], align 16, !invariant.load [[META0:![0-9]+]]
11+
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE2:%.*]] poison, double [[DOTUNPACK]], 0
12+
; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[A]], i64 8
13+
; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load double, ptr addrspace(1) [[DOTELT1]], align 8, !invariant.load [[META0]]
14+
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[STRUCT_DOUBLE2]] [[TMP1]], double [[DOTUNPACK2]], 1
15+
; CHECK-NEXT: ret [[STRUCT_DOUBLE2]] [[TMP2]]
16+
;
17+
%1 = load %struct.double2, ptr addrspace(1) %a, align 16, !invariant.load !1
18+
ret %struct.double2 %1
19+
}
20+
21+
define %struct.double2 @func2(ptr %a) {
22+
; CHECK-LABEL: define %struct.double2 @func2(
23+
; CHECK-SAME: ptr [[A:%.*]]) {
24+
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr [[A]], align 16, !invariant.load [[META0]]
25+
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE2:%.*]] poison, double [[DOTUNPACK]], 0
26+
; CHECK-NEXT: [[DOTELT1:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i64 8
27+
; CHECK-NEXT: [[DOTUNPACK2:%.*]] = load double, ptr [[DOTELT1]], align 8, !invariant.load [[META0]]
28+
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[STRUCT_DOUBLE2]] [[TMP1]], double [[DOTUNPACK2]], 1
29+
; CHECK-NEXT: ret [[STRUCT_DOUBLE2]] [[TMP2]]
30+
;
31+
%1 = load %struct.double2, ptr %a, align 16, !invariant.load !1
32+
ret %struct.double2 %1
33+
}
34+
35+
define %struct.double1 @func3(ptr %a) {
36+
; CHECK-LABEL: define %struct.double1 @func3(
37+
; CHECK-SAME: ptr [[A:%.*]]) {
38+
; CHECK-NEXT: [[DOTUNPACK:%.*]] = load double, ptr [[A]], align 16, !invariant.load [[META0]]
39+
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue [[STRUCT_DOUBLE1:%.*]] poison, double [[DOTUNPACK]], 0
40+
; CHECK-NEXT: ret [[STRUCT_DOUBLE1]] [[TMP1]]
41+
;
42+
%1 = load %struct.double1, ptr %a, align 16, !invariant.load !1
43+
ret %struct.double1 %1
44+
}
45+
46+
!1 = !{}

0 commit comments

Comments
 (0)