From c4b6768db4c0a7bfa0ca5e1a704a8cd9b577385b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 25 Apr 2008 18:27:55 +0000 Subject: [PATCH] Remove the code from CodeGenPrepare that moved getresult instructions to the block that defines their operands. This doesn't work in the case that the operand is an invoke, because invoke is a terminator and must be the last instruction in a block. Replace it with support in SelectionDAGISel for copying struct values into sequences of virtual registers. llvm-svn: 50279 --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 239 ++++++++++++------ lib/Transforms/Scalar/CodeGenPrepare.cpp | 9 - ...e-return-values-cross-block-with-invoke.ll | 18 ++ 3 files changed, 174 insertions(+), 92 deletions(-) create mode 100644 test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 73617c0dfa0..22e8ad8ef02 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -90,37 +90,89 @@ namespace { namespace { struct SDISelAsmOperandInfo; } namespace { + /// ComputeValueVTs - Given an LLVM IR type, compute a sequence of + /// MVT::ValueTypes that represent all the individual underlying + /// non-aggregate types that comprise it. + static void ComputeValueVTs(const TargetLowering &TLI, + const Type *Ty, + SmallVectorImpl &ValueVTs) { + // Given a struct type, recursively traverse the elements. + if (const StructType *STy = dyn_cast(Ty)) { + for (StructType::element_iterator EI = STy->element_begin(), + EB = STy->element_end(); + EI != EB; ++EI) + ComputeValueVTs(TLI, *EI, ValueVTs); + return; + } + // Given an array type, recursively traverse the elements. + if (const ArrayType *ATy = dyn_cast(Ty)) { + const Type *EltTy = ATy->getElementType(); + for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) + ComputeValueVTs(TLI, EltTy, ValueVTs); + return; + } + // Base case: we can get an MVT::ValueType for this LLVM IR type. + MVT::ValueType VT = TLI.getValueType(Ty); + ValueVTs.push_back(VT); + } + /// RegsForValue - This struct represents the physical registers that a /// particular value is assigned and the type information about the value. /// This is needed because values can be promoted into larger registers and /// expanded into multiple smaller registers than the value. struct VISIBILITY_HIDDEN RegsForValue { + /// TLI - The TargetLowering object. + const TargetLowering *TLI; + /// Regs - This list holds the register (for legal and promoted values) /// or register set (for expanded values) that the value should be assigned /// to. std::vector Regs; - /// RegVT - The value type of each register. + /// RegVTs - The value types of the registers. This is the same size + /// as ValueVTs; every register contributing to a given value must + /// have the same type. When Regs contains all virtual registers, the + /// contents of RegVTs is redundant with TLI's getRegisterType member + /// function, however when Regs contains physical registers, it is + /// necessary to have a separate record of the types. /// - MVT::ValueType RegVT; + SmallVector RegVTs; - /// ValueVT - The value type of the LLVM value, which may be promoted from - /// RegVT or made from merging the two expanded parts. - MVT::ValueType ValueVT; + /// ValueVTs - The value types of the values, which may be promoted + /// or synthesized from one or more registers. + SmallVector ValueVTs; - RegsForValue() : RegVT(MVT::Other), ValueVT(MVT::Other) {} + RegsForValue() : TLI(0) {} - RegsForValue(unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt) - : RegVT(regvt), ValueVT(valuevt) { - Regs.push_back(Reg); - } - RegsForValue(const std::vector ®s, + RegsForValue(const TargetLowering &tli, + unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt) + : TLI(&tli), Regs(1, Reg), RegVTs(1, regvt), ValueVTs(1, valuevt) {} + RegsForValue(const TargetLowering &tli, + const std::vector ®s, MVT::ValueType regvt, MVT::ValueType valuevt) - : Regs(regs), RegVT(regvt), ValueVT(valuevt) { + : TLI(&tli), Regs(regs), RegVTs(1, regvt), ValueVTs(1, valuevt) {} + RegsForValue(const TargetLowering &tli, + const std::vector ®s, + const SmallVector ®vts, + const SmallVector &valuevts) + : TLI(&tli), Regs(regs), RegVTs(regvts), ValueVTs(valuevts) {} + RegsForValue(const TargetLowering &tli, + unsigned Reg, const Type *Ty) : TLI(&tli) { + ComputeValueVTs(tli, Ty, ValueVTs); + + for (unsigned Value = 0; Value != ValueVTs.size(); ++Value) { + MVT::ValueType ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI->getNumRegisters(ValueVT); + MVT::ValueType RegisterVT = TLI->getRegisterType(ValueVT); + for (unsigned i = 0; i != NumRegs; ++i) + Regs.push_back(Reg + i); + RegVTs.push_back(RegisterVT); + Reg += NumRegs; + } } /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from - /// this value and returns the result as a ValueVT value. This uses + /// this value and returns the result as a ValueVTs value. This uses /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. SDOperand getCopyFromRegs(SelectionDAG &DAG, @@ -310,16 +362,22 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli, /// the correctly promoted or expanded types. Assign these registers /// consecutive vreg numbers and return the first assigned number. unsigned FunctionLoweringInfo::CreateRegForValue(const Value *V) { - MVT::ValueType VT = TLI.getValueType(V->getType()); - - unsigned NumRegisters = TLI.getNumRegisters(VT); - MVT::ValueType RegisterVT = TLI.getRegisterType(VT); + const Type *Ty = V->getType(); + SmallVector ValueVTs; + ComputeValueVTs(TLI, Ty, ValueVTs); - unsigned R = MakeReg(RegisterVT); - for (unsigned i = 1; i != NumRegisters; ++i) - MakeReg(RegisterVT); + unsigned FirstReg = 0; + for (unsigned Value = 0; Value != ValueVTs.size(); ++Value) { + MVT::ValueType ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI.getNumRegisters(ValueVT); + MVT::ValueType RegisterVT = TLI.getRegisterType(ValueVT); - return R; + for (unsigned i = 0; i != NumRegs; ++i) { + unsigned R = MakeReg(RegisterVT); + if (!FirstReg) FirstReg = R; + } + } + return FirstReg; } //===----------------------------------------------------------------------===// @@ -986,7 +1044,7 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) { if (N.Val) return N; const Type *VTy = V->getType(); - MVT::ValueType VT = TLI.getValueType(VTy); + MVT::ValueType VT = TLI.getValueType(VTy, true); if (Constant *C = const_cast(dyn_cast(V))) { if (ConstantExpr *CE = dyn_cast(C)) { visit(CE->getOpcode(), *CE); @@ -1056,14 +1114,7 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) { unsigned InReg = FuncInfo.ValueMap[V]; assert(InReg && "Value not in map!"); - MVT::ValueType RegisterVT = TLI.getRegisterType(VT); - unsigned NumRegs = TLI.getNumRegisters(VT); - - std::vector Regs(NumRegs); - for (unsigned i = 0; i != NumRegs; ++i) - Regs[i] = InReg + i; - - RegsForValue RFV(Regs, RegisterVT, VT); + RegsForValue RFV(TLI, InReg, VTy); SDOperand Chain = DAG.getEntryNode(); return RFV.getCopyFromRegs(DAG, Chain, NULL); @@ -3316,6 +3367,13 @@ void SelectionDAGLowering::visitGetResult(GetResultInst &I) { setValue(&I, Undef); } else { SDOperand Call = getValue(I.getOperand(0)); + + // To add support for individual return values with aggregate types, + // we'd need a way to take a getresult index and determine which + // values of the Call SDNode are associated with it. + assert(TLI.getValueType(I.getType(), true) != MVT::Other && + "Individual return values must not be aggregates!"); + setValue(&I, SDOperand(Call.Val, I.getIndex())); } } @@ -3327,21 +3385,32 @@ void SelectionDAGLowering::visitGetResult(GetResultInst &I) { /// If the Flag pointer is NULL, no flag is used. SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, SDOperand &Chain, SDOperand *Flag)const{ - // Copy the legal parts from the registers. - unsigned NumParts = Regs.size(); - SmallVector Parts(NumParts); - for (unsigned i = 0; i != NumParts; ++i) { - SDOperand Part = Flag ? - DAG.getCopyFromReg(Chain, Regs[i], RegVT, *Flag) : - DAG.getCopyFromReg(Chain, Regs[i], RegVT); - Chain = Part.getValue(1); - if (Flag) - *Flag = Part.getValue(2); - Parts[i] = Part; - } + // Assemble the legal parts into the final values. + SmallVector Values(ValueVTs.size()); + for (unsigned Value = 0, Part = 0; Value != ValueVTs.size(); ++Value) { + // Copy the legal parts from the registers. + MVT::ValueType ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI->getNumRegisters(ValueVT); + MVT::ValueType RegisterVT = RegVTs[Value]; + + SmallVector Parts(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { + SDOperand P = Flag ? + DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT, *Flag) : + DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT); + Chain = P.getValue(1); + if (Flag) + *Flag = P.getValue(2); + Parts[Part+i] = P; + } - // Assemble the legal parts into the final value. - return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT); + Values[Value] = getCopyFromParts(DAG, &Parts[Part], NumRegs, RegisterVT, + ValueVT); + Part += NumRegs; + } + return DAG.getNode(ISD::MERGE_VALUES, + DAG.getVTList(&ValueVTs[0], ValueVTs.size()), + &Values[0], ValueVTs.size()); } /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the @@ -3351,19 +3420,29 @@ SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG, SDOperand &Chain, SDOperand *Flag) const { // Get the list of the values's legal parts. - unsigned NumParts = Regs.size(); - SmallVector Parts(NumParts); - getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT); + unsigned NumRegs = Regs.size(); + SmallVector Parts(NumRegs); + for (unsigned Value = 0, Part = 0; Value != ValueVTs.size(); ++Value) { + MVT::ValueType ValueVT = ValueVTs[Value]; + unsigned NumParts = TLI->getNumRegisters(ValueVT); + MVT::ValueType RegisterVT = RegVTs[Value]; + + getCopyToParts(DAG, Val.getValue(Val.ResNo + Value), + &Parts[Part], NumParts, RegisterVT); + Part += NumParts; + } // Copy the parts into the registers. - for (unsigned i = 0; i != NumParts; ++i) { + SmallVector Chains(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { SDOperand Part = Flag ? DAG.getCopyToReg(Chain, Regs[i], Parts[i], *Flag) : DAG.getCopyToReg(Chain, Regs[i], Parts[i]); - Chain = Part.getValue(0); + Chains[i] = Part.getValue(0); if (Flag) *Flag = Part.getValue(1); } + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs); } /// AddInlineAsmOperands - Add this value to the specified inlineasm node @@ -3373,8 +3452,16 @@ void RegsForValue::AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG, std::vector &Ops) const { MVT::ValueType IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy(); Ops.push_back(DAG.getTargetConstant(Code | (Regs.size() << 3), IntPtrTy)); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) - Ops.push_back(DAG.getRegister(Regs[i], RegVT)); + for (unsigned Value = 0, Reg = 0; Value != ValueVTs.size(); ++Value) { + MVT::ValueType ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI->getNumRegisters(ValueVT); + MVT::ValueType RegisterVT = RegVTs[Value]; + for (unsigned i = 0; i != NumRegs; ++i) { + SDOperand RegOp = DAG.getRegister(Regs[Reg+i], RegisterVT); + Ops.push_back(RegOp); + } + Reg += NumRegs; + } } /// isAllocatableRegister - If the specified register is safe to allocate, @@ -3440,7 +3527,7 @@ struct SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo { /// contains the set of register corresponding to the operand. RegsForValue AssignedRegs; - SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info) + explicit SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info) : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) { } @@ -3558,7 +3645,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, Regs.push_back(*I); } } - OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT); + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT); const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); return; @@ -3587,7 +3674,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, for (; NumRegs; --NumRegs) Regs.push_back(RegInfo.createVirtualRegister(PhysReg.second)); - OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT); + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT); return; } @@ -3637,7 +3724,7 @@ GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber, for (unsigned i = RegStart; i != RegEnd; ++i) Regs.push_back(RegClassRegs[i]); - OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(), + OpInfo.AssignedRegs = RegsForValue(TLI, Regs, *RC->vt_begin(), OpInfo.ConstraintVT); OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); return; @@ -3898,8 +3985,9 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) { if ((NumOps & 7) == 2 /*REGDEF*/) { // Add NumOps>>3 registers to MatchedRegs. RegsForValue MatchedRegs; - MatchedRegs.ValueVT = InOperandVal.getValueType(); - MatchedRegs.RegVT = AsmNodeOperands[CurOp+1].getValueType(); + MatchedRegs.TLI = &TLI; + MatchedRegs.ValueVTs.resize(1, InOperandVal.getValueType()); + MatchedRegs.RegVTs.resize(1, AsmNodeOperands[CurOp+1].getValueType()); for (unsigned i = 0, e = NumOps>>3; i != e; ++i) { unsigned Reg = cast(AsmNodeOperands[++CurOp])->getReg(); @@ -4304,21 +4392,14 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, } // Figure out the result value types. We start by making a list of - // the high-level LLVM return types. - SmallVector LLVMRetTys; - if (const StructType *ST = dyn_cast(RetTy)) - // A struct return type in the LLVM IR means we have multiple return values. - LLVMRetTys.insert(LLVMRetTys.end(), ST->element_begin(), ST->element_end()); - else - LLVMRetTys.push_back(RetTy); - - // Then we translate that to a list of lowered codegen result types. + // the potentially illegal return value types. SmallVector LoweredRetTys; SmallVector RetTys; - for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) { - MVT::ValueType VT = getValueType(LLVMRetTys[I]); - RetTys.push_back(VT); + ComputeValueVTs(*this, RetTy, RetTys); + // Then we translate that to a list of legal types. + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + MVT::ValueType VT = RetTys[I]; MVT::ValueType RegisterVT = getRegisterType(VT); unsigned NumRegs = getNumRegisters(VT); for (unsigned i = 0; i != NumRegs; ++i) @@ -4345,8 +4426,8 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, SmallVector ReturnValues; unsigned RegNo = 0; - for (unsigned I = 0, E = LLVMRetTys.size(); I != E; ++I) { - MVT::ValueType VT = getValueType(LLVMRetTys[I]); + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + MVT::ValueType VT = RetTys[I]; MVT::ValueType RegisterVT = getRegisterType(VT); unsigned NumRegs = getNumRegisters(VT); unsigned RegNoEnd = NumRegs + RegNo; @@ -4441,19 +4522,11 @@ void SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, cast(Op.getOperand(1))->getReg() != Reg) && "Copy from a reg to the same reg!"); assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Is a physreg"); - - MVT::ValueType SrcVT = Op.getValueType(); - MVT::ValueType RegisterVT = TLI.getRegisterType(SrcVT); - unsigned NumRegs = TLI.getNumRegisters(SrcVT); - SmallVector Regs(NumRegs); - SmallVector Chains(NumRegs); - // Copy the value by legal parts into sequential virtual registers. - getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT); - for (unsigned i = 0; i != NumRegs; ++i) - Chains[i] = DAG.getCopyToReg(DAG.getEntryNode(), Reg + i, Regs[i]); - SDOperand Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs); - PendingExports.push_back(Ch); + RegsForValue RFV(TLI, Reg, V->getType()); + SDOperand Chain = DAG.getEntryNode(); + RFV.getCopyToRegs(Op, DAG, Chain, 0); + PendingExports.push_back(Chain); } void SelectionDAGISel:: diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 532af2511e1..4be37a33cf4 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -1127,15 +1127,6 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { // Sink address computing for memory operands into the block. MadeChange |= OptimizeInlineAsmInst(I, &(*CI), SunkAddrs); } - } else if (GetResultInst *GRI = dyn_cast(I)) { - // Ensure that all getresult instructions live in the same basic block - // as their associated struct-value instructions. Codegen requires - // this, as lowering only works on one basic block at a time. - if (Instruction *Agg = dyn_cast(GRI->getAggregateValue())) { - BasicBlock *AggBB = Agg->getParent(); - if (AggBB != GRI->getParent()) - GRI->moveBefore(AggBB->getTerminator()); - } } } diff --git a/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll b/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll new file mode 100644 index 00000000000..f21b645615a --- /dev/null +++ b/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llc + +declare { i64, double } @wild() + +define void @foo(i64* %p, double* %q) nounwind { + %t = invoke { i64, double } @wild() to label %normal unwind label %handler + +normal: + %mrv_gr = getresult { i64, double } %t, 0 + store i64 %mrv_gr, i64* %p + %mrv_gr12681 = getresult { i64, double } %t, 1 + store double %mrv_gr12681, double* %q + ret void + +handler: + ret void +} +