aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/CppBackend/CPPBackend.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-12-21 13:52:26 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-12-21 13:56:49 -0800
commitc2b3ea05aa367e7e1957b30a154b86458d61605f (patch)
tree257b5d867488a795ac5d6ae22401f0ebd4f92353 /lib/Target/CppBackend/CPPBackend.cpp
parent30716ce07e1014fc22481cfd4ecd7d0eda338415 (diff)
optimize integer multiply with a constant
Diffstat (limited to 'lib/Target/CppBackend/CPPBackend.cpp')
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index db5c4f8817..747459e9a7 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -405,8 +405,29 @@ std::string JSWriter::getDoubleToInt(const StringRef &s) {
}
std::string JSWriter::getIMul(const Value *V1, const Value *V2) {
- // TODO: if small enough, emit direct multiply
- return "Math_imul(" + getValueAsStr(V1) + ", " + getValueAsStr(V2) + ")|0";
+ const ConstantInt *CI = NULL;
+ const Value *Other = NULL;
+ if ((CI = dyn_cast<ConstantInt>(V1))) {
+ Other = V2;
+ } else if ((CI = dyn_cast<ConstantInt>(V2))) {
+ Other = V1;
+ }
+ // we ignore optimizing the case of multiplying two constants - optimizer would have removed those
+ if (CI) {
+ std::string OtherStr = getValueAsStr(Other);
+ unsigned C = CI->getZExtValue();
+ if (C == 0) return "0";
+ if (C == 1) return OtherStr;
+ unsigned Orig = C, Shifts = 0;
+ while (C) {
+ if ((C & 1) && (C != 1)) break; // not power of 2
+ C >>= 1;
+ Shifts++;
+ if (C == 0) return OtherStr + "<<" + utostr(Shifts-1); // power of 2, emit shift
+ }
+ if (Orig < (1<<20)) return "(" + OtherStr + "*" + utostr(Orig) + ")|0"; // small enough, avoid imul
+ }
+ return "Math_imul(" + getValueAsStr(V1) + ", " + getValueAsStr(V2) + ")|0"; // unknown or too large, emit imul
}
std::string JSWriter::getLoad(std::string Assign, const Value *P, const Type *T, unsigned Alignment, char sep) {