mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-13 00:11:56 +00:00
WholeProgramDevirt: Implement export/import support for VCP.
Differential Revision: https://reviews.llvm.org/D30017 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297503 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eb3c7034f3
commit
bfecb4640b
@ -380,6 +380,7 @@ struct DevirtModule {
|
||||
PointerType *Int8PtrTy;
|
||||
IntegerType *Int32Ty;
|
||||
IntegerType *Int64Ty;
|
||||
IntegerType *IntPtrTy;
|
||||
|
||||
bool RemarksEnabled;
|
||||
|
||||
@ -402,6 +403,7 @@ struct DevirtModule {
|
||||
Int8PtrTy(Type::getInt8PtrTy(M.getContext())),
|
||||
Int32Ty(Type::getInt32Ty(M.getContext())),
|
||||
Int64Ty(Type::getInt64Ty(M.getContext())),
|
||||
IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
|
||||
RemarksEnabled(areRemarksEnabled()) {}
|
||||
|
||||
bool areRemarksEnabled();
|
||||
@ -448,7 +450,7 @@ struct DevirtModule {
|
||||
// This function is called during the import phase to create a reference to
|
||||
// the symbol definition created during the export phase.
|
||||
Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
|
||||
StringRef Name);
|
||||
StringRef Name, unsigned AbsWidth = 0);
|
||||
|
||||
void applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne,
|
||||
Constant *UniqueMemberAddr);
|
||||
@ -802,12 +804,25 @@ void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
|
||||
}
|
||||
|
||||
Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
|
||||
StringRef Name) {
|
||||
StringRef Name, unsigned AbsWidth) {
|
||||
Constant *C = M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Ty);
|
||||
auto *GV = dyn_cast<GlobalVariable>(C);
|
||||
if (!GV)
|
||||
// We only need to set metadata if the global is newly created, in which
|
||||
// case it would not have hidden visibility.
|
||||
if (!GV || GV->getVisibility() == GlobalValue::HiddenVisibility)
|
||||
return C;
|
||||
|
||||
GV->setVisibility(GlobalValue::HiddenVisibility);
|
||||
auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
|
||||
auto *MinC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Min));
|
||||
auto *MaxC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Max));
|
||||
GV->setMetadata(LLVMContext::MD_absolute_symbol,
|
||||
MDNode::get(M.getContext(), {MinC, MaxC}));
|
||||
};
|
||||
if (AbsWidth == IntPtrTy->getBitWidth())
|
||||
SetAbsRange(~0ull, ~0ull); // Full set.
|
||||
else if (AbsWidth)
|
||||
SetAbsRange(0, 1ull << AbsWidth);
|
||||
return GV;
|
||||
}
|
||||
|
||||
@ -895,6 +910,7 @@ void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
|
||||
Call.replaceAndErase("virtual-const-prop", FnName, RemarksEnabled, Val);
|
||||
}
|
||||
}
|
||||
CSInfo.markDevirt();
|
||||
}
|
||||
|
||||
bool DevirtModule::tryVirtualConstProp(
|
||||
@ -979,9 +995,18 @@ bool DevirtModule::tryVirtualConstProp(
|
||||
for (auto &&Target : TargetsForSlot)
|
||||
Target.WasDevirt = true;
|
||||
|
||||
// Rewrite each call to a load from OffsetByte/OffsetBit.
|
||||
Constant *ByteConst = ConstantInt::get(Int32Ty, OffsetByte);
|
||||
Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
|
||||
|
||||
if (CSByConstantArg.second.isExported()) {
|
||||
ResByArg->TheKind = WholeProgramDevirtResolution::ByArg::VirtualConstProp;
|
||||
exportGlobal(Slot, CSByConstantArg.first, "byte",
|
||||
ConstantExpr::getIntToPtr(ByteConst, Int8PtrTy));
|
||||
exportGlobal(Slot, CSByConstantArg.first, "bit",
|
||||
ConstantExpr::getIntToPtr(BitConst, Int8PtrTy));
|
||||
}
|
||||
|
||||
// Rewrite each call to a load from OffsetByte/OffsetBit.
|
||||
applyVirtualConstProp(CSByConstantArg.second,
|
||||
TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
|
||||
}
|
||||
@ -1207,6 +1232,13 @@ void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
|
||||
UniqueMemberAddr);
|
||||
break;
|
||||
}
|
||||
case WholeProgramDevirtResolution::ByArg::VirtualConstProp: {
|
||||
Constant *Byte = importGlobal(Slot, CSByConstantArg.first, "byte", 32);
|
||||
Byte = ConstantExpr::getPtrToInt(Byte, Int32Ty);
|
||||
Constant *Bit = importGlobal(Slot, CSByConstantArg.first, "bit", 8);
|
||||
Bit = ConstantExpr::getPtrToInt(Bit, Int8Ty);
|
||||
applyVirtualConstProp(CSByConstantArg.second, "", Byte, Bit);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
19
test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml
Normal file
19
test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
TypeIdMap:
|
||||
typeid1:
|
||||
WPDRes:
|
||||
0:
|
||||
Kind: Indir
|
||||
ResByArg:
|
||||
1:
|
||||
Kind: VirtualConstProp
|
||||
Info: 0
|
||||
typeid2:
|
||||
WPDRes:
|
||||
8:
|
||||
Kind: Indir
|
||||
ResByArg:
|
||||
3:
|
||||
Kind: VirtualConstProp
|
||||
Info: 0
|
||||
...
|
83
test/Transforms/WholeProgramDevirt/export-vcp.ll
Normal file
83
test/Transforms/WholeProgramDevirt/export-vcp.ll
Normal file
@ -0,0 +1,83 @@
|
||||
; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s
|
||||
; RUN: FileCheck --check-prefix=SUMMARY %s < %t
|
||||
|
||||
target datalayout = "e-p:64:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; SUMMARY: TypeIdMap:
|
||||
; SUMMARY-NEXT: typeid3:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: Indir
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: 12,24:
|
||||
; SUMMARY-NEXT: Kind: VirtualConstProp
|
||||
; SUMMARY-NEXT: Info: 0
|
||||
; SUMMARY-NEXT: typeid4:
|
||||
; SUMMARY-NEXT: TTRes:
|
||||
; SUMMARY-NEXT: Kind: Unsat
|
||||
; SUMMARY-NEXT: SizeM1BitWidth: 0
|
||||
; SUMMARY-NEXT: WPDRes:
|
||||
; SUMMARY-NEXT: 0:
|
||||
; SUMMARY-NEXT: Kind: Indir
|
||||
; SUMMARY-NEXT: SingleImplName: ''
|
||||
; SUMMARY-NEXT: ResByArg:
|
||||
; SUMMARY-NEXT: 24,12:
|
||||
; SUMMARY-NEXT: Kind: VirtualConstProp
|
||||
; SUMMARY-NEXT: Info: 0
|
||||
|
||||
; CHECK: [[CVT3A:.*]] = private constant { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] zeroinitializer, i1 (i8*, i32, i32)* @vf0i1, [0 x i8] zeroinitializer }, !type !0
|
||||
@vt3a = constant i1 (i8*, i32, i32)* @vf0i1, !type !0
|
||||
|
||||
; CHECK: [[CVT3B:.*]] = private constant { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", i1 (i8*, i32, i32)* @vf1i1, [0 x i8] zeroinitializer }, !type !0
|
||||
@vt3b = constant i1 (i8*, i32, i32)* @vf1i1, !type !0
|
||||
|
||||
; CHECK: [[CVT3C:.*]] = private constant { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] zeroinitializer, i1 (i8*, i32, i32)* @vf0i1, [0 x i8] zeroinitializer }, !type !0
|
||||
@vt3c = constant i1 (i8*, i32, i32)* @vf0i1, !type !0
|
||||
|
||||
; CHECK: [[CVT3D:.*]] = private constant { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", i1 (i8*, i32, i32)* @vf1i1, [0 x i8] zeroinitializer }, !type !0
|
||||
@vt3d = constant i1 (i8*, i32, i32)* @vf1i1, !type !0
|
||||
|
||||
; CHECK: [[CVT4A:.*]] = private constant { [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] c"\00\00\00\00\01\00\00\00", i32 (i8*, i32, i32)* @vf1i32, [0 x i8] zeroinitializer }, !type !1
|
||||
@vt4a = constant i32 (i8*, i32, i32)* @vf1i32, !type !1
|
||||
|
||||
; CHECK: [[CVT4B:.*]] = private constant { [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] c"\00\00\00\00\02\00\00\00", i32 (i8*, i32, i32)* @vf2i32, [0 x i8] zeroinitializer }, !type !1
|
||||
@vt4b = constant i32 (i8*, i32, i32)* @vf2i32, !type !1
|
||||
|
||||
; CHECK: @__typeid_typeid3_0_12_24_byte = hidden alias i8, inttoptr (i32 -1 to i8*)
|
||||
; CHECK: @__typeid_typeid3_0_12_24_bit = hidden alias i8, inttoptr (i8 1 to i8*)
|
||||
; CHECK: @__typeid_typeid4_0_24_12_byte = hidden alias i8, inttoptr (i32 -4 to i8*)
|
||||
; CHECK: @__typeid_typeid4_0_24_12_bit = hidden alias i8, inttoptr (i8 1 to i8*)
|
||||
|
||||
; CHECK: @vt3a = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3A]], i32 0, i32 1)
|
||||
; CHECK: @vt3b = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3B]], i32 0, i32 1)
|
||||
; CHECK: @vt3c = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3C]], i32 0, i32 1)
|
||||
; CHECK: @vt3d = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3D]], i32 0, i32 1)
|
||||
; CHECK: @vt4a = alias i32 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] }* [[CVT4A]], i32 0, i32 1)
|
||||
; CHECK: @vt4b = alias i32 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] }* [[CVT4B]], i32 0, i32 1)
|
||||
|
||||
define i1 @vf0i1(i8* %this, i32, i32) readnone {
|
||||
ret i1 0
|
||||
}
|
||||
|
||||
define i1 @vf1i1(i8* %this, i32, i32) readnone {
|
||||
ret i1 1
|
||||
}
|
||||
|
||||
define i32 @vf1i32(i8* %this, i32, i32) readnone {
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
define i32 @vf2i32(i8* %this, i32, i32) readnone {
|
||||
ret i32 2
|
||||
}
|
||||
|
||||
; CHECK: !0 = !{i32 8, !"typeid3"}
|
||||
; CHECK: !1 = !{i32 8, !"typeid4"}
|
||||
|
||||
!0 = !{i32 0, !"typeid3"}
|
||||
!1 = !{i32 0, !"typeid4"}
|
@ -2,10 +2,17 @@
|
||||
; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-uniform-ret-val.yaml < %s | FileCheck --check-prefixes=CHECK,UNIFORM-RET-VAL %s
|
||||
; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-unique-ret-val0.yaml < %s | FileCheck --check-prefixes=CHECK,UNIQUE-RET-VAL0 %s
|
||||
; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-unique-ret-val1.yaml < %s | FileCheck --check-prefixes=CHECK,UNIQUE-RET-VAL1 %s
|
||||
; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml < %s | FileCheck --check-prefixes=CHECK,VCP,VCP64 %s
|
||||
; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml -mtriple=i686-unknown-linux -data-layout=e-p:32:32 < %s | FileCheck --check-prefixes=CHECK,VCP,VCP32 %s
|
||||
|
||||
target datalayout = "e-p:64:64"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; VCP: @__typeid_typeid1_0_1_byte = external hidden global i8, !absolute_symbol !0
|
||||
; VCP: @__typeid_typeid1_0_1_bit = external hidden global i8, !absolute_symbol !1
|
||||
; VCP: @__typeid_typeid2_8_3_byte = external hidden global i8, !absolute_symbol !0
|
||||
; VCP: @__typeid_typeid2_8_3_bit = external hidden global i8, !absolute_symbol !1
|
||||
|
||||
; Test cases where the argument values are known and we can apply virtual
|
||||
; constant propagation.
|
||||
|
||||
@ -22,6 +29,11 @@ define i32 @call1(i8* %obj) {
|
||||
; SINGLE-IMPL: call i32 bitcast (void ()* @singleimpl1 to i32 (i8*, i32)*)
|
||||
%result = call i32 %fptr_casted(i8* %obj, i32 1)
|
||||
; UNIFORM-RET-VAL: ret i32 42
|
||||
; VCP: [[VT1:%.*]] = bitcast {{.*}} to i8*
|
||||
; VCP: [[GEP1:%.*]] = getelementptr i8, i8* [[VT1]], i32 ptrtoint (i8* @__typeid_typeid1_0_1_byte to i32)
|
||||
; VCP: [[BC1:%.*]] = bitcast i8* [[GEP1]] to i32*
|
||||
; VCP: [[LOAD1:%.*]] = load i32, i32* [[BC1]]
|
||||
; VCP: ret i32 [[LOAD1]]
|
||||
ret i32 %result
|
||||
}
|
||||
|
||||
@ -68,6 +80,12 @@ cont:
|
||||
%result = call i1 %fptr_casted(i8* %obj, i32 3)
|
||||
; UNIQUE-RET-VAL0: icmp ne i8* %vtablei8, @__typeid_typeid2_8_3_unique_member
|
||||
; UNIQUE-RET-VAL1: icmp eq i8* %vtablei8, @__typeid_typeid2_8_3_unique_member
|
||||
; VCP: [[VT2:%.*]] = bitcast {{.*}} to i8*
|
||||
; VCP: [[GEP2:%.*]] = getelementptr i8, i8* [[VT2]], i32 ptrtoint (i8* @__typeid_typeid2_8_3_byte to i32)
|
||||
; VCP: [[LOAD2:%.*]] = load i8, i8* [[GEP2]]
|
||||
; VCP: [[AND2:%.*]] = and i8 [[LOAD2]], ptrtoint (i8* @__typeid_typeid2_8_3_bit to i8)
|
||||
; VCP: [[ICMP2:%.*]] = icmp ne i8 [[AND2]], 0
|
||||
; VCP: ret i1 [[ICMP2]]
|
||||
ret i1 %result
|
||||
|
||||
trap:
|
||||
@ -78,6 +96,12 @@ trap:
|
||||
; SINGLE-IMPL-DAG: declare void @singleimpl1()
|
||||
; SINGLE-IMPL-DAG: declare void @singleimpl2()
|
||||
|
||||
; VCP32: !0 = !{i32 -1, i32 -1}
|
||||
; VCP64: !0 = !{i64 0, i64 4294967296}
|
||||
|
||||
; VCP32: !1 = !{i32 0, i32 256}
|
||||
; VCP64: !1 = !{i64 0, i64 256}
|
||||
|
||||
declare void @llvm.assume(i1)
|
||||
declare void @llvm.trap()
|
||||
declare {i8*, i1} @llvm.type.checked.load(i8*, i32, metadata)
|
||||
|
Loading…
x
Reference in New Issue
Block a user