diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-02-06 16:23:56 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-02-06 16:23:56 -0500 |
commit | 1296ba6b4d429762ff2c4a93b27d8a148590fdc7 (patch) | |
tree | a79bf051b6cb58d1e3b676ee466ae77eb37a1e65 | |
parent | 3a31f089c8392243965dfaa1be93108d02671ea4 (diff) |
optimize partially aligned memsets
-rw-r--r-- | lib/Target/JSBackend/CallHandlers.h | 55 |
1 files changed, 30 insertions, 25 deletions
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h index 92d097ec5e..11a8cdad0e 100644 --- a/lib/Target/JSBackend/CallHandlers.h +++ b/lib/Target/JSBackend/CallHandlers.h @@ -278,35 +278,40 @@ DEF_CALL_HANDLER(llvm_memset_p0i8_i32, { if (LenInt) { ConstantInt *ValInt = dyn_cast<ConstantInt>(CI->getOperand(1)); if (ValInt) { + // we can emit inline code for this unsigned Len = LenInt->getZExtValue(); - if (Len == 0) return ""; // after here, we can assume Len>1 - unsigned Align = AlignInt->getZExtValue(); - unsigned Val = ValInt->getZExtValue(); - while (Align > 0 && Len % Align != 0) Align /= 2; // a very unaligned small number of bytes can still be unrolled in some cases - if (Align > 4) Align = 4; - if (Align > 0 && Len % Align == 0) { - // we can emit inline code for this + if (Len <= WRITE_LOOP_MAX) { + unsigned Align = AlignInt->getZExtValue(); + unsigned Val = ValInt->getZExtValue(); + if (Align > 4) Align = 4; + unsigned Pos = 0; std::string Ret; - std::string Dest = getValueAsStr(CI->getOperand(0)); - unsigned FullVal = 0; - for (unsigned i = 0; i < Align; i++) { - FullVal <<= 8; - FullVal |= Val; - } - unsigned Factor = Len/Align; - if (Factor <= UNROLL_LOOP_MAX) { - // unroll - Ret += getHeapAccess(Dest, Align) + "=" + utostr(FullVal) + "|0"; - for (unsigned Offset = Align; Offset < Len; Offset += Align) { - std::string Add = "+" + utostr(Offset) + (Align == 1 ? "|0" : ""); - Ret += ";" + getHeapAccess(Dest + Add, Align) + "=" + utostr(FullVal) + "|0"; + while (Len > 0) { + // handle as much as we can in the current alignment + unsigned CurrLen = Align*(Len/Align); + std::string Dest = getValueAsStr(CI->getOperand(0)); + unsigned FullVal = 0; + for (unsigned i = 0; i < Align; i++) { + FullVal <<= 8; + FullVal |= Val; } - return Ret; - } else if (Len <= WRITE_LOOP_MAX) { - // emit a loop - UsedVars["dest"] = UsedVars["stop"] = Type::getInt32Ty(TheModule->getContext())->getTypeID(); - return "dest=" + Dest + "; stop=" + Dest + "+" + utostr(Len) + "|0; do { " + getHeapAccess("dest", Align) + "=" + utostr(FullVal) + "|0; dest=dest+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0));"; + unsigned Factor = CurrLen/Align; + if (Factor <= UNROLL_LOOP_MAX) { + // unroll + for (unsigned Offset = 0; Offset < CurrLen; Offset += Align) { + std::string Add = "+" + utostr(Pos + Offset) + (Align == 1 ? "|0" : ""); + Ret += ";" + getHeapAccess(Dest + Add, Align) + "=" + utostr(FullVal) + "|0"; + } + } else { + // emit a loop + UsedVars["dest"] = UsedVars["stop"] = Type::getInt32Ty(TheModule->getContext())->getTypeID(); + Ret += "dest=" + Dest + "+" + utostr(Pos) + "|0; stop=dest+" + utostr(CurrLen) + "|0; do { " + getHeapAccess("dest", Align) + "=" + utostr(FullVal) + "|0; dest=dest+" + utostr(Align) + "|0; } while ((dest|0) < (stop|0));"; + } + Pos += CurrLen; + Len -= CurrLen; + Align /= 2; } + return Ret; } } } |