aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2006-02-14 08:22:34 +0000
committerEvan Cheng <evan.cheng@apple.com>2006-02-14 08:22:34 +0000
commit1db92f947cc600dee5edb9305a4e0f1c5c872965 (patch)
treec46ab942879d5f2d9a1e7882087d8ad89c00a31b
parent82eaf628b4c9574f297bc1d8c44ae5237bc62a8c (diff)
downloadexternal_llvm-1db92f947cc600dee5edb9305a4e0f1c5c872965.zip
external_llvm-1db92f947cc600dee5edb9305a4e0f1c5c872965.tar.gz
external_llvm-1db92f947cc600dee5edb9305a4e0f1c5c872965.tar.bz2
Expand memset dst, c, size to a series of stores if size falls below the
target specific theshold, e.g. 16 for x86. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26171 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp131
1 files changed, 127 insertions, 4 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 979f2be..f472c0e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1523,13 +1523,136 @@ void SelectionDAGLowering::visitFrameReturnAddress(CallInst &I, bool isFrame) {
DAG.setRoot(Result.second);
}
+/// getMemSetValue - Vectorized representation of the memset value
+/// operand.
+static SDOperand getMemsetValue(SDOperand Value, MVT::ValueType VT,
+ SelectionDAG &DAG) {
+ if (VT == MVT::i8)
+ return Value;
+
+ MVT::ValueType CurVT = VT;
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Value)) {
+ uint64_t Val = C->getValue() & 255;
+ unsigned Shift = 8;
+ while (CurVT != MVT::i8) {
+ Val = (Val << Shift) | Val;
+ Shift <<= 1;
+ CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
+ assert(MVT::isInteger(CurVT));
+ }
+ return DAG.getConstant(Val, VT);
+ } else {
+ Value = DAG.getNode(ISD::ZERO_EXTEND, VT, Value);
+ unsigned Shift = 8;
+ while (CurVT != MVT::i8) {
+ Value =
+ DAG.getNode(ISD::OR, VT,
+ DAG.getNode(ISD::SHL, VT, Value,
+ DAG.getConstant(Shift, MVT::i8)), Value);
+ Shift <<= 1;
+ CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
+ assert(MVT::isInteger(CurVT));
+ }
+
+ return Value;
+ }
+}
+
+/// getMemBasePlusOffset - Returns base and offset node for the
+static SDOperand getMemBasePlusOffset(SDOperand Base, unsigned Offset,
+ SelectionDAG &DAG, TargetLowering &TLI) {
+ MVT::ValueType VT = Base.getValueType();
+ return DAG.getNode(ISD::ADD, VT, Base, DAG.getConstant(Offset, VT));
+}
+
+/// getMemOpTypes - Determines the types of the sequence of
+/// memory ops to perform memset / memcpy.
+static void getMemOpTypes(std::vector<MVT::ValueType> &MemOps,
+ uint64_t Size, unsigned Align, TargetLowering &TLI) {
+ MVT::ValueType VT;
+
+ if (TLI.allowsUnalignedMemoryAccesses()) {
+ VT = MVT::i64;
+ } else {
+ switch (Align & 7) {
+ case 0:
+ VT = MVT::i64;
+ break;
+ case 4:
+ VT = MVT::i32;
+ break;
+ case 2:
+ VT = MVT::i16;
+ break;
+ default:
+ VT = MVT::i8;
+ break;
+ }
+ }
+
+ while (!TLI.isTypeLegal(VT)) {
+ VT = (MVT::ValueType)((unsigned)VT - 1);
+ assert(MVT::isInteger(VT));
+ }
+
+ while (Size != 0) {
+ unsigned VTSize = getSizeInBits(VT) / 8;
+ while (VTSize > Size) {
+ VT = (MVT::ValueType)((unsigned)VT - 1);
+ assert(MVT::isInteger(VT));
+ VTSize >>= 1;
+ }
+ MemOps.push_back(VT);
+ Size -= VTSize;
+ }
+}
+
void SelectionDAGLowering::visitMemIntrinsic(CallInst &I, unsigned Op) {
+ SDOperand Op1 = getValue(I.getOperand(1));
+ SDOperand Op2 = getValue(I.getOperand(2));
+ SDOperand Op3 = getValue(I.getOperand(3));
+ SDOperand Op4 = getValue(I.getOperand(4));
+ unsigned Align = (unsigned)cast<ConstantSDNode>(Op4)->getValue();
+ if (Align == 0) Align = 1;
+
+ if (ConstantSDNode *Size = dyn_cast<ConstantSDNode>(Op3)) {
+ std::vector<MVT::ValueType> MemOps;
+ getMemOpTypes(MemOps, Size->getValue(), Align, TLI);
+ unsigned NumMemOps = MemOps.size();
+
+ // Expand memset / memcpy to a series of load / store ops
+ // if the size operand falls below a certain threshold.
+ std::vector<SDOperand> OutChains;
+ switch (Op) {
+ default: ; // Do nothing for now.
+ case ISD::MEMSET: {
+ if (NumMemOps <= TLI.getMaxStoresPerMemSet()) {
+ unsigned Offset = 0;
+ for (unsigned i = 0; i < NumMemOps; i++) {
+ MVT::ValueType VT = MemOps[i];
+ unsigned VTSize = getSizeInBits(VT) / 8;
+ SDOperand Value = getMemsetValue(Op2, VT, DAG);
+ OutChains.
+ push_back(DAG.getNode(ISD::STORE, MVT::Other, getRoot(),
+ Value,
+ getMemBasePlusOffset(Op1, Offset, DAG, TLI),
+ DAG.getSrcValue(NULL)));
+ Offset += VTSize;
+ }
+
+ DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains));
+ return;
+ }
+ }
+ }
+ }
+
std::vector<SDOperand> Ops;
Ops.push_back(getRoot());
- Ops.push_back(getValue(I.getOperand(1)));
- Ops.push_back(getValue(I.getOperand(2)));
- Ops.push_back(getValue(I.getOperand(3)));
- Ops.push_back(getValue(I.getOperand(4)));
+ Ops.push_back(Op1);
+ Ops.push_back(Op2);
+ Ops.push_back(Op3);
+ Ops.push_back(Op4);
DAG.setRoot(DAG.getNode(Op, MVT::Other, Ops));
}