remove the read/write port/io intrinsics.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26479 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2006-03-03 00:19:58 +00:00
parent 472c0ebea4
commit 41edaa0529
11 changed files with 12 additions and 387 deletions

View File

@ -143,13 +143,6 @@
<li><a href="#i_readcyclecounter"><tt>llvm.readcyclecounter</tt>' Intrinsic</a></li>
</ol>
</li>
<li><a href="#int_os">Operating System Intrinsics</a>
<ol>
<li><a href="#i_readport">'<tt>llvm.readport</tt>' Intrinsic</a></li>
<li><a href="#i_writeport">'<tt>llvm.writeport</tt>' Intrinsic</a></li>
<li><a href="#i_readio">'<tt>llvm.readio</tt>' Intrinsic</a></li>
<li><a href="#i_writeio">'<tt>llvm.writeio</tt>' Intrinsic</a></li>
</ol>
<li><a href="#int_libc">Standard C Library Intrinsics</a>
<ol>
<li><a href="#i_memcpy">'<tt>llvm.memcpy.*</tt>' Intrinsic</a></li>
@ -3266,199 +3259,6 @@ system wide value. On backends without support, this is lowered to a constant 0
</div>
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="int_os">Operating System Intrinsics</a>
</div>
<div class="doc_text">
<p>
These intrinsics are provided by LLVM to support the implementation of
operating system level code.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="i_readport">'<tt>llvm.readport</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre>
declare &lt;integer type&gt; %llvm.readport (&lt;integer type&gt; &lt;address&gt;)
</pre>
<h5>Overview:</h5>
<p>
The '<tt>llvm.readport</tt>' intrinsic reads data from the specified hardware
I/O port.
</p>
<h5>Arguments:</h5>
<p>
The argument to this intrinsic indicates the hardware I/O address from which
to read the data. The address is in the hardware I/O address namespace (as
opposed to being a memory location for memory mapped I/O).
</p>
<h5>Semantics:</h5>
<p>
The '<tt>llvm.readport</tt>' intrinsic reads data from the hardware I/O port
specified by <i>address</i> and returns the value. The address and return
value must be integers, but the size is dependent upon the platform upon which
the program is code generated. For example, on x86, the address must be an
unsigned 16-bit value, and the return value must be 8, 16, or 32 bits.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="i_writeport">'<tt>llvm.writeport</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre>
call void (&lt;integer type&gt;, &lt;integer type&gt;)*
%llvm.writeport (&lt;integer type&gt; &lt;value&gt;,
&lt;integer type&gt; &lt;address&gt;)
</pre>
<h5>Overview:</h5>
<p>
The '<tt>llvm.writeport</tt>' intrinsic writes data to the specified hardware
I/O port.
</p>
<h5>Arguments:</h5>
<p>
The first argument is the value to write to the I/O port.
</p>
<p>
The second argument indicates the hardware I/O address to which data should be
written. The address is in the hardware I/O address namespace (as opposed to
being a memory location for memory mapped I/O).
</p>
<h5>Semantics:</h5>
<p>
The '<tt>llvm.writeport</tt>' intrinsic writes <i>value</i> to the I/O port
specified by <i>address</i>. The address and value must be integers, but the
size is dependent upon the platform upon which the program is code generated.
For example, on x86, the address must be an unsigned 16-bit value, and the
value written must be 8, 16, or 32 bits in length.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="i_readio">'<tt>llvm.readio</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre>
declare &lt;result&gt; %llvm.readio (&lt;ty&gt; * &lt;pointer&gt;)
</pre>
<h5>Overview:</h5>
<p>
The '<tt>llvm.readio</tt>' intrinsic reads data from a memory mapped I/O
address.
</p>
<h5>Arguments:</h5>
<p>
The argument to this intrinsic is a pointer indicating the memory address from
which to read the data. The data must be a
<a href="#t_firstclass">first class</a> type.
</p>
<h5>Semantics:</h5>
<p>
The '<tt>llvm.readio</tt>' intrinsic reads data from a memory mapped I/O
location specified by <i>pointer</i> and returns the value. The argument must
be a pointer, and the return value must be a
<a href="#t_firstclass">first class</a> type. However, certain architectures
may not support I/O on all first class types. For example, 32-bit processors
may only support I/O on data types that are 32 bits or less.
</p>
<p>
This intrinsic enforces an in-order memory model for llvm.readio and
llvm.writeio calls on machines that use dynamic scheduling. Dynamically
scheduled processors may execute loads and stores out of order, re-ordering at
run time accesses to memory mapped I/O registers. Using these intrinsics
ensures that accesses to memory mapped I/O registers occur in program order.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="i_writeio">'<tt>llvm.writeio</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<pre>
declare void %llvm.writeio (&lt;ty1&gt; &lt;value&gt;, &lt;ty2&gt; * &lt;pointer&gt;)
</pre>
<h5>Overview:</h5>
<p>
The '<tt>llvm.writeio</tt>' intrinsic writes data to the specified memory
mapped I/O address.
</p>
<h5>Arguments:</h5>
<p>
The first argument is the value to write to the memory mapped I/O location.
The second argument is a pointer indicating the memory address to which the
data should be written.
</p>
<h5>Semantics:</h5>
<p>
The '<tt>llvm.writeio</tt>' intrinsic writes <i>value</i> to the memory mapped
I/O address specified by <i>pointer</i>. The value must be a
<a href="#t_firstclass">first class</a> type. However, certain architectures
may not support I/O on all first class types. For example, 32-bit processors
may only support I/O on data types that are 32 bits or less.
</p>
<p>
This intrinsic enforces an in-order memory model for llvm.readio and
llvm.writeio calls on machines that use dynamic scheduling. Dynamically
scheduled processors may execute loads and stores out of order, re-ordering at
run time accesses to memory mapped I/O registers. Using these intrinsics
ensures that accesses to memory mapped I/O registers occur in program order.
</p>
</div>
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="int_libc">Standard C Library Intrinsics</a>

