[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp
Evan Cheng
evan.cheng at apple.com
Fri Mar 3 18:49:08 PST 2006
Changes in directory llvm/lib/Target/X86:
X86ISelLowering.cpp updated: 1.100 -> 1.101
---
Log message:
MEMSET / MEMCPY lowering bugs: we can't issue a single WORD / DWORD version of
rep/stos and rep/mov if the count is not a constant. We could do
rep/stosl; and $count, 3; rep/stosb
For now, I will lower them to memset / memcpy calls. We will revisit this after
a little bit experiment.
Also need to take care of the trailing bytes even if the count is a constant.
Since the max. number of trailing bytes are 3, we will simply issue loads /
stores.
---
Diffs of the changes: (+83 -28)
X86ISelLowering.cpp | 111 ++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 83 insertions(+), 28 deletions(-)
Index: llvm/lib/Target/X86/X86ISelLowering.cpp
diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.100 llvm/lib/Target/X86/X86ISelLowering.cpp:1.101
--- llvm/lib/Target/X86/X86ISelLowering.cpp:1.100 Fri Mar 3 19:12:00 2006
+++ llvm/lib/Target/X86/X86ISelLowering.cpp Fri Mar 3 20:48:56 2006
@@ -1696,7 +1696,7 @@
Op.getOperand(0), Op.getOperand(2), CC, Cond);
}
case ISD::MEMSET: {
- SDOperand InFlag;
+ SDOperand InFlag(0, 0);
SDOperand Chain = Op.getOperand(0);
unsigned Align =
(unsigned)cast<ConstantSDNode>(Op.getOperand(4))->getValue();
@@ -1705,7 +1705,7 @@
ConstantSDNode *I = dyn_cast<ConstantSDNode>(Op.getOperand(3));
// If not DWORD aligned, call memset if size is less than the threshold.
// It knows how to align to the right boundary first.
- if ((Align & 3) != 0 &&
+ if ((Align & 3) != 0 ||
!(I && I->getValue() >= Subtarget->getMinRepStrSizeThreshold())) {
MVT::ValueType IntPtr = getPointerTy();
const Type *IntPtrTy = getTargetData().getIntPtrType();
@@ -1723,7 +1723,9 @@
MVT::ValueType AVT;
SDOperand Count;
- if (ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Op.getOperand(2))) {
+ ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Op.getOperand(2));
+ unsigned BytesLeft = 0;
+ if (ValC) {
unsigned ValReg;
unsigned Val = ValC->getValue() & 255;
@@ -1731,21 +1733,15 @@
switch (Align & 3) {
case 2: // WORD aligned
AVT = MVT::i16;
- if (I)
- Count = DAG.getConstant(I->getValue() / 2, MVT::i32);
- else
- Count = DAG.getNode(ISD::SRL, MVT::i32, Op.getOperand(3),
- DAG.getConstant(1, MVT::i8));
+ Count = DAG.getConstant(I->getValue() / 2, MVT::i32);
+ BytesLeft = I->getValue() % 2;
Val = (Val << 8) | Val;
ValReg = X86::AX;
break;
case 0: // DWORD aligned
AVT = MVT::i32;
- if (I)
- Count = DAG.getConstant(I->getValue() / 4, MVT::i32);
- else
- Count = DAG.getNode(ISD::SRL, MVT::i32, Op.getOperand(3),
- DAG.getConstant(2, MVT::i8));
+ Count = DAG.getConstant(I->getValue() / 4, MVT::i32);
+ BytesLeft = I->getValue() % 4;
Val = (Val << 8) | Val;
Val = (Val << 16) | Val;
ValReg = X86::EAX;
@@ -1771,9 +1767,36 @@
InFlag = Chain.getValue(1);
Chain = DAG.getCopyToReg(Chain, X86::EDI, Op.getOperand(1), InFlag);
InFlag = Chain.getValue(1);
+ Chain = DAG.getNode(X86ISD::REP_STOS, MVT::Other, Chain,
+ DAG.getValueType(AVT), InFlag);
+
+ if (BytesLeft) {
+ // Issue stores for the last 1 - 3 bytes.
+ SDOperand Value;
+ unsigned Val = ValC->getValue() & 255;
+ unsigned Offset = I->getValue() - BytesLeft;
+ SDOperand DstAddr = Op.getOperand(1);
+ MVT::ValueType AddrVT = DstAddr.getValueType();
+ if (BytesLeft >= 2) {
+ Value = DAG.getConstant((Val << 8) | Val, MVT::i16);
+ Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+ DAG.getNode(ISD::ADD, AddrVT, DstAddr,
+ DAG.getConstant(Offset, AddrVT)),
+ DAG.getSrcValue(NULL));
+ BytesLeft -= 2;
+ Offset += 2;
+ }
+
+ if (BytesLeft == 1) {
+ Value = DAG.getConstant(Val, MVT::i8);
+ Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+ DAG.getNode(ISD::ADD, AddrVT, DstAddr,
+ DAG.getConstant(Offset, AddrVT)),
+ DAG.getSrcValue(NULL));
+ }
+ }
- return DAG.getNode(X86ISD::REP_STOS, MVT::Other, Chain,
- DAG.getValueType(AVT), InFlag);
+ return Chain;
}
case ISD::MEMCPY: {
SDOperand Chain = Op.getOperand(0);
@@ -1784,7 +1807,7 @@
ConstantSDNode *I = dyn_cast<ConstantSDNode>(Op.getOperand(3));
// If not DWORD aligned, call memcpy if size is less than the threshold.
// It knows how to align to the right boundary first.
- if ((Align & 3) != 0 &&
+ if ((Align & 3) != 0 ||
!(I && I->getValue() >= Subtarget->getMinRepStrSizeThreshold())) {
MVT::ValueType IntPtr = getPointerTy();
const Type *IntPtrTy = getTargetData().getIntPtrType();
@@ -1800,21 +1823,17 @@
MVT::ValueType AVT;
SDOperand Count;
+ unsigned BytesLeft = 0;
switch (Align & 3) {
case 2: // WORD aligned
AVT = MVT::i16;
- if (I)
- Count = DAG.getConstant(I->getValue() / 2, MVT::i32);
- else
- Count = DAG.getConstant(I->getValue() / 2, MVT::i32);
+ Count = DAG.getConstant(I->getValue() / 2, MVT::i32);
+ BytesLeft = I->getValue() % 2;
break;
case 0: // DWORD aligned
AVT = MVT::i32;
- if (I)
- Count = DAG.getConstant(I->getValue() / 4, MVT::i32);
- else
- Count = DAG.getNode(ISD::SRL, MVT::i32, Op.getOperand(3),
- DAG.getConstant(2, MVT::i8));
+ Count = DAG.getConstant(I->getValue() / 4, MVT::i32);
+ BytesLeft = I->getValue() % 4;
break;
default: // Byte aligned
AVT = MVT::i8;
@@ -1822,16 +1841,52 @@
break;
}
- SDOperand InFlag;
+ SDOperand InFlag(0, 0);
Chain = DAG.getCopyToReg(Chain, X86::ECX, Count, InFlag);
InFlag = Chain.getValue(1);
Chain = DAG.getCopyToReg(Chain, X86::EDI, Op.getOperand(1), InFlag);
InFlag = Chain.getValue(1);
Chain = DAG.getCopyToReg(Chain, X86::ESI, Op.getOperand(2), InFlag);
InFlag = Chain.getValue(1);
+ Chain = DAG.getNode(X86ISD::REP_MOVS, MVT::Other, Chain,
+ DAG.getValueType(AVT), InFlag);
+
+ if (BytesLeft) {
+ // Issue loads and stores for the last 1 - 3 bytes.
+ unsigned Offset = I->getValue() - BytesLeft;
+ SDOperand DstAddr = Op.getOperand(1);
+ MVT::ValueType DstVT = DstAddr.getValueType();
+ SDOperand SrcAddr = Op.getOperand(2);
+ MVT::ValueType SrcVT = SrcAddr.getValueType();
+ SDOperand Value;
+ if (BytesLeft >= 2) {
+ Value = DAG.getLoad(MVT::i16, Chain,
+ DAG.getNode(ISD::ADD, SrcVT, SrcAddr,
+ DAG.getConstant(Offset, SrcVT)),
+ DAG.getSrcValue(NULL));
+ Chain = Value.getValue(1);
+ Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+ DAG.getNode(ISD::ADD, DstVT, DstAddr,
+ DAG.getConstant(Offset, DstVT)),
+ DAG.getSrcValue(NULL));
+ BytesLeft -= 2;
+ Offset += 2;
+ }
+
+ if (BytesLeft == 1) {
+ Value = DAG.getLoad(MVT::i8, Chain,
+ DAG.getNode(ISD::ADD, SrcVT, SrcAddr,
+ DAG.getConstant(Offset, SrcVT)),
+ DAG.getSrcValue(NULL));
+ Chain = Value.getValue(1);
+ Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Value,
+ DAG.getNode(ISD::ADD, DstVT, DstAddr,
+ DAG.getConstant(Offset, DstVT)),
+ DAG.getSrcValue(NULL));
+ }
+ }
- return DAG.getNode(X86ISD::REP_MOVS, MVT::Other, Chain,
- DAG.getValueType(AVT), InFlag);
+ return Chain;
}
// ConstantPool, GlobalAddress, and ExternalSymbol are lowered as their
More information about the llvm-commits
mailing list