aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-01-31 02:03:41 +0000
committerChris Lattner <sabre@nondot.org>2006-01-31 02:03:41 +0000
commit6656dd1a7888e6dabc82ebce734734127b1df6a7 (patch)
treefdf0a15fb83d43f440315b1881827cbe1c80c5a2 /lib/CodeGen
parent594086d494e5282d8f8b665efe5af2170f83c653 (diff)
Handle physreg input/outputs. We now compile this:
int %test_cpuid(int %op) { %B = alloca int %C = alloca int %D = alloca int %A = call int asm "cpuid", "=eax,==ebx,==ecx,==edx,eax"(int* %B, int* %C, int* %D, int %op) %Bv = load int* %B %Cv = load int* %C %Dv = load int* %D %x = add int %A, %Bv %y = add int %x, %Cv %z = add int %y, %Dv ret int %z } to this: _test_cpuid: sub %ESP, 16 mov DWORD PTR [%ESP], %EBX mov %EAX, DWORD PTR [%ESP + 20] cpuid mov DWORD PTR [%ESP + 8], %ECX mov DWORD PTR [%ESP + 12], %EBX mov DWORD PTR [%ESP + 4], %EDX mov %ECX, DWORD PTR [%ESP + 12] add %EAX, %ECX mov %ECX, DWORD PTR [%ESP + 8] add %EAX, %ECX mov %ECX, DWORD PTR [%ESP + 4] add %EAX, %ECX mov %EBX, DWORD PTR [%ESP] add %ESP, 16 ret ... note the proper register allocation. :) it is unclear to me why the loads aren't folded into the adds. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25827 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAG.cpp2
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp99
2 files changed, 97 insertions, 4 deletions
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
index 4e45bd6564..9f285d5c9c 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
@@ -300,7 +300,7 @@ void ScheduleDAG::EmitNode(NodeInfo *NI) {
// Add all of the operand registers to the instruction.
for (unsigned i = 2; i != NumOps; i += 2) {
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
- unsigned Flags = cast<ConstantSDNode>(Node->getOperand(i))->getValue();
+ unsigned Flags =cast<ConstantSDNode>(Node->getOperand(i+1))->getValue();
MachineOperand::UseType UseTy;
switch (Flags) {
default: assert(0 && "Bad flags!");
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 78db4554da..32fff90e96 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1158,7 +1158,6 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
std::vector<std::pair<InlineAsm::ConstraintPrefix, std::string> >
Constraints = IA->ParseConstraints();
-
/// AsmNodeOperands - A list of pairs. The first element is a register, the
/// second is a bitfield where bit #0 is set if it is a use and bit #1 is set
@@ -1170,7 +1169,69 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
SDOperand Chain = getRoot();
SDOperand Flag;
- // FIXME: input copies.
+ // Loop over all of the inputs, copying the operand values into the
+ // appropriate registers and processing the output regs.
+ unsigned RetValReg = 0;
+ std::vector<std::pair<unsigned, Value*> > IndirectStoresToEmit;
+ unsigned OpNum = 1;
+ bool FoundOutputConstraint = false;
+ for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
+ switch (Constraints[i].first) {
+ case InlineAsm::isOutput: {
+ assert(!FoundOutputConstraint &&
+ "Cannot have multiple output constraints yet!");
+ FoundOutputConstraint = true;
+ assert(I.getType() != Type::VoidTy && "Bad inline asm!");
+ // Copy the output from the appropriate register.
+ std::vector<unsigned> Regs =
+ TLI.getRegForInlineAsmConstraint(Constraints[i].second);
+ assert(Regs.size() == 1 && "Only handle simple regs right now!");
+ RetValReg = Regs[0];
+
+ // Add information to the INLINEASM node to know that this register is
+ // set.
+ AsmNodeOperands.push_back(DAG.getRegister(RetValReg,
+ TLI.getValueType(I.getType())));
+ AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
+ break;
+ }
+ case InlineAsm::isIndirectOutput: {
+ // Copy the output from the appropriate register.
+ std::vector<unsigned> Regs =
+ TLI.getRegForInlineAsmConstraint(Constraints[i].second);
+ assert(Regs.size() == 1 && "Only handle simple regs right now!");
+ IndirectStoresToEmit.push_back(std::make_pair(Regs[0],
+ I.getOperand(OpNum)));
+ OpNum++; // Consumes a call operand.
+
+ // Add information to the INLINEASM node to know that this register is
+ // set.
+ AsmNodeOperands.push_back(DAG.getRegister(Regs[0],
+ TLI.getValueType(I.getType())));
+ AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
+ break;
+ }
+ case InlineAsm::isInput: {
+ // Copy the input into the appropriate register.
+ std::vector<unsigned> Regs =
+ TLI.getRegForInlineAsmConstraint(Constraints[i].second);
+ assert(Regs.size() == 1 && "Only handle simple regs right now!");
+ Chain = DAG.getCopyToReg(Chain, Regs[0],
+ getValue(I.getOperand(OpNum)), Flag);
+ Flag = Chain.getValue(1);
+
+ // Add information to the INLINEASM node to know that this register is
+ // read.
+ AsmNodeOperands.push_back(DAG.getRegister(Regs[0],
+ TLI.getValueType(I.getType())));
+ AsmNodeOperands.push_back(DAG.getConstant(1, MVT::i32)); // ISUSE
+ break;
+ }
+ case InlineAsm::isClobber:
+ // Nothing to do.
+ break;
+ }
+ }
// Finish up input operands.
AsmNodeOperands[0] = Chain;
@@ -1182,8 +1243,40 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
Chain = DAG.getNode(ISD::INLINEASM, VTs, AsmNodeOperands);
Flag = Chain.getValue(1);
- // FIXME: Copies out of registers here, setValue(CI).
+ // If this asm returns a register value, copy the result from that register
+ // and set it as the value of the call.
+ if (RetValReg) {
+ SDOperand Val = DAG.getCopyFromReg(Chain, RetValReg,
+ TLI.getValueType(I.getType()), Flag);
+ Chain = Val.getValue(1);
+ Flag = Val.getValue(2);
+ setValue(&I, Val);
+ }
+
+ std::vector<std::pair<SDOperand, Value*> > StoresToEmit;
+
+ // Process indirect outputs, first output all of the flagged copies out of
+ // physregs.
+ for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) {
+ Value *Ptr = IndirectStoresToEmit[i].second;
+ const Type *Ty = cast<PointerType>(Ptr->getType())->getElementType();
+ SDOperand Val = DAG.getCopyFromReg(Chain, IndirectStoresToEmit[i].first,
+ TLI.getValueType(Ty), Flag);
+ Chain = Val.getValue(1);
+ Flag = Val.getValue(2);
+ StoresToEmit.push_back(std::make_pair(Val, Ptr));
+ OpNum++; // Consumes a call operand.
+ }
+ // Emit the non-flagged stores from the physregs.
+ std::vector<SDOperand> OutChains;
+ for (unsigned i = 0, e = StoresToEmit.size(); i != e; ++i)
+ OutChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+ StoresToEmit[i].first,
+ getValue(StoresToEmit[i].second),
+ DAG.getSrcValue(StoresToEmit[i].second)));
+ if (!OutChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains);
DAG.setRoot(Chain);
}