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

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: Modify test for x8632 and 64 to check with and without local-cse 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
Index: src/IceCfg.cpp
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index f71737994aba701b4a75e6dcd296b11a5f66fed9..4c45faa1ac6764ce9d0a4c3a90a494ff5f3d57d5 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -507,6 +507,122 @@ void Cfg::shuffleNodes() {
dump("After basic block shuffling");
}
+void Cfg::localCSE() {
Jim Stichnoth 2016/05/23 16:52:56 I'd like to have a comment here briefly describing
manasijm 2016/05/23 23:13:30 Done.
+ 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 (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
+ auto *Opnd = Instr->getSrc(i);
+ if (auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
+ Result ^= std::hash<SizeT>()(Var->getIndex());
Jim Stichnoth 2016/05/23 16:52:57 This is a repetition of the VariableHash implement
manasijm 2016/05/23 23:13:30 Done.
+ } else if (Constant *Const = llvm::dyn_cast<Constant>(Opnd)) {
+ Result ^= std::hash<Constant *>()(Const);
+ // TODO : get Value of ConstantPrimitive
Jim Stichnoth 2016/05/23 16:52:57 If I understand this correctly, your hash function
manasijm 2016/05/23 23:13:30 Done.
+ } else
+ Result ^= std::hash<Operand *>()(Opnd);
+ }
+ return Result;
+ }
+ };
+ struct InstEq {
+ bool srcEq(const Operand *A, const Operand *B) const {
+ if (!(llvm::isa<Variable>(A) || (llvm::isa<Constant>(A))) ||
Jim Stichnoth 2016/05/23 16:52:56 This is really hard to read/understand. How about
manasijm 2016/05/23 23:13:30 Done.
+ !(llvm::isa<Variable>(B) || (llvm::isa<Constant>(B))))
+ return false;
+ // No reason this has to an error. Returning false just disables the cse
Jim Stichnoth 2016/05/23 16:52:57 "has to an error" ==> "has to be an error" ? And
+ // optimization for this particular case
+ return (A == B);
+ }
+ bool operator()(const Inst *InstrA, const Inst *InstrB) const {
+ if ((InstrA->getKind() != InstrB->getKind()) ||
+ (InstrA->getSrcSize() != InstrB->getSrcSize()))
+ return false;
+
+ if (auto *A = llvm::dyn_cast<InstArithmetic>(InstrA)) {
+ auto B = llvm::cast<InstArithmetic>(InstrB);
Jim Stichnoth 2016/05/23 16:52:56 auto *
manasijm 2016/05/23 23:13:30 Done.
+ // A, B are guranteed to be of the same 'kind' at this point
Jim Stichnoth 2016/05/23 16:52:57 guaranteed
manasijm 2016/05/23 23:13:30 Done.
+ // So, dyn_Cast is not needed
Jim Stichnoth 2016/05/23 16:52:57 dyn_cast
manasijm 2016/05/23 23:13:30 Done.
+ if (A->getOp() != B->getOp())
+ return false;
+ }
+ // Does not enter loop if different kind or number of operands
+ for (SizeT i = 0; i < InstrA->getSrcSize(); ++i) {
+ if (!srcEq(InstrA->getSrc(i), InstrB->getSrc(i)))
+ return false;
+ }
+ return true;
+ }
+ };
+ struct VariableHash {
+ size_t operator()(const Variable *Var) const {
+ return std::hash<SizeT>()(Var->getIndex());
+ }
+ };
+ for (CfgNode *Node : getNodes()) {
+ CfgUnorderedSet<Inst *, InstHash, InstEq> Seen;
+
+ CfgUnorderedMap<Variable *, Variable *, VariableHash> Replacements;
+ // Combining the above two into a single data structure might consume less
+ // memory but will be slower i.e map of Instruction -> Set of Variables
+
+ CfgUnorderedMap<Variable *, std::vector<Inst *>, VariableHash> Dependency;
+ // Not necessary for SSA, still keeping it in case this pass is not run at
+ // the beginning. Remove to improve performace.
+
+ for (Inst &Instr : Node->getInsts()) {
+ if (Instr.isDeleted() || !llvm::isa<InstArithmetic>(&Instr))
+ continue;
+
+ // Invalidate replacements
+ auto Iter = Replacements.find(Instr.getDest());
+ if (Iter != Replacements.end()) {
+ Replacements.erase(Iter);
+ }
+
+ // Invalidate 'seen' instructions whose operands were just updated.
+ auto DepIter = Dependency.find(Instr.getDest());
+ if (DepIter != Dependency.end()) {
+ for (auto Dep : DepIter->second) {
Jim Stichnoth 2016/05/23 16:52:57 I think this use of "auto" is getting too deep for
manasijm 2016/05/23 23:13:30 Done.
+ Seen.erase(Dep);
+ }
+ }
+ // The above two can be removed if SSA is assumed.
+
+ // Replace - doing this before checking for repetitions might enable more
+ // optimizations
+ for (SizeT i = 0; i < Instr.getSrcSize(); ++i) {
+ auto *Opnd = Instr.getSrc(i);
+ if (Variable *const Var = llvm::dyn_cast<Variable>(Opnd)) {
Jim Stichnoth 2016/05/23 16:52:57 "Variable *const Var" just means that the value of
manasijm 2016/05/23 23:13:30 Artifact from first patch set.
+ if (Replacements.find(Var) != Replacements.end()) {
+ Instr.replaceSource(i, Replacements[Var]);
+ }
+ }
+ }
+
+ // Check for repetitions
+ auto SeenIter = Seen.find(&Instr);
+ if (SeenIter != Seen.end()) { // seen before
+ const Inst *Found = *SeenIter;
+ Replacements[Instr.getDest()] = Found->getDest();
+ } else { // new
+ Seen.insert(&Instr);
+
+ // Update dependencies
+ for (SizeT i = 0; i < Instr.getSrcSize(); ++i) {
+ auto *Opnd = Instr.getSrc(i);
+ if (auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
+ 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') | tests_lit/llvm2ice_tests/local-cse.ll » ('J')

Powered by Google App Engine
This is Rietveld 408576698