Skip to content

Commit f32f048

Browse files
authored
[llvm] Use ABI instead of preferred alignment for const prop checks (#142500)
We'd hit an assertion checking proper alignment for an i8 when building chromium because we used the prefered alignment (which is 4 bytes) instead of the ABI alignment (which is 1 byte). The ABI alignment should be used because that's the actual alignment needed to load a constant from the vtable. This also updates the two `virtual-const-prop-small-alignment-*` to explicitly give ABI alignments for i64s.
1 parent db54719 commit f32f048

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,7 @@ bool DevirtModule::tryVirtualConstProp(
18451845
if (BitWidth > 64)
18461846
return false;
18471847

1848-
Align TypeAlignment = M.getDataLayout().getPrefTypeAlign(RetType);
1848+
Align TypeAlignment = M.getDataLayout().getABIIntegerTypeAlignment(BitWidth);
18491849

18501850
// Make sure that each function is defined, does not access memory, takes at
18511851
// least one argument, does not use its first argument (which we assume is
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
;; Demonstrate that the ABI alignment is used over the preferred alignment.
2+
;;
3+
;; In both runs, pointers are 32-bit but we can only store the function returing
4+
;; the 64-bit constant in the vtable if the ABI alignment for an i64 is 32 since
5+
;; we cannot guarantee a 64-bit ABI alignment if the vtable is 32-bit aligned.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:32:64" %s | FileCheck %s --check-prefixes=COMMON,ABI32
7+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s --check-prefixes=COMMON,ABI64
8+
9+
; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] }
10+
; ABI32-SAME: [8 x i8] c"\05\00\00\00\00\00\00\00"
11+
; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] }
12+
; ABI64-SAME: zeroinitializer
13+
; COMMON-SAME: }, !type [[T:![0-9]+]]
14+
@vt6 = constant [2 x ptr] [
15+
ptr @vf10i8,
16+
ptr @vf5i64
17+
], !type !1
18+
19+
; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] }
20+
; ABI32-SAME: [8 x i8] c"\06\00\00\00\00\00\00\00"
21+
; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] }
22+
; ABI64-SAME: zeroinitializer
23+
; COMMON-SAME: }, !type [[T]]
24+
@vt7 = constant [2 x ptr] [
25+
ptr @vf9i8,
26+
ptr @vf6i64
27+
], !type !1
28+
29+
define i1 @vf0i1(ptr %this) readnone {
30+
ret i1 0
31+
}
32+
33+
define i1 @vf1i1(ptr %this) readnone {
34+
ret i1 1
35+
}
36+
37+
define i8 @vf0i8(ptr %this) readnone {
38+
ret i8 2
39+
}
40+
41+
define i8 @vf1i8(ptr %this) readnone {
42+
ret i8 3
43+
}
44+
45+
define i32 @vf1i32(ptr %this) readnone {
46+
ret i32 1
47+
}
48+
49+
define i32 @vf2i32(ptr %this) readnone {
50+
ret i32 2
51+
}
52+
53+
define i32 @vf3i32(ptr %this) readnone {
54+
ret i32 3
55+
}
56+
57+
define i32 @vf4i32(ptr %this) readnone {
58+
ret i32 4
59+
}
60+
61+
define i64 @vf5i64(ptr %this) readnone {
62+
ret i64 5
63+
}
64+
65+
define i64 @vf6i64(ptr %this) readnone {
66+
ret i64 6
67+
}
68+
69+
define i8 @vf9i8(ptr %this) readnone {
70+
ret i8 10
71+
}
72+
73+
define i8 @vf10i8(ptr %this) readnone {
74+
ret i8 11
75+
}
76+
77+
; COMMON-LABEL: define i8 @call0(
78+
define i8 @call0(ptr %obj) {
79+
%vtable = load ptr, ptr %obj
80+
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid")
81+
call void @llvm.assume(i1 %p)
82+
%fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 0
83+
%fptr = load ptr, ptr %fptrptr
84+
%result = call i8 %fptr(ptr %obj)
85+
ret i8 %result
86+
; COMMON: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -1
87+
; COMMON: [[VTLOAD:%[^ ]*]] = load i8, ptr [[VTGEP]]
88+
; COMMON: ret i8 [[VTLOAD]]
89+
}
90+
91+
; COMMON-LABEL: define i64 @call1(
92+
define i64 @call1(ptr %obj) {
93+
%vtable = load ptr, ptr %obj
94+
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid")
95+
call void @llvm.assume(i1 %p)
96+
%fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1
97+
%fptr = load ptr, ptr %fptrptr
98+
%result = call i64 %fptr(ptr %obj)
99+
ret i64 %result
100+
; ABI32: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 8
101+
; ABI32-NEXT: [[VTLOAD:%[^ ]*]] = load i64, ptr [[VTGEP]]
102+
; ABI64: [[VTGEP:%[^ ]*]] = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1
103+
; ABI64-NEXT: [[FUNC:%[^ ]*]] = load ptr, ptr [[VTGEP]], align 4
104+
; ABI64-NEXT: [[VTLOAD:%[^ ]*]] = call i64 [[FUNC]](ptr %obj)
105+
; COMMON-NEXT: ret i64 [[VTLOAD]]
106+
}
107+
108+
; COMMON: [[T]] = !{i32 4, !"typeid"}
109+
110+
!1 = !{i32 0, !"typeid"}

llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
2-
31
;; This target uses 32-bit sized and aligned pointers.
4-
target datalayout = "e-p:32:32"
2+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s
3+
4+
;; The tests should be the exact same even with different preferred alignments since
5+
;; the ABI alignment is used.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:128" %s | FileCheck %s
57

68
;; Constant propagation should be agnostic towards sections.
79
;; Also the new global should be in the original vtable's section.

llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s
2-
31
;; This target uses 64-bit sized and aligned pointers.
4-
target datalayout = "e-p:64:64"
2+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:64" %s | FileCheck %s
3+
4+
;; The tests should be the exact same even with different preferred alignments since
5+
;; the ABI alignment is used.
6+
; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:128" %s | FileCheck %s
57

68
;; Constant propagation should be agnostic towards sections.
79
;; Also the new global should be in the original vtable's section.

0 commit comments

Comments
 (0)