diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index 412cd0a21ad41..6199419077f0c 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -36,6 +36,7 @@ void CallLowering::anchor() {} static void addFlagsUsingAttrFn(ISD::ArgFlagsTy &Flags, const std::function &AttrFn) { + // TODO: There are missing flags. Add them here. if (AttrFn(Attribute::SExt)) Flags.setSExt(); if (AttrFn(Attribute::ZExt)) @@ -743,6 +744,8 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, continue; } + auto AllocaAddressSpace = MF.getDataLayout().getAllocaAddrSpace(); + const MVT ValVT = VA.getValVT(); const MVT LocVT = VA.getLocVT(); @@ -751,6 +754,8 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, const LLT NewLLT = Handler.isIncomingArgumentHandler() ? LocTy : ValTy; const EVT OrigVT = EVT::getEVT(Args[i].Ty); const LLT OrigTy = getLLTForType(*Args[i].Ty, DL); + const LLT PointerTy = LLT::pointer( + AllocaAddressSpace, DL.getPointerSizeInBits(AllocaAddressSpace)); // Expected to be multiple regs for a single incoming arg. // There should be Regs.size() ArgLocs per argument. @@ -765,31 +770,76 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, // intermediate values. Args[i].Regs.resize(NumParts); - // For each split register, create and assign a vreg that will store - // the incoming component of the larger value. These will later be - // merged to form the final vreg. - for (unsigned Part = 0; Part < NumParts; ++Part) - Args[i].Regs[Part] = MRI.createGenericVirtualRegister(NewLLT); + // When we have indirect parameter passing we are receiving a pointer, + // that points to the actual value, so we need one "temporary" pointer. + if (VA.getLocInfo() == CCValAssign::Indirect) { + if (Handler.isIncomingArgumentHandler()) + Args[i].Regs[0] = MRI.createGenericVirtualRegister(PointerTy); + } else { + // For each split register, create and assign a vreg that will store + // the incoming component of the larger value. These will later be + // merged to form the final vreg. + for (unsigned Part = 0; Part < NumParts; ++Part) + Args[i].Regs[Part] = MRI.createGenericVirtualRegister(NewLLT); + } } assert((j + (NumParts - 1)) < ArgLocs.size() && "Too many regs for number of args"); // Coerce into outgoing value types before register assignment. - if (!Handler.isIncomingArgumentHandler() && OrigTy != ValTy) { + if (!Handler.isIncomingArgumentHandler() && OrigTy != ValTy && + VA.getLocInfo() != CCValAssign::Indirect) { assert(Args[i].OrigRegs.size() == 1); buildCopyToRegs(MIRBuilder, Args[i].Regs, Args[i].OrigRegs[0], OrigTy, ValTy, extendOpFromFlags(Args[i].Flags[0])); } + bool IndirectParameterPassingHandled = false; bool BigEndianPartOrdering = TLI->hasBigEndianPartOrdering(OrigVT, DL); for (unsigned Part = 0; Part < NumParts; ++Part) { + assert((VA.getLocInfo() != CCValAssign::Indirect || Part == 0) && + "Only the first parameter should be processed when " + "handling indirect passing!"); Register ArgReg = Args[i].Regs[Part]; // There should be Regs.size() ArgLocs per argument. unsigned Idx = BigEndianPartOrdering ? NumParts - 1 - Part : Part; CCValAssign &VA = ArgLocs[j + Idx]; const ISD::ArgFlagsTy Flags = Args[i].Flags[Part]; + // We found an indirect parameter passing, and we have an + // OutgoingValueHandler as our handler (so we are at the call site or the + // return value). In this case, start the construction of the following + // GMIR, that is responsible for the preparation of indirect parameter + // passing: + // + // %1(indirectly passed type) = The value to pass + // %3(pointer) = G_FRAME_INDEX %stack.0 + // G_STORE %1, %3 :: (store (s128), align 8) + // + // After this GMIR, the remaining part of the loop body will decide how + // to get the value to the caller and we break out of the loop. + if (VA.getLocInfo() == CCValAssign::Indirect && + !Handler.isIncomingArgumentHandler()) { + Align AlignmentForStored = DL.getPrefTypeAlign(Args[i].Ty); + MachineFrameInfo &MFI = MF.getFrameInfo(); + // Get some space on the stack for the value, so later we can pass it + // as a reference. + int FrameIdx = MFI.CreateStackObject(OrigTy.getScalarSizeInBits(), + AlignmentForStored, false); + Register PointerToStackReg = + MIRBuilder.buildFrameIndex(PointerTy, FrameIdx).getReg(0); + MachinePointerInfo StackPointerMPO = + MachinePointerInfo::getFixedStack(MF, FrameIdx); + // Store the value in the previously created stack space. + MIRBuilder.buildStore(Args[i].OrigRegs[Part], PointerToStackReg, + StackPointerMPO, + inferAlignFromPtrInfo(MF, StackPointerMPO)); + + ArgReg = PointerToStackReg; + IndirectParameterPassingHandled = true; + } + if (VA.isMemLoc() && !Flags.isByVal()) { // Individual pieces may have been spilled to the stack and others // passed in registers. @@ -799,14 +849,21 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, LLT MemTy = Handler.getStackValueStoreType(DL, VA, Flags); MachinePointerInfo MPO; - Register StackAddr = Handler.getStackAddress( - MemTy.getSizeInBytes(), VA.getLocMemOffset(), MPO, Flags); - - Handler.assignValueToAddress(Args[i], Part, StackAddr, MemTy, MPO, VA); - continue; - } - - if (VA.isMemLoc() && Flags.isByVal()) { + Register StackAddr = + Handler.getStackAddress(VA.getLocInfo() == CCValAssign::Indirect + ? PointerTy.getSizeInBytes() + : MemTy.getSizeInBytes(), + VA.getLocMemOffset(), MPO, Flags); + + // Finish the handling of indirect passing from the passers + // (OutgoingParameterHandler) side. + // This branch is needed, so the pointer to the value is loaded onto the + // stack. + if (VA.getLocInfo() == CCValAssign::Indirect) + Handler.assignValueToAddress(ArgReg, StackAddr, PointerTy, MPO, VA); + else + Handler.assignValueToAddress(Args[i], Part, StackAddr, MemTy, MPO, VA); + } else if (VA.isMemLoc() && Flags.isByVal()) { assert(Args[i].Regs.size() == 1 && "didn't expect split byval pointer"); @@ -845,30 +902,45 @@ bool CallLowering::handleAssignments(ValueHandler &Handler, DstMPO, DstAlign, SrcMPO, SrcAlign, MemSize, VA); } - continue; - } - - assert(!VA.needsCustom() && "custom loc should have been handled already"); - - if (i == 0 && !ThisReturnRegs.empty() && - Handler.isIncomingArgumentHandler() && - isTypeIsValidForThisReturn(ValVT)) { + } else if (i == 0 && !ThisReturnRegs.empty() && + Handler.isIncomingArgumentHandler() && + isTypeIsValidForThisReturn(ValVT)) { Handler.assignValueToReg(ArgReg, ThisReturnRegs[Part], VA); - continue; - } - - if (Handler.isIncomingArgumentHandler()) + } else if (Handler.isIncomingArgumentHandler()) { Handler.assignValueToReg(ArgReg, VA.getLocReg(), VA); - else { + } else { DelayedOutgoingRegAssignments.emplace_back([=, &Handler]() { Handler.assignValueToReg(ArgReg, VA.getLocReg(), VA); }); } + + // Finish the handling of indirect parameter passing when receiving + // the value (we are in the called function or the caller when receiving + // the return value). + if (VA.getLocInfo() == CCValAssign::Indirect && + Handler.isIncomingArgumentHandler()) { + Align Alignment = DL.getABITypeAlign(Args[i].Ty); + MachinePointerInfo MPO = MachinePointerInfo::getUnknownStack(MF); + + // Since we are doing indirect parameter passing, we know that the value + // in the temporary register is not the value passed to the function, + // but rather a pointer to that value. Let's load that value into the + // virtual register where the parameter should go. + MIRBuilder.buildLoad(Args[i].OrigRegs[0], Args[i].Regs[0], MPO, + Alignment); + + IndirectParameterPassingHandled = true; + } + + if (IndirectParameterPassingHandled) + break; } // Now that all pieces have been assigned, re-pack the register typed values - // into the original value typed registers. - if (Handler.isIncomingArgumentHandler() && OrigVT != LocVT) { + // into the original value typed registers. This is only necessary, when + // the value was passed in multiple registers, not indirectly. + if (Handler.isIncomingArgumentHandler() && OrigVT != LocVT && + !IndirectParameterPassingHandled) { // Merge the split registers into the expected larger result vregs of // the original call. buildCopyFromRegs(MIRBuilder, Args[i].OrigRegs, Args[i].Regs, OrigTy, diff --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp index 2bfee45852b20..b5f8715598f3a 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp @@ -341,10 +341,8 @@ static bool isLegalElementTypeForRVV(Type *EltTy, // TODO: Remove IsLowerArgs argument by adding support for vectors in lowerCall. static bool isSupportedArgumentType(Type *T, const RISCVSubtarget &Subtarget, bool IsLowerArgs = false) { - // TODO: Integers larger than 2*XLen are passed indirectly which is not - // supported yet. if (T->isIntegerTy()) - return T->getIntegerBitWidth() <= Subtarget.getXLen() * 2; + return true; if (T->isHalfTy() || T->isFloatTy() || T->isDoubleTy()) return true; if (T->isPointerTy()) diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-ilp32d-common.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-ilp32d-common.ll index 1a3489521af19..f76b39c26eeed 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-ilp32d-common.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-ilp32-ilp32f-ilp32d-common.ll @@ -83,6 +83,588 @@ define i32 @caller_i64_in_regs() nounwind { ret i32 %1 } +; Check the correct handling of passing of values that are larger that 2*XLen. + +define i64 @callee_128i_indirect_reference_in_stack(i64 %x1, i64 %x2, i64 %x3, i64 %x4, i128 %y, i128 %y2) { + ; RV32I-LABEL: name: callee_128i_indirect_reference_in_stack + ; RV32I: bb.1 (%ir-block.0): + ; RV32I-NEXT: liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; RV32I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; RV32I-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32) + ; RV32I-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $x14 + ; RV32I-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $x15 + ; RV32I-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) + ; RV32I-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY $x16 + ; RV32I-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $x17 + ; RV32I-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32) + ; RV32I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1 + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.1, align 16) + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s128) = G_LOAD [[LOAD]](p0) :: (load (s128), align 8) + ; RV32I-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; RV32I-NEXT: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX1]](p0) :: (load (p0) from %fixed-stack.0) + ; RV32I-NEXT: [[LOAD3:%[0-9]+]]:_(s128) = G_LOAD [[LOAD2]](p0) :: (load (s128), align 8) + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s128) = G_ADD [[LOAD1]], [[LOAD3]] + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[ADD]](s128) + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[TRUNC]](s64) + ; RV32I-NEXT: $x10 = COPY [[UV]](s32) + ; RV32I-NEXT: $x11 = COPY [[UV1]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 + %1 = add i128 %y, %y2 + %2 = trunc i128 %1 to i64 + ret i64 %2 +} + +define i32 @callee_128i_indirect_refernce_in_stack( ) { + ; ILP32-LABEL: name: callee_128i_indirect_refernce_in_stack + ; ILP32: bb.1 (%ir-block.0): + ; ILP32-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32-NEXT: [[C2:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C3]](s32) + ; ILP32-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; ILP32-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32-NEXT: G_STORE [[C2]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C4]](s32) + ; ILP32-NEXT: G_STORE [[FRAME_INDEX1]](p0), [[PTR_ADD1]](p0) :: (store (p0) into stack + 4) + ; ILP32-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32-NEXT: PseudoRET implicit $x10 + ; + ; ILP32F-LABEL: name: callee_128i_indirect_refernce_in_stack + ; ILP32F: bb.1 (%ir-block.0): + ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32F-NEXT: [[C2:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32F-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32F-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32F-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32F-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32F-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32F-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C3]](s32) + ; ILP32F-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; ILP32F-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32F-NEXT: G_STORE [[C2]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32F-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32F-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C4]](s32) + ; ILP32F-NEXT: G_STORE [[FRAME_INDEX1]](p0), [[PTR_ADD1]](p0) :: (store (p0) into stack + 4) + ; ILP32F-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32F-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32F-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32F-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32F-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32F-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32F-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32F-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32F-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32F-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32F-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32F-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32F-NEXT: PseudoRET implicit $x10 + ; + ; ILP32D-LABEL: name: callee_128i_indirect_refernce_in_stack + ; ILP32D: bb.1 (%ir-block.0): + ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32D-NEXT: [[C2:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32D-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32D-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32D-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32D-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32D-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32D-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C3]](s32) + ; ILP32D-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; ILP32D-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32D-NEXT: G_STORE [[C2]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32D-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32D-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C4]](s32) + ; ILP32D-NEXT: G_STORE [[FRAME_INDEX1]](p0), [[PTR_ADD1]](p0) :: (store (p0) into stack + 4) + ; ILP32D-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32D-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32D-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32D-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32D-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32D-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32D-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32D-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32D-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32D-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32D-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32D-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_128i_indirect_reference_in_stack(i64 1,i64 1, i64 1, i64 1, i128 2, i128 42) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + +define i64 @callee_128i_indirect_reference_in_stack_not_first(i64 %x0, i64 %x1, i64 %x2, i64 %x4, i64 %x5, i64 %x6, i64 %x7, i64 %x8, i128 %y ) { + ; RV32I-LABEL: name: callee_128i_indirect_reference_in_stack_not_first + ; RV32I: bb.1 (%ir-block.0): + ; RV32I-NEXT: liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 + ; RV32I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 + ; RV32I-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32) + ; RV32I-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $x14 + ; RV32I-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $x15 + ; RV32I-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) + ; RV32I-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY $x16 + ; RV32I-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $x17 + ; RV32I-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY6]](s32), [[COPY7]](s32) + ; RV32I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.8 + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.8, align 16) + ; RV32I-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.7 + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load (s32) from %fixed-stack.7) + ; RV32I-NEXT: [[MV4:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD]](s32), [[LOAD1]](s32) + ; RV32I-NEXT: [[FRAME_INDEX2:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.6 + ; RV32I-NEXT: [[LOAD2:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX2]](p0) :: (load (s32) from %fixed-stack.6, align 8) + ; RV32I-NEXT: [[FRAME_INDEX3:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.5 + ; RV32I-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX3]](p0) :: (load (s32) from %fixed-stack.5) + ; RV32I-NEXT: [[MV5:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD2]](s32), [[LOAD3]](s32) + ; RV32I-NEXT: [[FRAME_INDEX4:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.4 + ; RV32I-NEXT: [[LOAD4:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX4]](p0) :: (load (s32) from %fixed-stack.4, align 16) + ; RV32I-NEXT: [[FRAME_INDEX5:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.3 + ; RV32I-NEXT: [[LOAD5:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX5]](p0) :: (load (s32) from %fixed-stack.3) + ; RV32I-NEXT: [[MV6:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD4]](s32), [[LOAD5]](s32) + ; RV32I-NEXT: [[FRAME_INDEX6:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.2 + ; RV32I-NEXT: [[LOAD6:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX6]](p0) :: (load (s32) from %fixed-stack.2, align 8) + ; RV32I-NEXT: [[FRAME_INDEX7:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1 + ; RV32I-NEXT: [[LOAD7:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX7]](p0) :: (load (s32) from %fixed-stack.1) + ; RV32I-NEXT: [[MV7:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[LOAD6]](s32), [[LOAD7]](s32) + ; RV32I-NEXT: [[FRAME_INDEX8:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; RV32I-NEXT: [[LOAD8:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX8]](p0) :: (load (p0) from %fixed-stack.0, align 16) + ; RV32I-NEXT: [[LOAD9:%[0-9]+]]:_(s128) = G_LOAD [[LOAD8]](p0) :: (load (s128), align 8) + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[LOAD9]](s128) + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[TRUNC]](s64) + ; RV32I-NEXT: $x10 = COPY [[UV]](s32) + ; RV32I-NEXT: $x11 = COPY [[UV1]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 + %2 = trunc i128 %y to i64 + ret i64 %2 +} + +define i32 @caller_128i_indirect_reference_in_stack_not_first() { + ; ILP32-LABEL: name: caller_128i_indirect_reference_in_stack_not_first + ; ILP32: bb.1 (%ir-block.0): + ; ILP32-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; ILP32-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; ILP32-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; ILP32-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; ILP32-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; ILP32-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; ILP32-NEXT: [[C8:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32-NEXT: ADJCALLSTACKDOWN 36, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64) + ; ILP32-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) + ; ILP32-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64) + ; ILP32-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64) + ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32) + ; ILP32-NEXT: G_STORE [[UV8]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16) + ; ILP32-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C10]](s32) + ; ILP32-NEXT: G_STORE [[UV9]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4) + ; ILP32-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C5]](s64) + ; ILP32-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; ILP32-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C11]](s32) + ; ILP32-NEXT: G_STORE [[UV10]](s32), [[PTR_ADD2]](p0) :: (store (s32) into stack + 8, align 8) + ; ILP32-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 + ; ILP32-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C12]](s32) + ; ILP32-NEXT: G_STORE [[UV11]](s32), [[PTR_ADD3]](p0) :: (store (s32) into stack + 12) + ; ILP32-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64) + ; ILP32-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; ILP32-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32) + ; ILP32-NEXT: G_STORE [[UV12]](s32), [[PTR_ADD4]](p0) :: (store (s32) into stack + 16, align 16) + ; ILP32-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 + ; ILP32-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C14]](s32) + ; ILP32-NEXT: G_STORE [[UV13]](s32), [[PTR_ADD5]](p0) :: (store (s32) into stack + 20) + ; ILP32-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C7]](s64) + ; ILP32-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; ILP32-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C15]](s32) + ; ILP32-NEXT: G_STORE [[UV14]](s32), [[PTR_ADD6]](p0) :: (store (s32) into stack + 24, align 8) + ; ILP32-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 28 + ; ILP32-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C16]](s32) + ; ILP32-NEXT: G_STORE [[UV15]](s32), [[PTR_ADD7]](p0) :: (store (s32) into stack + 28) + ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32-NEXT: G_STORE [[C8]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 + ; ILP32-NEXT: [[PTR_ADD8:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C17]](s32) + ; ILP32-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD8]](p0) :: (store (p0) into stack + 32, align 16) + ; ILP32-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack_not_first, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32-NEXT: ADJCALLSTACKUP 36, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32-NEXT: PseudoRET implicit $x10 + ; + ; ILP32F-LABEL: name: caller_128i_indirect_reference_in_stack_not_first + ; ILP32F: bb.1 (%ir-block.0): + ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32F-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; ILP32F-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; ILP32F-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; ILP32F-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; ILP32F-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; ILP32F-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; ILP32F-NEXT: [[C8:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32F-NEXT: ADJCALLSTACKDOWN 36, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32F-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64) + ; ILP32F-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) + ; ILP32F-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64) + ; ILP32F-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64) + ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32F-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32) + ; ILP32F-NEXT: G_STORE [[UV8]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16) + ; ILP32F-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32F-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C10]](s32) + ; ILP32F-NEXT: G_STORE [[UV9]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4) + ; ILP32F-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C5]](s64) + ; ILP32F-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; ILP32F-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C11]](s32) + ; ILP32F-NEXT: G_STORE [[UV10]](s32), [[PTR_ADD2]](p0) :: (store (s32) into stack + 8, align 8) + ; ILP32F-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 + ; ILP32F-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C12]](s32) + ; ILP32F-NEXT: G_STORE [[UV11]](s32), [[PTR_ADD3]](p0) :: (store (s32) into stack + 12) + ; ILP32F-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64) + ; ILP32F-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; ILP32F-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32) + ; ILP32F-NEXT: G_STORE [[UV12]](s32), [[PTR_ADD4]](p0) :: (store (s32) into stack + 16, align 16) + ; ILP32F-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 + ; ILP32F-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C14]](s32) + ; ILP32F-NEXT: G_STORE [[UV13]](s32), [[PTR_ADD5]](p0) :: (store (s32) into stack + 20) + ; ILP32F-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C7]](s64) + ; ILP32F-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; ILP32F-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C15]](s32) + ; ILP32F-NEXT: G_STORE [[UV14]](s32), [[PTR_ADD6]](p0) :: (store (s32) into stack + 24, align 8) + ; ILP32F-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 28 + ; ILP32F-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C16]](s32) + ; ILP32F-NEXT: G_STORE [[UV15]](s32), [[PTR_ADD7]](p0) :: (store (s32) into stack + 28) + ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32F-NEXT: G_STORE [[C8]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32F-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 + ; ILP32F-NEXT: [[PTR_ADD8:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C17]](s32) + ; ILP32F-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD8]](p0) :: (store (p0) into stack + 32, align 16) + ; ILP32F-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32F-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32F-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32F-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32F-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32F-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32F-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32F-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack_not_first, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32F-NEXT: ADJCALLSTACKUP 36, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32F-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32F-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32F-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32F-NEXT: PseudoRET implicit $x10 + ; + ; ILP32D-LABEL: name: caller_128i_indirect_reference_in_stack_not_first + ; ILP32D: bb.1 (%ir-block.0): + ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; ILP32D-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; ILP32D-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; ILP32D-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; ILP32D-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; ILP32D-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; ILP32D-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; ILP32D-NEXT: [[C8:%[0-9]+]]:_(s128) = G_CONSTANT i128 42 + ; ILP32D-NEXT: ADJCALLSTACKDOWN 36, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) + ; ILP32D-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64) + ; ILP32D-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) + ; ILP32D-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64) + ; ILP32D-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C4]](s64) + ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; ILP32D-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; ILP32D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32) + ; ILP32D-NEXT: G_STORE [[UV8]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16) + ; ILP32D-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; ILP32D-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C10]](s32) + ; ILP32D-NEXT: G_STORE [[UV9]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4) + ; ILP32D-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C5]](s64) + ; ILP32D-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; ILP32D-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C11]](s32) + ; ILP32D-NEXT: G_STORE [[UV10]](s32), [[PTR_ADD2]](p0) :: (store (s32) into stack + 8, align 8) + ; ILP32D-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 + ; ILP32D-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C12]](s32) + ; ILP32D-NEXT: G_STORE [[UV11]](s32), [[PTR_ADD3]](p0) :: (store (s32) into stack + 12) + ; ILP32D-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64) + ; ILP32D-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; ILP32D-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C13]](s32) + ; ILP32D-NEXT: G_STORE [[UV12]](s32), [[PTR_ADD4]](p0) :: (store (s32) into stack + 16, align 16) + ; ILP32D-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 20 + ; ILP32D-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C14]](s32) + ; ILP32D-NEXT: G_STORE [[UV13]](s32), [[PTR_ADD5]](p0) :: (store (s32) into stack + 20) + ; ILP32D-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C7]](s64) + ; ILP32D-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; ILP32D-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C15]](s32) + ; ILP32D-NEXT: G_STORE [[UV14]](s32), [[PTR_ADD6]](p0) :: (store (s32) into stack + 24, align 8) + ; ILP32D-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 28 + ; ILP32D-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C16]](s32) + ; ILP32D-NEXT: G_STORE [[UV15]](s32), [[PTR_ADD7]](p0) :: (store (s32) into stack + 28) + ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32D-NEXT: G_STORE [[C8]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32D-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 + ; ILP32D-NEXT: [[PTR_ADD8:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C17]](s32) + ; ILP32D-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD8]](p0) :: (store (p0) into stack + 32, align 16) + ; ILP32D-NEXT: $x10 = COPY [[UV]](s32) + ; ILP32D-NEXT: $x11 = COPY [[UV1]](s32) + ; ILP32D-NEXT: $x12 = COPY [[UV2]](s32) + ; ILP32D-NEXT: $x13 = COPY [[UV3]](s32) + ; ILP32D-NEXT: $x14 = COPY [[UV4]](s32) + ; ILP32D-NEXT: $x15 = COPY [[UV5]](s32) + ; ILP32D-NEXT: $x16 = COPY [[UV6]](s32) + ; ILP32D-NEXT: $x17 = COPY [[UV7]](s32) + ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_stack_not_first, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10, implicit-def $x11 + ; ILP32D-NEXT: ADJCALLSTACKUP 36, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32D-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32D-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) + ; ILP32D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32D-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_128i_indirect_reference_in_stack_not_first(i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i128 42) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + + +define i64 @callee_128i_indirect_reference_in_regs(i128 %x, i128 %y ) { + ; RV32I-LABEL: name: callee_128i_indirect_reference_in_regs + ; RV32I: bb.1 (%ir-block.0): + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s128) = G_LOAD [[COPY]](p0) :: (load (s128), align 8) + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s128) = G_LOAD [[COPY1]](p0) :: (load (s128), align 8) + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s128) = G_ADD [[LOAD]], [[LOAD1]] + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[LOAD]](s128) + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[TRUNC]](s64) + ; RV32I-NEXT: $x10 = COPY [[UV]](s32) + ; RV32I-NEXT: $x11 = COPY [[UV1]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 + %1 = add i128 %x, %y + %2 = trunc i128 %x to i64 + ret i64 %2 +} + +define i32 @caller_128i_indirect_reference_in_regs( ) { + ; ILP32-LABEL: name: caller_128i_indirect_reference_in_regs + ; ILP32: bb.1 (%ir-block.0): + ; ILP32-NEXT: [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 1 + ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32-NEXT: G_STORE [[C]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_regs, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32-NEXT: PseudoRET implicit $x10 + ; + ; ILP32F-LABEL: name: caller_128i_indirect_reference_in_regs + ; ILP32F: bb.1 (%ir-block.0): + ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 1 + ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32F-NEXT: G_STORE [[C]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32F-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32F-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32F-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_regs, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32F-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32F-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32F-NEXT: PseudoRET implicit $x10 + ; + ; ILP32D-LABEL: name: caller_128i_indirect_reference_in_regs + ; ILP32D: bb.1 (%ir-block.0): + ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 1 + ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s128) = G_CONSTANT i128 2 + ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32D-NEXT: G_STORE [[C]](s128), [[FRAME_INDEX]](p0) :: (store (s128) into %stack.0, align 8) + ; ILP32D-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32D-NEXT: G_STORE [[C1]](s128), [[FRAME_INDEX1]](p0) :: (store (s128) into %stack.1, align 8) + ; ILP32D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32D-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_128i_indirect_reference_in_regs, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32D-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32D-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_128i_indirect_reference_in_regs(i128 1, i128 2) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + +define i64 @callee_256i_indirect_reference_in_regs(i256 %x, i256 %y ) { + + ; RV32I-LABEL: name: callee_256i_indirect_reference_in_regs + ; RV32I: bb.1 (%ir-block.0): + ; RV32I-NEXT: liveins: $x10, $x11 + ; RV32I-NEXT: {{ $}} + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s256) = G_LOAD [[COPY]](p0) :: (load (s256), align 8) + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s256) = G_LOAD [[COPY1]](p0) :: (load (s256), align 8) + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s256) = G_ADD [[LOAD]], [[LOAD1]] + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[LOAD]](s256) + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[TRUNC]](s64) + ; RV32I-NEXT: $x10 = COPY [[UV]](s32) + ; RV32I-NEXT: $x11 = COPY [[UV1]](s32) + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 + %1 = add i256 %x, %y + %2 = trunc i256 %x to i64 + ret i64 %2 +} + +define i32 @caller_256i_indirect_reference_in_regs( ) { + ; ILP32-LABEL: name: caller_256i_indirect_reference_in_regs + ; ILP32: bb.1 (%ir-block.0): + ; ILP32-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 8) + ; ILP32-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 8) + ; ILP32-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_256i_indirect_reference_in_regs, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32-NEXT: PseudoRET implicit $x10 + ; + ; ILP32F-LABEL: name: caller_256i_indirect_reference_in_regs + ; ILP32F: bb.1 (%ir-block.0): + ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32F-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 8) + ; ILP32F-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32F-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 8) + ; ILP32F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32F-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_256i_indirect_reference_in_regs, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32F-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32F-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32F-NEXT: PseudoRET implicit $x10 + ; + ; ILP32D-LABEL: name: caller_256i_indirect_reference_in_regs + ; ILP32D: bb.1 (%ir-block.0): + ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; ILP32D-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 8) + ; ILP32D-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; ILP32D-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 8) + ; ILP32D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; ILP32D-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_256i_indirect_reference_in_regs, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10, implicit-def $x11 + ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 + ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 + ; ILP32D-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) + ; ILP32D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) + ; ILP32D-NEXT: $x10 = COPY [[TRUNC]](s32) + ; ILP32D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_256i_indirect_reference_in_regs(i256 1, i256 2) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + ; Check that the stack is used once the GPRs are exhausted define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind { diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-lp64d-common.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-lp64d-common.ll index b175b8d92e6c9..43efede1aef1e 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-lp64d-common.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/calling-conv-lp64-lp64f-lp64d-common.ll @@ -83,6 +83,220 @@ define i64 @caller_i128_in_regs() nounwind { ret i64 %1 } +; Check the correct handling of passing of values that are larger that 2*XLen. + +define i32 @caller_i256_indirect_reference_in_stack() { + ; LP64-LABEL: name: caller_i256_indirect_reference_in_stack + ; LP64: bb.1 (%ir-block.0): + ; LP64-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; LP64-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; LP64-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; LP64-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; LP64-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; LP64-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; LP64-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; LP64-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 + ; LP64-NEXT: [[C8:%[0-9]+]]:_(s256) = G_CONSTANT i256 42 + ; LP64-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; LP64-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64-NEXT: G_STORE [[C8]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; LP64-NEXT: [[C9:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; LP64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s64) + ; LP64-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; LP64-NEXT: $x10 = COPY [[C]](s64) + ; LP64-NEXT: $x11 = COPY [[C1]](s64) + ; LP64-NEXT: $x12 = COPY [[C2]](s64) + ; LP64-NEXT: $x13 = COPY [[C3]](s64) + ; LP64-NEXT: $x14 = COPY [[C4]](s64) + ; LP64-NEXT: $x15 = COPY [[C5]](s64) + ; LP64-NEXT: $x16 = COPY [[C6]](s64) + ; LP64-NEXT: $x17 = COPY [[C7]](s64) + ; LP64-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_stack, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10 + ; LP64-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; LP64-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; LP64-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64-NEXT: PseudoRET implicit $x10 + ; + ; LP64F-LABEL: name: caller_i256_indirect_reference_in_stack + ; LP64F: bb.1 (%ir-block.0): + ; LP64F-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; LP64F-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; LP64F-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; LP64F-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; LP64F-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; LP64F-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; LP64F-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; LP64F-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 + ; LP64F-NEXT: [[C8:%[0-9]+]]:_(s256) = G_CONSTANT i256 42 + ; LP64F-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; LP64F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64F-NEXT: G_STORE [[C8]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64F-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; LP64F-NEXT: [[C9:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; LP64F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s64) + ; LP64F-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; LP64F-NEXT: $x10 = COPY [[C]](s64) + ; LP64F-NEXT: $x11 = COPY [[C1]](s64) + ; LP64F-NEXT: $x12 = COPY [[C2]](s64) + ; LP64F-NEXT: $x13 = COPY [[C3]](s64) + ; LP64F-NEXT: $x14 = COPY [[C4]](s64) + ; LP64F-NEXT: $x15 = COPY [[C5]](s64) + ; LP64F-NEXT: $x16 = COPY [[C6]](s64) + ; LP64F-NEXT: $x17 = COPY [[C7]](s64) + ; LP64F-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_stack, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10 + ; LP64F-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; LP64F-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; LP64F-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64F-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64F-NEXT: PseudoRET implicit $x10 + ; + ; LP64D-LABEL: name: caller_i256_indirect_reference_in_stack + ; LP64D: bb.1 (%ir-block.0): + ; LP64D-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; LP64D-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; LP64D-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; LP64D-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 + ; LP64D-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; LP64D-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 6 + ; LP64D-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 + ; LP64D-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 + ; LP64D-NEXT: [[C8:%[0-9]+]]:_(s256) = G_CONSTANT i256 42 + ; LP64D-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2 + ; LP64D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64D-NEXT: G_STORE [[C8]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64D-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 + ; LP64D-NEXT: [[C9:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; LP64D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s64) + ; LP64D-NEXT: G_STORE [[FRAME_INDEX]](p0), [[PTR_ADD]](p0) :: (store (p0) into stack, align 16) + ; LP64D-NEXT: $x10 = COPY [[C]](s64) + ; LP64D-NEXT: $x11 = COPY [[C1]](s64) + ; LP64D-NEXT: $x12 = COPY [[C2]](s64) + ; LP64D-NEXT: $x13 = COPY [[C3]](s64) + ; LP64D-NEXT: $x14 = COPY [[C4]](s64) + ; LP64D-NEXT: $x15 = COPY [[C5]](s64) + ; LP64D-NEXT: $x16 = COPY [[C6]](s64) + ; LP64D-NEXT: $x17 = COPY [[C7]](s64) + ; LP64D-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_stack, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10 + ; LP64D-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2 + ; LP64D-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY1]](s64) + ; LP64D-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64D-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_i256_indirect_reference_in_stack(i64 1, i64 2, i64 3, i64 4,i64 5,i64 6,i64 7,i64 8, i256 42) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + + +define i64 @callee_i256_indirect_reference_in_stack(i64 %x1, i64 %x2, i64 %x3, i64 %x4, i64 %x5, i64 %x6, i64 %x7, i64 %x8, i256 %y) { + ; RV64I-LABEL: name: callee_i256_indirect_reference_in_stack + ; RV64I: bb.1 (%ir-block.0): + ; RV64I-NEXT: liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 + ; RV64I-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $x12 + ; RV64I-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY $x13 + ; RV64I-NEXT: [[COPY4:%[0-9]+]]:_(s64) = COPY $x14 + ; RV64I-NEXT: [[COPY5:%[0-9]+]]:_(s64) = COPY $x15 + ; RV64I-NEXT: [[COPY6:%[0-9]+]]:_(s64) = COPY $x16 + ; RV64I-NEXT: [[COPY7:%[0-9]+]]:_(s64) = COPY $x17 + ; RV64I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 + ; RV64I-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[FRAME_INDEX]](p0) :: (load (p0) from %fixed-stack.0, align 16) + ; RV64I-NEXT: [[LOAD1:%[0-9]+]]:_(s256) = G_LOAD [[LOAD]](p0) :: (load (s256), align 16) + ; RV64I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[LOAD1]](s256) + ; RV64I-NEXT: $x10 = COPY [[TRUNC]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %2 = trunc i256 %y to i64 + ret i64 %2 +} + + +define i64 @callee_i256_indirect_reference_in_reg(i256 %x, i256 %y) { + ; RV64I-LABEL: name: callee_i256_indirect_reference_in_reg + ; RV64I: bb.1 (%ir-block.0): + ; RV64I-NEXT: liveins: $x10, $x11 + ; RV64I-NEXT: {{ $}} + ; RV64I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64I-NEXT: [[LOAD:%[0-9]+]]:_(s256) = G_LOAD [[COPY]](p0) :: (load (s256), align 16) + ; RV64I-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 + ; RV64I-NEXT: [[LOAD1:%[0-9]+]]:_(s256) = G_LOAD [[COPY1]](p0) :: (load (s256), align 16) + ; RV64I-NEXT: [[ADD:%[0-9]+]]:_(s256) = G_ADD [[LOAD]], [[LOAD1]] + ; RV64I-NEXT: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[ADD]](s256) + ; RV64I-NEXT: $x10 = COPY [[TRUNC]](s64) + ; RV64I-NEXT: PseudoRET implicit $x10 + %1 = add i256 %x, %y + %2 = trunc i256 %1 to i64 + ret i64 %2 +} + +define i32 @caller_i256_indirect_reference_in_reg() { + ; LP64-LABEL: name: caller_i256_indirect_reference_in_reg + ; LP64: bb.1 (%ir-block.0): + ; LP64-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; LP64-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; LP64-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; LP64-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; LP64-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 16) + ; LP64-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; LP64-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; LP64-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_reg, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; LP64-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; LP64-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; LP64-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64-NEXT: PseudoRET implicit $x10 + ; + ; LP64F-LABEL: name: caller_i256_indirect_reference_in_reg + ; LP64F: bb.1 (%ir-block.0): + ; LP64F-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; LP64F-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; LP64F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; LP64F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64F-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64F-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; LP64F-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 16) + ; LP64F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; LP64F-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; LP64F-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_reg, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; LP64F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; LP64F-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64F-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; LP64F-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64F-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64F-NEXT: PseudoRET implicit $x10 + ; + ; LP64D-LABEL: name: caller_i256_indirect_reference_in_reg + ; LP64D: bb.1 (%ir-block.0): + ; LP64D-NEXT: [[C:%[0-9]+]]:_(s256) = G_CONSTANT i256 1 + ; LP64D-NEXT: [[C1:%[0-9]+]]:_(s256) = G_CONSTANT i256 2 + ; LP64D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2 + ; LP64D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 + ; LP64D-NEXT: G_STORE [[C]](s256), [[FRAME_INDEX]](p0) :: (store (s256) into %stack.0, align 16) + ; LP64D-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1 + ; LP64D-NEXT: G_STORE [[C1]](s256), [[FRAME_INDEX1]](p0) :: (store (s256) into %stack.1, align 16) + ; LP64D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) + ; LP64D-NEXT: $x11 = COPY [[FRAME_INDEX1]](p0) + ; LP64D-NEXT: PseudoCALL target-flags(riscv-call) @callee_i256_indirect_reference_in_reg, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit-def $x10 + ; LP64D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2 + ; LP64D-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x10 + ; LP64D-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; LP64D-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]](s32) + ; LP64D-NEXT: $x10 = COPY [[ANYEXT]](s64) + ; LP64D-NEXT: PseudoRET implicit $x10 + %1 = call i64 @callee_i256_indirect_reference_in_reg(i256 1, i256 2) + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + ; Check that the stack is used once the GPRs are exhausted define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i128 %d, i32 %e, i32 %f, i128 %g, i32 %h) nounwind {