diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 187e000d0272d..da92f7d99df43 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -4397,8 +4397,14 @@ class TargetLowering : public TargetLoweringBase { } CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType, - SDValue Target, ArgListTy &&ArgsList) { + SDValue Target, ArgListTy &&ArgsList, + AttributeSet ResultAttrs = {}) { RetTy = ResultType; + IsInReg = ResultAttrs.hasAttribute(Attribute::InReg); + RetSExt = ResultAttrs.hasAttribute(Attribute::SExt); + RetZExt = ResultAttrs.hasAttribute(Attribute::ZExt); + NoMerge = ResultAttrs.hasAttribute(Attribute::NoMerge); + Callee = Target; CallConv = CC; NumFixedArgs = ArgsList.size(); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index c5fd56795a520..4bb0ba6f08310 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9728,7 +9728,7 @@ SDValue SelectionDAGBuilder::lowerRangeToAssertZExt(SelectionDAG &DAG, void SelectionDAGBuilder::populateCallLoweringInfo( TargetLowering::CallLoweringInfo &CLI, const CallBase *Call, unsigned ArgIdx, unsigned NumArgs, SDValue Callee, Type *ReturnTy, - bool IsPatchPoint) { + AttributeSet RetAttrs, bool IsPatchPoint) { TargetLowering::ArgListTy Args; Args.reserve(NumArgs); @@ -9749,7 +9749,8 @@ void SelectionDAGBuilder::populateCallLoweringInfo( CLI.setDebugLoc(getCurSDLoc()) .setChain(getRoot()) - .setCallee(Call->getCallingConv(), ReturnTy, Callee, std::move(Args)) + .setCallee(Call->getCallingConv(), ReturnTy, Callee, std::move(Args), + RetAttrs) .setDiscardResult(Call->use_empty()) .setIsPatchPoint(IsPatchPoint) .setIsPreallocated( @@ -9898,7 +9899,7 @@ void SelectionDAGBuilder::visitPatchpoint(const CallBase &CB, TargetLowering::CallLoweringInfo CLI(DAG); populateCallLoweringInfo(CLI, &CB, NumMetaOpers, NumCallArgs, Callee, - ReturnTy, true); + ReturnTy, CB.getAttributes().getRetAttrs(), true); std::pair Result = lowerInvokable(CLI, EHPadBB); SDNode *CallEnd = Result.second.getNode(); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index ec23445b01640..a97884f0efb9a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -426,7 +426,8 @@ class SelectionDAGBuilder { void populateCallLoweringInfo(TargetLowering::CallLoweringInfo &CLI, const CallBase *Call, unsigned ArgIdx, unsigned NumArgs, SDValue Callee, - Type *ReturnTy, bool IsPatchPoint); + Type *ReturnTy, AttributeSet RetAttrs, + bool IsPatchPoint); std::pair lowerInvokable(TargetLowering::CallLoweringInfo &CLI, diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index f313d60424c23..cf32350036d41 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -1033,10 +1033,16 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, ActualCallee = Callee; } + const auto GCResultLocality = getGCResultLocality(I); + AttributeSet retAttrs; + if (GCResultLocality.first) + retAttrs = GCResultLocality.first->getAttributes().getRetAttrs(); + StatepointLoweringInfo SI(DAG); populateCallLoweringInfo(SI.CLI, &I, GCStatepointInst::CallArgsBeginPos, I.getNumCallArgs(), ActualCallee, - I.getActualReturnType(), false /* IsPatchPoint */); + I.getActualReturnType(), retAttrs, + /*IsPatchPoint=*/false); // There may be duplication in the gc.relocate list; such as two copies of // each relocation on normal and exceptional path for an invoke. We only @@ -1092,8 +1098,6 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, SDValue ReturnValue = LowerAsSTATEPOINT(SI); // Export the result value if needed - const auto GCResultLocality = getGCResultLocality(I); - if (!GCResultLocality.first && !GCResultLocality.second) { // The return value is not needed, just generate a poison value. // Note: This covers the void return case. @@ -1138,7 +1142,7 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl( populateCallLoweringInfo( SI.CLI, Call, ArgBeginIndex, Call->arg_size(), Callee, ForceVoidReturnTy ? Type::getVoidTy(*DAG.getContext()) : Call->getType(), - false); + Call->getAttributes().getRetAttrs(), /*IsPatchPoint=*/false); if (!VarArgDisallowed) SI.CLI.IsVarArg = Call->getFunctionType()->isVarArg(); diff --git a/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll b/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll index 6326d3db9afb8..9619895c450ca 100644 --- a/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll +++ b/llvm/test/CodeGen/AArch64/statepoint-call-lowering.ll @@ -23,7 +23,6 @@ define i1 @test_i1_return() gc "statepoint-example" { ; CHECK-NEXT: .cfi_offset w30, -16 ; CHECK-NEXT: bl return_i1 ; CHECK-NEXT: .Ltmp0: -; CHECK-NEXT: and w0, w0, #0x1 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret ; This is just checking that a i1 gets lowered normally when there's no extra @@ -106,7 +105,6 @@ define i1 @test_relocate(ptr addrspace(1) %a) gc "statepoint-example" { ; CHECK-NEXT: .cfi_offset w30, -16 ; CHECK-NEXT: bl return_i1 ; CHECK-NEXT: .Ltmp5: -; CHECK-NEXT: and w0, w0, #0x1 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret ; Check that an ununsed relocate has no code-generation impact @@ -145,7 +143,6 @@ define i1 @test_i1_return_patchable() gc "statepoint-example" { ; CHECK-NEXT: .cfi_offset w30, -16 ; CHECK-NEXT: nop ; CHECK-NEXT: .Ltmp7: -; CHECK-NEXT: and w0, w0, #0x1 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret ; A patchable variant of test_i1_return diff --git a/llvm/test/CodeGen/X86/statepoint-call-lowering.ll b/llvm/test/CodeGen/X86/statepoint-call-lowering.ll index 66088046ef5ec..758cb8b7b63d5 100644 --- a/llvm/test/CodeGen/X86/statepoint-call-lowering.ll +++ b/llvm/test/CodeGen/X86/statepoint-call-lowering.ll @@ -247,8 +247,6 @@ define i8 @test_signext_return(ptr) gc "statepoint-example" { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: callq signext_return_i1@PLT ; CHECK-NEXT: .Ltmp10: -; CHECK-NEXT: andb $1, %al -; CHECK-NEXT: negb %al ; CHECK-NEXT: popq %rcx ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq @@ -266,7 +264,6 @@ define i8 @test_zeroext_return() gc "statepoint-example" { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: callq return_i1@PLT ; CHECK-NEXT: .Ltmp11: -; CHECK-NEXT: andb $1, %al ; CHECK-NEXT: popq %rcx ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq @@ -277,6 +274,24 @@ entry: ret i8 %ext } +define signext i1 @test_noext_signext_return() gc "statepoint-example" { +; CHECK-LABEL: test_noext_signext_return: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: callq return_i1@PLT +; CHECK-NEXT: .Ltmp12: +; CHECK-NEXT: andb $1, %al +; CHECK-NEXT: negb %al +; CHECK-NEXT: popq %rcx +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +entry: + %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) + %call1 = call i1 @llvm.experimental.gc.result.i1(token %safepoint_token) + ret i1 %call1 +} + declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...) declare i1 @llvm.experimental.gc.result.i1(token)