forked from OSchip/llvm-project
[InstCombine] Simplify calls with casted `returned` attribute
The handling of the `returned` attribute in D75815 did miss the case where the argument is (bit)casted to a different type. This is explicitly allowed by the language reference and exposed by the Attributor. Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D77977
This commit is contained in:
parent
8ad19ffa7b
commit
ea7f17ee38
|
@ -4654,8 +4654,13 @@ Instruction *InstCombiner::visitCallBase(CallBase &Call) {
|
|||
}
|
||||
|
||||
if (!Call.use_empty() && !Call.isMustTailCall())
|
||||
if (Value *ReturnedArg = Call.getReturnedArgOperand())
|
||||
return replaceInstUsesWith(Call, ReturnedArg);
|
||||
if (Value *ReturnedArg = Call.getReturnedArgOperand()) {
|
||||
Type *CallTy = Call.getType();
|
||||
Type *RetArgTy = ReturnedArg->getType();
|
||||
if (RetArgTy->canLosslesslyBitCastTo(CallTy))
|
||||
return replaceInstUsesWith(
|
||||
Call, Builder.CreateBitOrPointerCast(ReturnedArg, CallTy));
|
||||
}
|
||||
|
||||
if (isAllocLikeFn(&Call, &TLI))
|
||||
return visitAllocSite(Call);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
declare i32 @passthru_i32(i32 returned)
|
||||
declare i8* @passthru_p8(i8* returned)
|
||||
declare i8* @passthru_p8_from_p32(i32* returned)
|
||||
declare <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> returned)
|
||||
|
||||
define i32 @returned_const_int_arg() {
|
||||
; CHECK-LABEL: @returned_const_int_arg(
|
||||
|
@ -22,6 +24,46 @@ define i8* @returned_const_ptr_arg() {
|
|||
ret i8* %x
|
||||
}
|
||||
|
||||
define i8* @returned_const_ptr_arg_casted() {
|
||||
; CHECK-LABEL: @returned_const_ptr_arg_casted(
|
||||
; CHECK-NEXT: [[X:%.*]] = call i8* @passthru_p8_from_p32(i32* null)
|
||||
; CHECK-NEXT: ret i8* null
|
||||
;
|
||||
%x = call i8* @passthru_p8_from_p32(i32* null)
|
||||
ret i8* %x
|
||||
}
|
||||
|
||||
define i8* @returned_ptr_arg_casted(i32* %a) {
|
||||
; CHECK-LABEL: @returned_ptr_arg_casted(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[A:%.*]] to i8*
|
||||
; CHECK-NEXT: [[X:%.*]] = call i8* @passthru_p8_from_p32(i32* [[A]])
|
||||
; CHECK-NEXT: ret i8* [[TMP1]]
|
||||
;
|
||||
%x = call i8* @passthru_p8_from_p32(i32* %a)
|
||||
ret i8* %x
|
||||
}
|
||||
|
||||
@GV = constant <2 x i32> zeroinitializer
|
||||
define <8 x i8> @returned_const_vec_arg_casted() {
|
||||
; CHECK-LABEL: @returned_const_vec_arg_casted(
|
||||
; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> zeroinitializer)
|
||||
; CHECK-NEXT: ret <8 x i8> zeroinitializer
|
||||
;
|
||||
%v = load <2 x i32>, <2 x i32>* @GV
|
||||
%x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %v)
|
||||
ret <8 x i8> %x
|
||||
}
|
||||
|
||||
define <8 x i8> @returned_vec_arg_casted(<2 x i32> %a) {
|
||||
; CHECK-LABEL: @returned_vec_arg_casted(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[A:%.*]] to <8 x i8>
|
||||
; CHECK-NEXT: [[X:%.*]] = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> [[A]])
|
||||
; CHECK-NEXT: ret <8 x i8> [[TMP1]]
|
||||
;
|
||||
%x = call <8 x i8> @passthru_8i8v_from_2i32v(<2 x i32> %a)
|
||||
ret <8 x i8> %x
|
||||
}
|
||||
|
||||
define i32 @returned_var_arg(i32 %arg) {
|
||||
; CHECK-LABEL: @returned_var_arg(
|
||||
; CHECK-NEXT: [[X:%.*]] = call i32 @passthru_i32(i32 [[ARG:%.*]])
|
||||
|
@ -48,3 +90,4 @@ define i32 @returned_var_arg_musttail(i32 %arg) {
|
|||
%x = musttail call i32 @passthru_i32(i32 %arg)
|
||||
ret i32 %x
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue