diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -208,6 +208,11 @@ return static_cast(TLI); } + /// \returns Flags corresponding to the attributes on the \p ArgIdx-th + /// parameter of \p Call. + ISD::ArgFlagsTy getAttributesForArgIdx(const CallBase &Call, + unsigned ArgIdx) const; + template void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -30,6 +30,34 @@ void CallLowering::anchor() {} +ISD::ArgFlagsTy CallLowering::getAttributesForArgIdx(const CallBase &Call, + unsigned ArgIdx) const { + ISD::ArgFlagsTy Flags; + if (Call.paramHasAttr(ArgIdx, Attribute::SExt)) + Flags.setSExt(); + if (Call.paramHasAttr(ArgIdx, Attribute::ZExt)) + Flags.setZExt(); + if (Call.paramHasAttr(ArgIdx, Attribute::InReg)) + Flags.setInReg(); + if (Call.paramHasAttr(ArgIdx, Attribute::StructRet)) + Flags.setSRet(); + if (Call.paramHasAttr(ArgIdx, Attribute::Nest)) + Flags.setNest(); + if (Call.paramHasAttr(ArgIdx, Attribute::ByVal)) + Flags.setByVal(); + if (Call.paramHasAttr(ArgIdx, Attribute::Preallocated)) + Flags.setPreallocated(); + if (Call.paramHasAttr(ArgIdx, Attribute::InAlloca)) + Flags.setInAlloca(); + if (Call.paramHasAttr(ArgIdx, Attribute::Returned)) + Flags.setReturned(); + if (Call.paramHasAttr(ArgIdx, Attribute::SwiftSelf)) + Flags.setSwiftSelf(); + if (Call.paramHasAttr(ArgIdx, Attribute::SwiftError)) + Flags.setSwiftError(); + return Flags; +} + bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, ArrayRef ResRegs, ArrayRef> ArgRegs, @@ -44,7 +72,7 @@ unsigned i = 0; unsigned NumFixedArgs = CB.getFunctionType()->getNumParams(); for (auto &Arg : CB.args()) { - ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}, + ArgInfo OrigArg{ArgRegs[i], Arg->getType(), getAttributesForArgIdx(CB, i), i < NumFixedArgs}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CB); Info.OrigArgs.push_back(OrigArg); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -151,6 +151,42 @@ ret void } +; CHECK-LABEL: name: test_zext_in_callee +; CHECK: bb.1 (%ir-block.0): +; CHECK: liveins: $x0 +; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 +; CHECK: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (load 1 from %ir.addr) +; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp +; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[LOAD]](s8) +; CHECK: $w0 = COPY [[ZEXT]](s32) +; CHECK: BL @has_zext_param, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0 +; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp +; CHECK: RET_ReallyLR +declare void @has_zext_param(i8 zeroext) +define void @test_zext_in_callee(i8* %addr) { + %val = load i8, i8* %addr + call void @has_zext_param(i8 %val) + ret void +} + +; CHECK-LABEL: name: test_sext_in_callee +; CHECK: bb.1 (%ir-block.0): +; CHECK: liveins: $x0 +; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 +; CHECK: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (load 1 from %ir.addr) +; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp +; CHECK: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[LOAD]](s8) +; CHECK: $w0 = COPY [[SEXT]](s32) +; CHECK: BL @has_sext_param, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0 +; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp +; CHECK: RET_ReallyLR +declare void @has_sext_param(i8 signext) +define void @test_sext_in_callee(i8* %addr) { + %val = load i8, i8* %addr + call void @has_sext_param(i8 %val) + ret void +} + ; CHECK-LABEL: name: test_abi_sext_ret ; CHECK: [[VAL:%[0-9]+]]:_(s8) = G_LOAD ; CHECK: [[SVAL:%[0-9]+]]:_(s32) = G_SEXT [[VAL]](s8) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll @@ -513,3 +513,67 @@ %error = load %swift_error*, %swift_error** %error_ptr ret %swift_error* %error } + +; foo takes a swifterror parameter. We should be able to see that even when +; it isn't explicitly on the call. +define float @swifterror_param_not_on_call(i8* %error_ref) { +; CHECK-LABEL: swifterror_param_not_on_call: +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: bl {{.*}}foo +; CHECK: mov x0, x21 +; CHECK: cbnz x21 +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: bl {{.*}}free + +entry: + %error_ptr_ref = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr_ref + %call = call float @foo(%swift_error** %error_ptr_ref) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont +cont: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} + +; foo_sret takes an sret parameter and a swifterror parameter. We should be +; able to see that, even if it's not explicitly on the call. +define float @swifterror_param_not_on_call2(i8* %error_ref) { +; CHECK-LABEL: swifterror_param_not_on_call2: +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: mov [[ZERO:x[0-9]+]], xzr +; CHECK: bl {{.*}}foo_sret +; CHECK: mov x0, x21 +; CHECK: cbnz x21 +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: bl {{.*}}free + +entry: + %s = alloca %struct.S, align 8 + %error_ptr_ref = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr_ref + call void @foo_sret(%struct.S* %s, i32 1, %swift_error** %error_ptr_ref) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont +cont: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/swiftself.ll b/llvm/test/CodeGen/AArch64/GlobalISel/swiftself.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/swiftself.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/swiftself.ll @@ -60,3 +60,14 @@ store i8* %3, i8** %0, align 8 ret void } + +; Check that x20 is used to pass a swiftself argument when the parameter is +; only in the declaration's arguments. +; CHECK-LABEL: _swiftself_not_on_call_params: +; CHECK: mov x20, x0 +; CHECK: bl {{_?}}swiftself_param +; CHECK: ret +define i8 *@swiftself_not_on_call_params(i8* %arg) { + %res = call i8 *@swiftself_param(i8* %arg) + ret i8 *%res +} diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-sret.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-sret.ll --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-sret.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/irtranslator-call-sret.ll @@ -49,9 +49,12 @@ ; GCN: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY20]], [[C5]](s32) ; GCN: [[OR1:%[0-9]+]]:_(s32) = G_OR [[OR]], [[SHL1]] ; GCN: $vgpr0 = COPY [[FRAME_INDEX1]](p5) - ; GCN: $vgpr1 = COPY [[FRAME_INDEX]](p5) - ; GCN: [[COPY21:%[0-9]+]]:_(<4 x s32>) = COPY $private_rsrc_reg - ; GCN: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY21]](<4 x s32>) + ; GCN: [[COPY21:%[0-9]+]]:_(p5) = COPY $sp_reg + ; GCN: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; GCN: [[PTR_ADD2:%[0-9]+]]:_(p5) = G_PTR_ADD [[COPY21]], [[C6]](s32) + ; GCN: G_STORE [[FRAME_INDEX]](p5), [[PTR_ADD2]](p5) :: (store 4 into stack, align 16, addrspace 5) + ; GCN: [[COPY22:%[0-9]+]]:_(<4 x s32>) = COPY $private_rsrc_reg + ; GCN: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY22]](<4 x s32>) ; GCN: $sgpr4_sgpr5 = COPY [[COPY11]](p4) ; GCN: $sgpr6_sgpr7 = COPY [[COPY12]](p4) ; GCN: $sgpr8_sgpr9 = COPY [[PTR_ADD1]](p4) @@ -60,11 +63,11 @@ ; GCN: $sgpr13 = COPY [[COPY16]](s32) ; GCN: $sgpr14 = COPY [[COPY17]](s32) ; GCN: $vgpr31 = COPY [[OR1]](s32) - ; GCN: $sgpr30_sgpr31 = SI_CALL [[GV]](p0), @external_void_func_sret_struct_i8_i32_byval_struct_i8_i32, csr_amdgpu_highregs, implicit $vgpr0, implicit $vgpr1, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr4_sgpr5, implicit $sgpr6_sgpr7, implicit $sgpr8_sgpr9, implicit $sgpr10_sgpr11, implicit $sgpr12, implicit $sgpr13, implicit $sgpr14, implicit $vgpr31 - ; GCN: ADJCALLSTACKDOWN 0, 0, implicit-def $scc - ; GCN: [[PTR_ADD2:%[0-9]+]]:_(p5) = G_PTR_ADD [[FRAME_INDEX1]], [[C2]](s32) + ; GCN: $sgpr30_sgpr31 = SI_CALL [[GV]](p0), @external_void_func_sret_struct_i8_i32_byval_struct_i8_i32, csr_amdgpu_highregs, implicit $vgpr0, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $sgpr4_sgpr5, implicit $sgpr6_sgpr7, implicit $sgpr8_sgpr9, implicit $sgpr10_sgpr11, implicit $sgpr12, implicit $sgpr13, implicit $sgpr14, implicit $vgpr31 + ; GCN: ADJCALLSTACKDOWN 0, 8, implicit-def $scc + ; GCN: [[PTR_ADD3:%[0-9]+]]:_(p5) = G_PTR_ADD [[FRAME_INDEX1]], [[C2]](s32) ; GCN: [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[FRAME_INDEX1]](p5) :: (dereferenceable load 1 from %ir.out.gep02, addrspace 5) - ; GCN: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD2]](p5) :: (dereferenceable load 4 from %ir.out.gep1, addrspace 5) + ; GCN: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD3]](p5) :: (dereferenceable load 4 from %ir.out.gep1, addrspace 5) ; GCN: G_STORE [[LOAD]](s8), [[DEF]](p1) :: (volatile store 1 into `i8 addrspace(1)* undef`, addrspace 1) ; GCN: G_STORE [[LOAD1]](s32), [[COPY10]](p1) :: (volatile store 4 into `i32 addrspace(1)* undef`, addrspace 1) ; GCN: S_ENDPGM 0