Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: src/IceCfg.cpp

Issue 1997443002: Subzero: Initial implementation of BB Local CSE (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Initial Implementation Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceCfg.h ('k') | src/IceClFlags.def » ('j') | src/IceClFlags.def » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceCfg.cpp
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index f71737994aba701b4a75e6dcd296b11a5f66fed9..679636a5e2fd5f2b1c73a5a5714e5289f0acb281 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -27,7 +27,6 @@
#include "IceLoopAnalyzer.h"
#include "IceOperand.h"
#include "IceTargetLowering.h"
-
Jim Stichnoth 2016/05/19 01:35:50 don't remove this separator blank line
manasijm 2016/05/19 17:50:16 Done.
#include <memory>
#include <utility>
@@ -507,6 +506,114 @@ void Cfg::shuffleNodes() {
dump("After basic block shuffling");
}
+void Cfg::localCSE() {
Jim Stichnoth 2016/05/19 01:35:49 (putting this comment here for lack of a better pl
manasijm 2016/05/19 02:01:52 I have not managed to isolate a small example yet
+ TimerMarker T(TimerStack::TT_localCse, this);
+ struct InstHash {
+ size_t operator()(const Inst *Instr) const {
+ auto Kind = Instr->getKind();
+ auto Result =
+ std::hash<typename std::underlying_type<Inst::InstKind>::type>()(
+ Kind);
+ for (unsigned int i = 0; i < Instr->getSrcSize(); ++i) {
Jim Stichnoth 2016/05/19 01:35:50 SizeT instead of unsigned int
+ Operand *Opr = Instr->getSrc(i);
Jim Stichnoth 2016/05/19 01:35:49 I would name it not "Opr", but "Op" or "Opnd" to f
+ if (Variable *Var = llvm::dyn_cast<Variable>(Opr)) {
Jim Stichnoth 2016/05/19 01:35:49 auto *Var because the type is already clear from t
manasijm 2016/05/19 17:50:16 Done.
+ Result ^= std::hash<uint32_t>()(Var->getIndex());
Jim Stichnoth 2016/05/19 01:35:49 Can you use SizeT instead of uint32_t, to match th
manasijm 2016/05/19 17:50:16 Done.
+ } else if (Constant *Cst = llvm::dyn_cast<Constant>(Opr)) {
Jim Stichnoth 2016/05/19 01:35:49 Name it "Const" instead of "Cst" for consistency.
manasijm 2016/05/19 02:01:53 Ok, didn't do that in the first place because cons
+ Result ^= std::hash<Constant *>()(
+ Cst); // TODO : get Value ConstantPrimitive
Jim Stichnoth 2016/05/19 01:35:49 TODO(manasijm): get ... Also, probably put the TO
+ } else
+ Result ^= std::hash<Operand *>()(Opr);
+ }
+ return Result;
Jim Stichnoth 2016/05/19 01:35:49 Use early returns more aggressively, per http://ll
manasijm 2016/05/19 17:50:16 Not applicable here, all the sources has to be inc
+ }
+ };
+ struct InstEq {
+ bool operator()(Inst *const InstrA, Inst *const InstrB) const {
Jim Stichnoth 2016/05/19 01:35:48 Shouldn't this be "const Inst *InstrA"? Those are
manasijm 2016/05/19 02:01:53 I had some const correctness trouble with that. Wi
manasijm 2016/05/19 17:50:16 Done.
+ bool Result = (InstrA->getKind() == InstrB->getKind()) &&
+ (InstrA->getSrcSize() == InstrB->getSrcSize());
Jim Stichnoth 2016/05/19 01:35:48 I think this can be made clearer and more efficien
+
+ if (llvm::isa<InstArithmetic>(InstrA)) {
Jim Stichnoth 2016/05/19 01:35:49 if (auto *A = llvm::dyn_cast<InstArithmetic>(Instr
+ auto A = llvm::dyn_cast<InstArithmetic>(InstrA);
Jim Stichnoth 2016/05/19 01:35:49 auto *A auto *B
+ auto B = llvm::dyn_cast<InstArithmetic>(InstrB);
Jim Stichnoth 2016/05/19 01:35:50 use llvm::cast<> instead of llvm::dyn_cast<> here.
+ Result = Result && (A->getOp() == B->getOp());
+ }
+ // Does not enter loop if different kind or number of operands
+ for (unsigned int i = 0; i < InstrA->getSrcSize() && Result; ++i) {
Jim Stichnoth 2016/05/19 01:35:49 SizeT i
+ Result = Result && (InstrA->getSrc(i) == InstrB->getSrc(i));
Jim Stichnoth 2016/05/19 01:35:48 Be aware that Operand* pointer equality is fine wi
manasijm 2016/05/19 02:01:52 Or just returning false if they are not Constant*
+ }
+ return Result;
+ }
+ };
+ struct VariableHash {
+ size_t operator()(Variable *Var) const {
Jim Stichnoth 2016/05/19 01:35:49 const Variable * ?
+ return std::hash<uint32_t>()(Var->getIndex());
Jim Stichnoth 2016/05/19 01:35:49 Can this be SizeT instead of uint32_t?
+ }
+ };
+ for (CfgNode *Node : getNodes()) {
+ std::unordered_map<Inst *, Variable *, InstHash, InstEq,
Jim Stichnoth 2016/05/19 01:35:49 You should be able to do: CfgUnorderedMap<Inst *,
+ CfgLocalAllocator<std::pair<Inst *const, Variable *>>>
+ Seen;
+ // This could be converted to an unordered_set without much effort.
Jim Stichnoth 2016/05/19 01:35:48 If that's true, and reasonable, then just do it? Y
+ std::unordered_map<
+ Variable *, Variable *, VariableHash, std::equal_to<Variable *>,
+ CfgLocalAllocator<std::pair<Variable *const, Variable *>>> Replacements;
+ // Combining the above two into a single data structure
Jim Stichnoth 2016/05/19 01:35:50 Reflow comment to 80-col
+ // might consume less memory but will be slower
+ // i.e map of Instruction -> Vector/Set of Variables
+ std::unordered_map<
+ Variable *, std::vector<Inst *>, VariableHash,
+ std::equal_to<Variable *>,
+ CfgLocalAllocator<std::pair<Variable *const, std::vector<Inst *>>>>
+ Dependency;
+ // Not necessary for SSA, still keeping it in case this pass is
Jim Stichnoth 2016/05/19 01:35:50 reflow comment
+ // not run at the beginning. Remove to improve performace.
+
+ for (Inst &Instr : Node->getInsts()) {
+ if (Instr.isDeleted() || !llvm::isa<InstArithmetic>(&Instr))
+ continue;
+
+ auto Iter = Replacements.find(Instr.getDest());
+ if (Iter != Replacements.end()) {
+ Replacements.erase(Iter);
+ }
+
+ auto DIter = Dependency.find(Instr.getDest());
+ if (DIter != Dependency.end()) {
+ for (auto Dep : DIter->second) {
+ Seen.erase(Dep);
+ }
+ }
+
+ // replace - doing this before checking for repitions
Jim Stichnoth 2016/05/19 01:35:49 repetitions and reflow to 80-col
+ // might enable more optimizations
+ for (unsigned int i = 0; i < Instr.getSrcSize(); ++i) {
Jim Stichnoth 2016/05/19 01:35:48 SizeT
+ Operand *Opr = Instr.getSrc(i);
+ if (Variable *const Var = llvm::dyn_cast<Variable>(Opr)) {
Jim Stichnoth 2016/05/19 01:35:48 auto *
+ if (Replacements.find(Var) != Replacements.end()) {
+ Instr.replaceSource(i, Replacements[Var]);
+ }
+ }
+ }
+
+ // check for repititions
Jim Stichnoth 2016/05/19 01:35:48 repetitions
manasijm 2016/05/19 02:01:53 typo, will update on next patchset.
manasijm 2016/05/19 17:50:16 Done.
+
+ if (Seen.find(&Instr) != Seen.end()) { // seen before
+ Replacements[Instr.getDest()] = Seen[&Instr];
+ // Instr.setDeleted();
Jim Stichnoth 2016/05/19 01:35:49 remove commented-out line
manasijm 2016/05/19 17:50:16 Done.
+ } else { // new
+ Seen[&Instr] = Instr.getDest();
+
+ for (unsigned int i = 0; i < Instr.getSrcSize(); ++i) {
Jim Stichnoth 2016/05/19 01:35:49 SizeT
manasijm 2016/05/19 17:50:16 Done.
+ Operand *Opr = Instr.getSrc(i);
+ if (Variable *Var = llvm::dyn_cast<Variable>(Opr)) {
Jim Stichnoth 2016/05/19 01:35:49 auto *Var
manasijm 2016/05/19 17:50:16 Done.
+ Dependency[Var].push_back(&Instr);
+ }
+ }
+ }
+ }
+ }
+}
+
void Cfg::doArgLowering() {
TimerMarker T(TimerStack::TT_doArgLowering, this);
getTarget()->lowerArguments();
« no previous file with comments | « src/IceCfg.h ('k') | src/IceClFlags.def » ('j') | src/IceClFlags.def » ('J')

Powered by Google App Engine
This is Rietveld 408576698