diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 3a25255d0a4c8..a7d9f3ba24b24 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -1845,7 +1845,7 @@ bool DevirtModule::tryVirtualConstProp( if (BitWidth > 64) return false; - Align TypeAlignment = M.getDataLayout().getPrefTypeAlign(RetType); + Align TypeAlignment = M.getDataLayout().getABIIntegerTypeAlignment(BitWidth); // Make sure that each function is defined, does not access memory, takes at // least one argument, does not use its first argument (which we assume is diff --git a/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-ignore-preferred-alignment.ll b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-ignore-preferred-alignment.ll new file mode 100644 index 0000000000000..6bee92301e330 --- /dev/null +++ b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-ignore-preferred-alignment.ll @@ -0,0 +1,110 @@ +;; Demonstrate that the ABI alignment is used over the preferred alignment. +;; +;; In both runs, pointers are 32-bit but we can only store the function returing +;; the 64-bit constant in the vtable if the ABI alignment for an i64 is 32 since +;; we cannot guarantee a 64-bit ABI alignment if the vtable is 32-bit aligned. +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:32:64" %s | FileCheck %s --check-prefixes=COMMON,ABI32 +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s --check-prefixes=COMMON,ABI64 + +; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] } +; ABI32-SAME: [8 x i8] c"\05\00\00\00\00\00\00\00" +; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] } +; ABI64-SAME: zeroinitializer +; COMMON-SAME: }, !type [[T:![0-9]+]] +@vt6 = constant [2 x ptr] [ +ptr @vf10i8, +ptr @vf5i64 +], !type !1 + +; ABI32: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [8 x i8] } +; ABI32-SAME: [8 x i8] c"\06\00\00\00\00\00\00\00" +; ABI64: [[VT6DATA:@[^ ]*]] = {{.*}} { [4 x i8], [2 x ptr], [0 x i8] } +; ABI64-SAME: zeroinitializer +; COMMON-SAME: }, !type [[T]] +@vt7 = constant [2 x ptr] [ +ptr @vf9i8, +ptr @vf6i64 +], !type !1 + +define i1 @vf0i1(ptr %this) readnone { + ret i1 0 +} + +define i1 @vf1i1(ptr %this) readnone { + ret i1 1 +} + +define i8 @vf0i8(ptr %this) readnone { + ret i8 2 +} + +define i8 @vf1i8(ptr %this) readnone { + ret i8 3 +} + +define i32 @vf1i32(ptr %this) readnone { + ret i32 1 +} + +define i32 @vf2i32(ptr %this) readnone { + ret i32 2 +} + +define i32 @vf3i32(ptr %this) readnone { + ret i32 3 +} + +define i32 @vf4i32(ptr %this) readnone { + ret i32 4 +} + +define i64 @vf5i64(ptr %this) readnone { + ret i64 5 +} + +define i64 @vf6i64(ptr %this) readnone { + ret i64 6 +} + +define i8 @vf9i8(ptr %this) readnone { + ret i8 10 +} + +define i8 @vf10i8(ptr %this) readnone { + ret i8 11 +} + +; COMMON-LABEL: define i8 @call0( +define i8 @call0(ptr %obj) { + %vtable = load ptr, ptr %obj + %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") + call void @llvm.assume(i1 %p) + %fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 0 + %fptr = load ptr, ptr %fptrptr + %result = call i8 %fptr(ptr %obj) + ret i8 %result + ; COMMON: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 -1 + ; COMMON: [[VTLOAD:%[^ ]*]] = load i8, ptr [[VTGEP]] + ; COMMON: ret i8 [[VTLOAD]] +} + +; COMMON-LABEL: define i64 @call1( +define i64 @call1(ptr %obj) { + %vtable = load ptr, ptr %obj + %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") + call void @llvm.assume(i1 %p) + %fptrptr = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1 + %fptr = load ptr, ptr %fptrptr + %result = call i64 %fptr(ptr %obj) + ret i64 %result + ; ABI32: [[VTGEP:%[^ ]*]] = getelementptr i8, ptr %vtable, i32 8 + ; ABI32-NEXT: [[VTLOAD:%[^ ]*]] = load i64, ptr [[VTGEP]] + ; ABI64: [[VTGEP:%[^ ]*]] = getelementptr [3 x ptr], ptr %vtable, i32 0, i32 1 + ; ABI64-NEXT: [[FUNC:%[^ ]*]] = load ptr, ptr [[VTGEP]], align 4 + ; ABI64-NEXT: [[VTLOAD:%[^ ]*]] = call i64 [[FUNC]](ptr %obj) + ; COMMON-NEXT: ret i64 [[VTLOAD]] +} + +; COMMON: [[T]] = !{i32 4, !"typeid"} + +!1 = !{i32 0, !"typeid"} diff --git a/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll index ab76f2c22e343..314b1ee13a800 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll +++ b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-32.ll @@ -1,7 +1,9 @@ -; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s - ;; This target uses 32-bit sized and aligned pointers. -target datalayout = "e-p:32:32" +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:64" %s | FileCheck %s + +;; The tests should be the exact same even with different preferred alignments since +;; the ABI alignment is used. +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:32:32-i64:64:128" %s | FileCheck %s ;; Constant propagation should be agnostic towards sections. ;; Also the new global should be in the original vtable's section. diff --git a/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll index c83fbc6ed5a19..9f39b65e26650 100644 --- a/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll +++ b/llvm/test/Transforms/WholeProgramDevirt/virtual-const-prop-small-alignment-64.ll @@ -1,7 +1,9 @@ -; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s - ;; This target uses 64-bit sized and aligned pointers. -target datalayout = "e-p:64:64" +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:64" %s | FileCheck %s + +;; The tests should be the exact same even with different preferred alignments since +;; the ABI alignment is used. +; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility --data-layout="e-p:64:64-i64:64:128" %s | FileCheck %s ;; Constant propagation should be agnostic towards sections. ;; Also the new global should be in the original vtable's section.