Index: llvm/trunk/lib/Target/Mips/MipsCallLowering.h =================================================================== --- llvm/trunk/lib/Target/Mips/MipsCallLowering.h +++ llvm/trunk/lib/Target/Mips/MipsCallLowering.h @@ -32,20 +32,19 @@ virtual ~MipsHandler() = default; protected: - bool assign(const CCValAssign &VA, unsigned vreg); + bool assign(unsigned VReg, const CCValAssign &VA); MachineIRBuilder &MIRBuilder; MachineRegisterInfo &MRI; private: - virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) = 0; + virtual unsigned getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) = 0; - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) = 0; + virtual void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) = 0; - virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, - uint64_t Size, - MachinePointerInfo &MPO) = 0; + virtual void assignValueToAddress(unsigned ValVReg, + const CCValAssign &VA) = 0; }; MipsCallLowering(const MipsTargetLowering &TLI); Index: llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp +++ llvm/trunk/lib/Target/Mips/MipsCallLowering.cpp @@ -24,16 +24,12 @@ MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) : CallLowering(&TLI) {} -bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, - unsigned vreg) { +bool MipsCallLowering::MipsHandler::assign(unsigned VReg, + const CCValAssign &VA) { if (VA.isRegLoc()) { - assignValueToReg(vreg, VA.getLocReg()); + assignValueToReg(VReg, VA); } else if (VA.isMemLoc()) { - unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; - unsigned Offset = VA.getLocMemOffset(); - MachinePointerInfo MPO; - unsigned StackAddr = getStackAddress(Size, Offset, MPO); - assignValueToAddress(vreg, StackAddr, Size, MPO); + assignValueToAddress(VReg, VA); } else { return false; } @@ -50,22 +46,20 @@ ArrayRef Args); private: - void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; - unsigned getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) override; + unsigned getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) override; - void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, - MachinePointerInfo &MPO) override; + void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; virtual void markPhysRegUsed(unsigned PhysReg) { MIRBuilder.getMBB().addLiveIn(PhysReg); } - void buildLoad(unsigned Val, unsigned Addr, uint64_t Size, unsigned Alignment, - MachinePointerInfo &MPO) { - MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( - MPO, MachineMemOperand::MOLoad, Size, Alignment); + void buildLoad(unsigned Val, const CCValAssign &VA) { + MachineMemOperand *MMO; + unsigned Addr = getStackAddress(VA, MMO); MIRBuilder.buildLoad(Val, Addr, *MMO); } }; @@ -87,17 +81,34 @@ } // end anonymous namespace void IncomingValueHandler::assignValueToReg(unsigned ValVReg, - unsigned PhysReg) { - MIRBuilder.buildCopy(ValVReg, PhysReg); + const CCValAssign &VA) { + unsigned PhysReg = VA.getLocReg(); + switch (VA.getLocInfo()) { + case CCValAssign::LocInfo::SExt: + case CCValAssign::LocInfo::ZExt: + case CCValAssign::LocInfo::AExt: { + auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); + MIRBuilder.buildTrunc(ValVReg, Copy); + break; + } + default: + MIRBuilder.buildCopy(ValVReg, PhysReg); + break; + } markPhysRegUsed(PhysReg); } -unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) { +unsigned IncomingValueHandler::getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) { + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + unsigned Offset = VA.getLocMemOffset(); MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); int FI = MFI.CreateFixedObject(Size, Offset, true); - MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + MachinePointerInfo MPO = + MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOLoad, + Size, /* Alignment */ 0); unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); MIRBuilder.buildFrameIndex(AddrReg, FI); @@ -105,17 +116,22 @@ return AddrReg; } -void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, - uint64_t Size, - MachinePointerInfo &MPO) { - // If the value is not extended, a simple load will suffice. - buildLoad(ValVReg, Addr, Size, /* Alignment */ 0, MPO); +void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, + const CCValAssign &VA) { + if (VA.getLocInfo() == CCValAssign::SExt || + VA.getLocInfo() == CCValAssign::ZExt || + VA.getLocInfo() == CCValAssign::AExt) { + unsigned LoadReg = MRI.createGenericVirtualRegister(LLT::scalar(32)); + buildLoad(LoadReg, VA); + MIRBuilder.buildTrunc(ValVReg, LoadReg); + } else + buildLoad(ValVReg, VA); } bool IncomingValueHandler::handle(ArrayRef ArgLocs, ArrayRef Args) { for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { - if (!assign(ArgLocs[i], Args[i].Reg)) + if (!assign(Args[i].Reg, ArgLocs[i])) return false; } return true; @@ -132,69 +148,134 @@ ArrayRef Args); private: - void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + void assignValueToReg(unsigned ValVReg, const CCValAssign &VA) override; + + unsigned getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) override; - unsigned getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) override; + void assignValueToAddress(unsigned ValVReg, const CCValAssign &VA) override; - void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, - MachinePointerInfo &MPO) override; + unsigned extendRegister(unsigned ValReg, const CCValAssign &VA); MachineInstrBuilder &MIB; }; } // end anonymous namespace void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, - unsigned PhysReg) { - MIRBuilder.buildCopy(PhysReg, ValVReg); + const CCValAssign &VA) { + unsigned PhysReg = VA.getLocReg(); + unsigned ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); } -unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, - MachinePointerInfo &MPO) { +unsigned OutgoingValueHandler::getStackAddress(const CCValAssign &VA, + MachineMemOperand *&MMO) { LLT p0 = LLT::pointer(0, 32); LLT s32 = LLT::scalar(32); unsigned SPReg = MRI.createGenericVirtualRegister(p0); MIRBuilder.buildCopy(SPReg, Mips::SP); unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); + unsigned Offset = VA.getLocMemOffset(); MIRBuilder.buildConstant(OffsetReg, Offset); unsigned AddrReg = MRI.createGenericVirtualRegister(p0); MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); - MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + MachinePointerInfo MPO = + MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + MMO = MIRBuilder.getMF().getMachineMemOperand(MPO, MachineMemOperand::MOStore, + Size, /* Alignment */ 0); + return AddrReg; } -void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, - uint64_t Size, - MachinePointerInfo &MPO) { - MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( - MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0); - MIRBuilder.buildStore(ValVReg, Addr, *MMO); +void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, + const CCValAssign &VA) { + MachineMemOperand *MMO; + unsigned Addr = getStackAddress(VA, MMO); + unsigned ExtReg = extendRegister(ValVReg, VA); + MIRBuilder.buildStore(ExtReg, Addr, *MMO); +} + +unsigned OutgoingValueHandler::extendRegister(unsigned ValReg, + const CCValAssign &VA) { + LLT LocTy{VA.getLocVT()}; + switch (VA.getLocInfo()) { + case CCValAssign::SExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildSExt(ExtReg, ValReg); + return ExtReg; + } + case CCValAssign::ZExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildZExt(ExtReg, ValReg); + return ExtReg; + } + case CCValAssign::AExt: { + unsigned ExtReg = MRI.createGenericVirtualRegister(LocTy); + MIRBuilder.buildAnyExt(ExtReg, ValReg); + return ExtReg; + } + // TODO : handle upper extends + case CCValAssign::Full: + return ValReg; + default: + break; + } + llvm_unreachable("unable to extend register"); } bool OutgoingValueHandler::handle(ArrayRef ArgLocs, ArrayRef Args) { for (unsigned i = 0; i < Args.size(); ++i) { - if (!assign(ArgLocs[i], Args[i].Reg)) + if (!assign(Args[i].Reg, ArgLocs[i])) return false; } return true; } static bool isSupportedType(Type *T) { - if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) + if (T->isIntegerTy() && T->getScalarSizeInBits() <= 32) return true; if (T->isPointerTy()) return true; return false; } +CCValAssign::LocInfo determineLocInfo(const MVT RegisterVT, const EVT VT, + const ISD::ArgFlagsTy &Flags) { + if (VT.getSizeInBits() == RegisterVT.getSizeInBits()) + return CCValAssign::LocInfo::Full; + if (Flags.isSExt()) + return CCValAssign::LocInfo::SExt; + if (Flags.isZExt()) + return CCValAssign::LocInfo::ZExt; + return CCValAssign::LocInfo::AExt; +} + +template +void setLocInfo(SmallVectorImpl &ArgLocs, + const SmallVectorImpl &Arguments) { + for (unsigned i = 0; i < ArgLocs.size(); ++i) { + const CCValAssign &VA = ArgLocs[i]; + CCValAssign::LocInfo LocInfo = determineLocInfo( + Arguments[i].VT, Arguments[i].ArgVT, Arguments[i].Flags); + if (VA.isMemLoc()) + ArgLocs[i] = + CCValAssign::getMem(VA.getValNo(), VA.getValVT(), + VA.getLocMemOffset(), VA.getLocVT(), LocInfo); + else + ArgLocs[i] = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), + VA.getLocReg(), VA.getLocVT(), LocInfo); + } +} + bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, - const Value *Val, - ArrayRef VRegs) const { + const Value *Val, + ArrayRef VRegs) const { MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); @@ -234,6 +315,7 @@ MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); + setLocInfo(ArgLocs, Outs); OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); if (!RetHandler.handle(ArgLocs, RetInfos)) { @@ -293,6 +375,7 @@ CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), 1); CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); + setLocInfo(ArgLocs, Ins); IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); if (!Handler.handle(ArgLocs, ArgInfos)) @@ -371,6 +454,7 @@ CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); + setLocInfo(ArgLocs, Outs); OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); if (!RetHandler.handle(ArgLocs, ArgInfos)) { @@ -405,6 +489,7 @@ F.getContext()); CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); + setLocInfo(ArgLocs, Ins); CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); if (!Handler.handle(ArgLocs, ArgInfos)) Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/irtranslator/extend_args.ll @@ -0,0 +1,288 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 + + +define signext i8 @sext_arg_i8(i8 signext %a) { + ; MIPS32-LABEL: name: sext_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s8) + ; MIPS32: $v0 = COPY [[SEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i8 %a +} + +define zeroext i8 @zext_arg_i8(i8 zeroext %a) { + ; MIPS32-LABEL: name: zext_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) + ; MIPS32: $v0 = COPY [[ZEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i8 %a +} + +define i8 @aext_arg_i8(i8 %a) { + ; MIPS32-LABEL: name: aext_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s8) + ; MIPS32: $v0 = COPY [[ANYEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i8 %a +} + +declare signext i8 @sext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 %a) +declare zeroext i8 @zext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 %a) +declare i8 @aext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 %a) + +define signext i8 @call_sext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 signext %a) { + ; MIPS32-LABEL: name: call_sext_stack_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s8) + ; MIPS32: G_STORE [[SEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @sext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC1]](s8) + ; MIPS32: $v0 = COPY [[SEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call signext i8 @sext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 signext %a) + ret i8 %call +} + +define zeroext i8 @call_zext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 zeroext %a) { + ; MIPS32-LABEL: name: call_zext_stack_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) + ; MIPS32: G_STORE [[ZEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @zext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s8) + ; MIPS32: $v0 = COPY [[ZEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call zeroext i8 @zext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 zeroext %a) + ret i8 %call +} + +define i8 @call_aext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 %a) { + ; MIPS32-LABEL: name: call_aext_stack_arg_i8 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s8) + ; MIPS32: G_STORE [[ANYEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @aext_stack_arg_i8, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC1]](s8) + ; MIPS32: $v0 = COPY [[ANYEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call i8 @aext_stack_arg_i8(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i8 %a) + ret i8 %call +} + + +define signext i16 @sext_arg_i16(i16 signext %a) { + ; MIPS32-LABEL: name: sext_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16) + ; MIPS32: $v0 = COPY [[SEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i16 %a +} + +define zeroext i16 @zext_arg_i16(i16 zeroext %a) { + ; MIPS32-LABEL: name: zext_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) + ; MIPS32: $v0 = COPY [[ZEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i16 %a +} + +define i16 @aext_arg_i16(i16 %a) { + ; MIPS32-LABEL: name: aext_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) + ; MIPS32: $v0 = COPY [[ANYEXT]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + ret i16 %a +} + +declare signext i16 @sext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 %a) +declare zeroext i16 @zext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 %a) +declare i16 @aext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 %a) + +define signext i16 @call_sext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 signext %a) { + ; MIPS32-LABEL: name: call_sext_stack_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16) + ; MIPS32: G_STORE [[SEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @sext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC1]](s16) + ; MIPS32: $v0 = COPY [[SEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call signext i16 @sext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 signext %a) + ret i16 %call +} + +define zeroext i16 @call_zext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 zeroext %a) { + ; MIPS32-LABEL: name: call_zext_stack_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) + ; MIPS32: G_STORE [[ZEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @zext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s16) + ; MIPS32: $v0 = COPY [[ZEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call zeroext i16 @zext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 zeroext %a) + ret i16 %call +} + +define i16 @call_aext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 %a) { + ; MIPS32-LABEL: name: call_aext_stack_arg_i16 + ; MIPS32: bb.1.entry: + ; MIPS32: liveins: $a0, $a1, $a2, $a3 + ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2 + ; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 + ; MIPS32: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; MIPS32: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load 4 from %fixed-stack.0, align 0) + ; MIPS32: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[LOAD]](s32) + ; MIPS32: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: $a0 = COPY [[COPY]](s32) + ; MIPS32: $a1 = COPY [[COPY1]](s32) + ; MIPS32: $a2 = COPY [[COPY2]](s32) + ; MIPS32: $a3 = COPY [[COPY3]](s32) + ; MIPS32: [[COPY4:%[0-9]+]]:_(p0) = COPY $sp + ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; MIPS32: [[GEP:%[0-9]+]]:_(p0) = G_GEP [[COPY4]], [[C]](s32) + ; MIPS32: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) + ; MIPS32: G_STORE [[ANYEXT]](s32), [[GEP]](p0) :: (store 4 into stack + 16, align 0) + ; MIPS32: JAL @aext_stack_arg_i16, csr_o32, implicit-def $ra, implicit-def $sp, implicit $a0, implicit $a1, implicit $a2, implicit $a3, implicit-def $v0 + ; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY $v0 + ; MIPS32: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY5]](s32) + ; MIPS32: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp + ; MIPS32: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC1]](s16) + ; MIPS32: $v0 = COPY [[ANYEXT1]](s32) + ; MIPS32: RetRA implicit $v0 +entry: + %call = call i16 @aext_stack_arg_i16(i32 %x1, i32 %x2, i32 %x3, i32 %x4, i16 %a) + ret i16 %call +}