1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[InstCombine] Make varargs cast transform compatible with opaque ptrs

The whole transform can be dropped once we have fully transitioned
to opaque pointers (as it's purpose is to remove no-op pointer
casts). For now, make sure that it handles opaque pointers correctly.
This commit is contained in:
Nikita Popov 2021-06-24 21:46:55 +02:00
parent e511168087
commit d354f79d7d
2 changed files with 62 additions and 11 deletions

View File

@ -2031,20 +2031,27 @@ static bool isSafeToEliminateVarargsCast(const CallBase &Call,
isa<GCResultInst>(Call))
return false;
// Opaque pointers are compatible with any byval types.
PointerType *SrcTy = cast<PointerType>(CI->getOperand(0)->getType());
if (SrcTy->isOpaque())
return true;
// The size of ByVal or InAlloca arguments is derived from the type, so we
// can't change to a type with a different size. If the size were
// passed explicitly we could avoid this check.
if (!Call.isPassPointeeByValueArgument(ix))
return true;
Type* SrcTy =
cast<PointerType>(CI->getOperand(0)->getType())->getElementType();
Type *DstTy = Call.isByValArgument(ix)
? Call.getParamByValType(ix)
: cast<PointerType>(CI->getType())->getElementType();
if (!SrcTy->isSized() || !DstTy->isSized())
// The transform currently only handles type replacement for byval, not other
// type-carrying attributes.
if (!Call.isByValArgument(ix))
return false;
if (DL.getTypeAllocSize(SrcTy) != DL.getTypeAllocSize(DstTy))
Type *SrcElemTy = SrcTy->getElementType();
Type *DstElemTy = Call.getParamByValType(ix);
if (!SrcElemTy->isSized() || !DstElemTy->isSized())
return false;
if (DL.getTypeAllocSize(SrcElemTy) != DL.getTypeAllocSize(DstElemTy))
return false;
return true;
}
@ -2310,6 +2317,7 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
if (IntrinsicInst *II = findInitTrampoline(Callee))
return transformCallThroughTrampoline(Call, *II);
// TODO: Drop this transform once opaque pointer transition is done.
FunctionType *FTy = Call.getFunctionType();
if (FTy->isVarArg()) {
int ix = FTy->getNumParams();
@ -2321,13 +2329,14 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
if (CI && isSafeToEliminateVarargsCast(Call, DL, CI, ix)) {
replaceUse(*I, CI->getOperand(0));
// Update the byval type to match the argument type.
if (Call.isByValArgument(ix)) {
// Update the byval type to match the pointer type.
// Not necessary for opaque pointers.
PointerType *NewTy = cast<PointerType>(CI->getOperand(0)->getType());
if (!NewTy->isOpaque() && Call.isByValArgument(ix)) {
Call.removeParamAttr(ix, Attribute::ByVal);
Call.addParamAttr(
ix, Attribute::getWithByValType(
Call.getContext(),
CI->getOperand(0)->getType()->getPointerElementType()));
Call.getContext(), NewTy->getElementType()));
}
Changed = true;
}

View File

@ -124,3 +124,45 @@ define void @call(ptr %a) {
call void %a()
ret void
}
declare void @varargs(...)
define void @varargs_cast_typed_to_opaque_same_type(i32* %a) {
; CHECK-LABEL: @varargs_cast_typed_to_opaque_same_type(
; CHECK-NEXT: call void (...) @varargs(i32* byval(i32) [[A:%.*]])
; CHECK-NEXT: ret void
;
%b = bitcast i32* %a to ptr
call void (...) @varargs(ptr byval(i32) %b)
ret void
}
define void @varargs_cast_typed_to_opaque_different_type(i32* %a) {
; CHECK-LABEL: @varargs_cast_typed_to_opaque_different_type(
; CHECK-NEXT: call void (...) @varargs(i32* byval(i32) [[A:%.*]])
; CHECK-NEXT: ret void
;
%b = bitcast i32* %a to ptr
call void (...) @varargs(ptr byval(float) %b)
ret void
}
define void @varargs_cast_typed_to_opaque_different_size(i32* %a) {
; CHECK-LABEL: @varargs_cast_typed_to_opaque_different_size(
; CHECK-NEXT: [[B:%.*]] = bitcast i32* [[A:%.*]] to ptr
; CHECK-NEXT: call void (...) @varargs(ptr byval(i64) [[B]])
; CHECK-NEXT: ret void
;
%b = bitcast i32* %a to ptr
call void (...) @varargs(ptr byval(i64) %b)
ret void
}
define void @varargs_cast_opaque_to_typed(ptr %a) {
; CHECK-LABEL: @varargs_cast_opaque_to_typed(
; CHECK-NEXT: call void (...) @varargs(ptr byval(i8) [[A:%.*]])
; CHECK-NEXT: ret void
;
%b = bitcast ptr %a to i8*
call void (...) @varargs(i8* byval(i8) %b)
ret void
}