[InstCombine] Support opaque pointers in callee bitcast fold

To make this actually trigger, we also need to check whether the
function types differ, which is a hidden cast under opaque pointers.
The transform is somewhat less relevant there because it is
primarily about pointer bitcasts, but it can also happen with other
bit- or pointer-castable types.

Byval handling is easier with opaque pointers because there is no
need to adjust the byval type, we only need to make sure that it's
still a pointer.
This commit is contained in:
Nikita Popov 2022-03-03 11:05:31 +01:00
parent 6b3b3ef344
commit c1b9667148
2 changed files with 40 additions and 9 deletions

View File

@ -2834,10 +2834,12 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
// If the callee is a pointer to a function, attempt to move any casts to the
// arguments of the call/callbr/invoke.
Value *Callee = Call.getCalledOperand();
if (!isa<Function>(Callee) && transformConstExprCastCall(Call))
Function *CalleeF = dyn_cast<Function>(Callee);
if ((!CalleeF || CalleeF->getFunctionType() != Call.getFunctionType()) &&
transformConstExprCastCall(Call))
return nullptr;
if (Function *CalleeF = dyn_cast<Function>(Callee)) {
if (CalleeF) {
// Remove the convergent attr on calls when the callee is not convergent.
if (Call.isConvergent() && !CalleeF->isConvergent() &&
!CalleeF->isIntrinsic()) {
@ -3167,13 +3169,18 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
// sized type and the sized type has to have the same size as the old type.
if (ParamTy != ActTy && CallerPAL.hasParamAttr(i, Attribute::ByVal)) {
PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy);
if (!ParamPTy || !ParamPTy->getPointerElementType()->isSized())
if (!ParamPTy)
return false;
Type *CurElTy = Call.getParamByValType(i);
if (DL.getTypeAllocSize(CurElTy) !=
DL.getTypeAllocSize(ParamPTy->getPointerElementType()))
return false;
if (!ParamPTy->isOpaque()) {
Type *ParamElTy = ParamPTy->getNonOpaquePointerElementType();
if (!ParamElTy->isSized())
return false;
Type *CurElTy = Call.getParamByValType(i);
if (DL.getTypeAllocSize(CurElTy) != DL.getTypeAllocSize(ParamElTy))
return false;
}
}
}
@ -3232,9 +3239,10 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
Args.push_back(NewArg);
// Add any parameter attributes.
if (CallerPAL.hasParamAttr(i, Attribute::ByVal)) {
if (CallerPAL.hasParamAttr(i, Attribute::ByVal) &&
!ParamTy->isOpaquePointerTy()) {
AttrBuilder AB(FT->getContext(), CallerPAL.getParamAttrs(i));
AB.addByValAttr(NewArg->getType()->getPointerElementType());
AB.addByValAttr(ParamTy->getNonOpaquePointerElementType());
ArgAttrs.push_back(AttributeSet::get(Ctx, AB));
} else
ArgAttrs.push_back(CallerPAL.getParamAttrs(i));

View File

@ -493,3 +493,26 @@ define void @dse(ptr %p) {
store i8 1, ptr %p
ret void
}
declare void @call_i64(i64)
declare void @call_byval(i64, ptr byval(i64))
define void @call_cast_ptr_to_int(ptr %p) {
; CHECK-LABEL: @call_cast_ptr_to_int(
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
; CHECK-NEXT: call void @call_i64(i64 [[TMP1]])
; CHECK-NEXT: ret void
;
call void @call_i64(ptr %p)
ret void
}
define void @call_cast_byval(ptr %p, ptr %p2) {
; CHECK-LABEL: @call_cast_byval(
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
; CHECK-NEXT: call void @call_byval(i64 [[TMP1]], ptr byval(double) [[P2:%.*]])
; CHECK-NEXT: ret void
;
call void @call_byval(ptr %p, ptr byval(double) %p2)
ret void
}