Index: include/llvm/IR/Intrinsics.td =================================================================== --- include/llvm/IR/Intrinsics.td +++ include/llvm/IR/Intrinsics.td @@ -584,6 +584,13 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +// Return from the current function with values in particular hardware +// registers +def int_return_with_registers : Intrinsic<[], + [llvm_vararg_ty], + [], + "llvm.experimental.retwr">; + //===-------------------------- Masked Intrinsics -------------------------===// // def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, Index: include/llvm/Target/TargetLowering.h =================================================================== --- include/llvm/Target/TargetLowering.h +++ include/llvm/Target/TargetLowering.h @@ -2406,6 +2406,16 @@ llvm_unreachable("Not Implemented"); } + /// This hook must be implemented to lower outgoing return values, described + /// by the Outs array, into the specified DAG. The implementation should + /// return the resulting token chain value. + virtual SDValue + LowerReturnWithRegisters(SDValue /*chain*/, + const SmallVectorImpl &/*OutVals*/, + SDLoc /*dl*/, SelectionDAG &/*DAG*/) const { + llvm_unreachable("Not Implemented"); + } + /// Return true if result of the specified node is used by a return node /// only. It also compute and return the input chain for the tail call. /// Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -808,6 +808,8 @@ void visitGCRelocate(const CallInst &I); void visitGCResult(const CallInst &I); + void visitReturnWithRegisters(const CallInst &I); + void visitUserOp1(const Instruction &I) { llvm_unreachable("UserOp1 should not exist at instruction selection time!"); } Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5448,9 +5448,13 @@ return nullptr; } + case Intrinsic::return_with_registers: + visitReturnWithRegisters(I); + return nullptr; case Intrinsic::eh_begincatch: case Intrinsic::eh_endcatch: llvm_unreachable("begin/end catch intrinsics not lowered in codegen"); + } } @@ -7137,6 +7141,37 @@ Attrs); } +void SelectionDAGBuilder::visitReturnWithRegisters(const CallInst &CI) +{ + SDLoc dl = getCurSDLoc(); + unsigned noof_args = CI.getNumArgOperands(); + SDValue chain = getRoot(), glue; + SmallVector values; + LLVMContext &Ctx = *DAG.getContext(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + assert(CI.getType()->isVoidTy() + && "llvm.experimental.retwr cannot return a value."); + for (unsigned i = 0; i < noof_args; i++) { + Attribute attrib = CI.getAttributes().getAttribute(i+1, Attribute::HWReg); + uint64_t regid = attrib.getHWReg(); + ConstantInt *reg_id = + ConstantInt::get(IntegerType::get(Ctx, 64), regid); + assert(reg_id && "Need hwreg for each argument"); + SDValue v = getValue(CI.getArgOperand(i)); + + chain = DAG.getCopyToReg(chain, dl, reg_id->getZExtValue(), v, glue); + glue = chain.getValue(1); + values.push_back(DAG.getRegister(reg_id->getZExtValue(), + TLI.getPointerTy())); + } + + DAG.setRoot(DAG.getTargetLoweringInfo().LowerReturnWithRegisters(chain, + values, + dl, + DAG)); +} + /// TargetLowering::LowerCallTo - This is the default LowerCallTo /// implementation, which just calls LowerCall. /// FIXME: When all targets are