View File

@ -379,12 +379,6 @@ namespace ISD {
// register (or other high accuracy low latency clock source)
READCYCLECOUNTER,
// READPORT, WRITEPORT, READIO, WRITEIO - These correspond to the LLVM
// intrinsics of the same name. The first operand is a token chain, the
// other operands match the intrinsic. These produce a token chain in
// addition to a value (if any).
READPORT, WRITEPORT, READIO, WRITEIO,
// HANDLENODE node - Used as a handle for various purposes.
HANDLENODE,

View File

@ -86,13 +86,6 @@ namespace Intrinsic {
cttz_i16, // Count trailing zeros of short
cttz_i32, // Count trailing zeros of int
cttz_i64, // Count trailing zeros of long
// Input/Output intrinsics.
readport,
writeport,
readio,
writeio
};
} // End Intrinsic namespace

View File

@ -1691,68 +1691,6 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
case ISD::READPORT:
Tmp1 = LegalizeOp(Node->getOperand(0));
Tmp2 = LegalizeOp(Node->getOperand(1));
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
// Since these produce two values, make sure to remember that we legalized
// both of them.
AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
return Result;
case ISD::WRITEPORT:
Tmp1 = LegalizeOp(Node->getOperand(0));
Tmp2 = LegalizeOp(Node->getOperand(1));
Tmp3 = LegalizeOp(Node->getOperand(2));
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
break;
case ISD::READIO:
Tmp1 = LegalizeOp(Node->getOperand(0));
Tmp2 = LegalizeOp(Node->getOperand(1));
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
case TargetLowering::Custom:
default: assert(0 && "This action not implemented for this operation!");
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
break;
case TargetLowering::Expand:
// Replace this with a load from memory.
Result = DAG.getLoad(Node->getValueType(0), Node->getOperand(0),
Node->getOperand(1), DAG.getSrcValue(NULL));
Result = LegalizeOp(Result);
break;
}
// Since these produce two values, make sure to remember that we legalized
// both of them.
AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
return Result.getValue(Op.ResNo);
case ISD::WRITEIO:
Tmp1 = LegalizeOp(Node->getOperand(0));
Tmp2 = LegalizeOp(Node->getOperand(1));
Tmp3 = LegalizeOp(Node->getOperand(2));
switch (TLI.getOperationAction(Node->getOpcode(),
Node->getOperand(1).getValueType())) {
case TargetLowering::Custom:
default: assert(0 && "This action not implemented for this operation!");
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
break;
case TargetLowering::Expand:
// Replace this with a store to memory.
Result = DAG.getNode(ISD::STORE, MVT::Other, Node->getOperand(0),
Node->getOperand(1), Node->getOperand(2),
DAG.getSrcValue(NULL));
break;
}
break;
case ISD::SHL_PARTS:
case ISD::SRA_PARTS:
case ISD::SRL_PARTS: {

View File

@ -2691,12 +2691,6 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::CTTZ: return "cttz";
case ISD::CTLZ: return "ctlz";
// IO Intrinsics
case ISD::READPORT: return "readport";
case ISD::WRITEPORT: return "writeport";
case ISD::READIO: return "readio";
case ISD::WRITEIO: return "writeio";
// Debug info
case ISD::LOCATION: return "location";
case ISD::DEBUG_LOC: return "debug_loc";

View File

@ -968,29 +968,6 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
visitMemIntrinsic(I, ISD::MEMMOVE);
return 0;
case Intrinsic::readport:
case Intrinsic::readio: {
std::vector<MVT::ValueType> VTs;
VTs.push_back(TLI.getValueType(I.getType()));
VTs.push_back(MVT::Other);
std::vector<SDOperand> Ops;
Ops.push_back(getRoot());
Ops.push_back(getValue(I.getOperand(1)));
SDOperand Tmp = DAG.getNode(Intrinsic == Intrinsic::readport ?
ISD::READPORT : ISD::READIO, VTs, Ops);
setValue(&I, Tmp);
DAG.setRoot(Tmp.getValue(1));
return 0;
}
case Intrinsic::writeport:
case Intrinsic::writeio:
DAG.setRoot(DAG.getNode(Intrinsic == Intrinsic::writeport ?
ISD::WRITEPORT : ISD::WRITEIO, MVT::Other,
getRoot(), getValue(I.getOperand(1)),
getValue(I.getOperand(2))));
return 0;
case Intrinsic::dbg_stoppoint: {
if (TLI.getTargetMachine().getIntrinsicLowering().EmitDebugFunctions())
return "llvm_debugger_stop";

View File

@ -138,14 +138,6 @@ def SDTBrcond : SDTypeProfile<0, 2, [ // brcond
def SDTRet : SDTypeProfile<0, 0, []>; // ret
def SDTReadPort : SDTypeProfile<1, 1, [ // readport
SDTCisInt<0>, SDTCisInt<1>
]>;
def SDTWritePort : SDTypeProfile<0, 2, [ // writeport
SDTCisInt<0>, SDTCisInt<1>
]>;
def SDTLoad : SDTypeProfile<1, 1, [ // load
SDTCisPtrTy<1>
]>;
@ -284,9 +276,6 @@ def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
def ret : SDNode<"ISD::RET" , SDTRet, [SDNPHasChain]>;
def readport : SDNode<"ISD::READPORT" , SDTReadPort, [SDNPHasChain]>;
def writeport : SDNode<"ISD::WRITEPORT" , SDTWritePort, [SDNPHasChain]>;
def load : SDNode<"ISD::LOAD" , SDTLoad, [SDNPHasChain]>;
def store : SDNode<"ISD::STORE" , SDTStore, [SDNPHasChain]>;

View File

@ -137,15 +137,6 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
setOperationAction(ISD::READCYCLECOUNTER , MVT::i64 , Custom);
setOperationAction(ISD::BSWAP , MVT::i16 , Expand);
setOperationAction(ISD::READIO , MVT::i1 , Expand);
setOperationAction(ISD::READIO , MVT::i8 , Expand);
setOperationAction(ISD::READIO , MVT::i16 , Expand);
setOperationAction(ISD::READIO , MVT::i32 , Expand);
setOperationAction(ISD::WRITEIO , MVT::i1 , Expand);
setOperationAction(ISD::WRITEIO , MVT::i8 , Expand);
setOperationAction(ISD::WRITEIO , MVT::i16 , Expand);
setOperationAction(ISD::WRITEIO , MVT::i32 , Expand);
// These should be promoted to a larger select which is supported.
setOperationAction(ISD::SELECT , MVT::i1 , Promote);
setOperationAction(ISD::SELECT , MVT::i8 , Promote);

View File

@ -581,48 +581,48 @@ def REP_STOSD : I<0xAB, RawFrm, (ops), "{rep;stosl|rep stosd}",
//
def IN8rr : I<0xEC, RawFrm, (ops),
"in{b} {%dx, %al|%AL, %DX}",
[(set AL, (readport DX))]>, Imp<[DX], [AL]>;
[]>, Imp<[DX], [AL]>;
def IN16rr : I<0xED, RawFrm, (ops),
"in{w} {%dx, %ax|%AX, %DX}",
[(set AX, (readport DX))]>, Imp<[DX], [AX]>, OpSize;
[]>, Imp<[DX], [AX]>, OpSize;
def IN32rr : I<0xED, RawFrm, (ops),
"in{l} {%dx, %eax|%EAX, %DX}",
[(set EAX, (readport DX))]>, Imp<[DX],[EAX]>;
[]>, Imp<[DX],[EAX]>;
def IN8ri : Ii8<0xE4, RawFrm, (ops i16i8imm:$port),
"in{b} {$port, %al|%AL, $port}",
[(set AL, (readport i16immZExt8:$port))]>,
[]>,
Imp<[], [AL]>;
def IN16ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{w} {$port, %ax|%AX, $port}",
[(set AX, (readport i16immZExt8:$port))]>,
[]>,
Imp<[], [AX]>, OpSize;
def IN32ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{l} {$port, %eax|%EAX, $port}",
[(set EAX, (readport i16immZExt8:$port))]>,
[]>,
Imp<[],[EAX]>;
def OUT8rr : I<0xEE, RawFrm, (ops),
"out{b} {%al, %dx|%DX, %AL}",
[(writeport AL, DX)]>, Imp<[DX, AL], []>;
[]>, Imp<[DX, AL], []>;
def OUT16rr : I<0xEF, RawFrm, (ops),
"out{w} {%ax, %dx|%DX, %AX}",
[(writeport AX, DX)]>, Imp<[DX, AX], []>, OpSize;
[]>, Imp<[DX, AX], []>, OpSize;
def OUT32rr : I<0xEF, RawFrm, (ops),
"out{l} {%eax, %dx|%DX, %EAX}",
[(writeport EAX, DX)]>, Imp<[DX, EAX], []>;
[]>, Imp<[DX, EAX], []>;
def OUT8ir : Ii8<0xE6, RawFrm, (ops i16i8imm:$port),
"out{b} {%al, $port|$port, %AL}",
[(writeport AL, i16immZExt8:$port)]>,
[]>,
Imp<[AL], []>;
def OUT16ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{w} {%ax, $port|$port, %AX}",
[(writeport AX, i16immZExt8:$port)]>,
[]>,
Imp<[AX], []>, OpSize;
def OUT32ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{l} {%eax, $port|$port, %EAX}",
[(writeport EAX, i16immZExt8:$port)]>,
[]>,
Imp<[EAX], []>;
//===----------------------------------------------------------------------===//

View File

@ -265,8 +265,6 @@ unsigned Function::getIntrinsicID() const {
break;
case 'r':
if (Name == "llvm.returnaddress") return Intrinsic::returnaddress;
if (Name == "llvm.readport") return Intrinsic::readport;
if (Name == "llvm.readio") return Intrinsic::readio;
if (Name == "llvm.readcyclecounter") return Intrinsic::readcyclecounter;
break;
case 's':
@ -283,10 +281,6 @@ unsigned Function::getIntrinsicID() const {
if (Name == "llvm.va_end") return Intrinsic::vaend;
if (Name == "llvm.va_start") return Intrinsic::vastart;
break;
case 'w':
if (Name == "llvm.writeport") return Intrinsic::writeport;
if (Name == "llvm.writeio") return Intrinsic::writeio;
break;
}
// The "llvm." namespace is reserved!
assert(!"Unknown LLVM intrinsic function!");

View File

@ -702,51 +702,6 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
NumArgs = 1;
break;
// Verify that read and write port have integral parameters of the correct
// signed-ness.
case Intrinsic::writeport:
Assert1(FT->getNumParams() == 2,
"Illegal # arguments for intrinsic function!", IF);
Assert1(FT->getParamType(0)->isIntegral(),
"First argument not unsigned int!", IF);
Assert1(FT->getParamType(1)->isUnsigned(),
"First argument not unsigned int!", IF);
NumArgs = 2;
break;
case Intrinsic::writeio:
Assert1(FT->getNumParams() == 2,
"Illegal # arguments for intrinsic function!", IF);
Assert1(FT->getParamType(0)->isFirstClassType(),
"First argument not a first class type!", IF);
Assert1(isa<PointerType>(FT->getParamType(1)),
"Second argument not a pointer!", IF);
NumArgs = 2;
break;
case Intrinsic::readport:
Assert1(FT->getNumParams() == 1,
"Illegal # arguments for intrinsic function!", IF);
Assert1(FT->getReturnType()->isFirstClassType(),
"Return type is not a first class type!", IF);
Assert1(FT->getParamType(0)->isUnsigned(),
"First argument not unsigned int!", IF);
NumArgs = 1;
break;
case Intrinsic::readio: {
const PointerType *ParamType = dyn_cast<PointerType>(FT->getParamType(0));
const Type *ReturnType = FT->getReturnType();
Assert1(FT->getNumParams() == 1,
"Illegal # arguments for intrinsic function!", IF);
Assert1(ParamType, "First argument not a pointer!", IF);
Assert1(ParamType->getElementType() == ReturnType,
"Pointer type doesn't match return type!", IF);
NumArgs = 1;
break;
}
case Intrinsic::isunordered_f32:
Assert1(FT->getNumParams() == 2,
"Illegal # arguments for intrinsic function!", IF);