[PATCH] D22051: MergeSimilarFunctions: a code size pass to merge functions with small differences

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 6 10:10:13 PDT 2016


majnemer added a subscriber: majnemer.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:100
@@ +99,3 @@
+
+static const char *MERGED_SUFFIX = "__merged";
+
----------------
This is not a good suffix to use, it is not reserved (user code can have it).

I'd suggest `.merged` because it will demangle nicely and is impossible to get to via most normal means.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:311-324
@@ +310,16 @@
+      && (DstType->isIntegerTy() || DstType->isPointerTy())) {
+    if (InsertBefore)
+      Result = CastInst::CreatePointerCast(V, DstType, "", InsertBefore);
+    else
+      Result = CastInst::CreatePointerCast(V, DstType, "", InsertAtEnd);
+  } else if (OrigType->isIntegerTy() && DstType->isPointerTy()
+             && OrigType == IntPtrType) {
+    // Int -> Ptr
+    if (InsertBefore) {
+      Result = CastInst::Create(CastInst::IntToPtr, V, DstType, "",
+                                InsertBefore);
+    } else {
+      Result = CastInst::Create(CastInst::IntToPtr, V, DstType, "",
+                                InsertAtEnd);
+    }
+  } else {
----------------
This code is a little inconsistent regarding bracing.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:341
@@ +340,3 @@
+public:
+  ComparableFunction() : Func(0), IsNew(false) { }
+
----------------
I'd use an in-class initializer.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:349
@@ +348,3 @@
+
+  ~ComparableFunction() { }
+
----------------
Is this definition/declaration necessary?

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:351-355
@@ +350,7 @@
+
+  ComparableFunction &operator=(const ComparableFunction &that) {
+    Func = that.Func;
+    IsNew = that.IsNew;
+    return *this;
+  }
+
----------------
Would it be insufficient to ` = default;` this operator?

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:376-378
@@ +375,5 @@
+
+}
+
+namespace {
+
----------------
No need to close & reopen the namespace.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:387-388
@@ +386,4 @@
+  FunctionComparator(const DataLayout *DL, Function *F1, Function *F2)
+    : isDifferent(false), isNotMergeable(false),
+      BasicBlockCount(0), InstructionCount(0), DifferingInstructionsCount(0),
+      F1(F1), F2(F2), SimilarityMetric(0), DL(DL), ID(CurID++) {}
----------------
In-class initializer?

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:391
@@ +390,3 @@
+
+  ~FunctionComparator() {}
+
----------------
Remove this?

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:501-503
@@ +500,5 @@
+
+  switch (Ty1->getTypeID()) {
+  default:
+    llvm_unreachable("Unknown type!");
+    // Fall through in Release mode.
----------------
Hmm, this won't handle token type.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:618-645
@@ +617,30 @@
+  }
+  if (const CmpInst *CI = dyn_cast<CmpInst>(I1))
+    return CI->getPredicate() == cast<CmpInst>(I2)->getPredicate();
+  if (const CallInst *CI = dyn_cast<CallInst>(I1))
+    return CI->getCallingConv() == cast<CallInst>(I2)->getCallingConv() &&
+           CI->getAttributes() == cast<CallInst>(I2)->getAttributes();
+  if (const InvokeInst *CI = dyn_cast<InvokeInst>(I1))
+    return CI->getCallingConv() == cast<InvokeInst>(I2)->getCallingConv() &&
+           CI->getAttributes() == cast<InvokeInst>(I2)->getAttributes();
+  if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(I1))
+    return IVI->getIndices() == cast<InsertValueInst>(I2)->getIndices();
+  if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(I1))
+    return EVI->getIndices() == cast<ExtractValueInst>(I2)->getIndices();
+  if (const FenceInst *FI = dyn_cast<FenceInst>(I1))
+    return FI->getOrdering() == cast<FenceInst>(I2)->getOrdering() &&
+           FI->getSynchScope() == cast<FenceInst>(I2)->getSynchScope();
+  if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1)) {
+    const AtomicCmpXchgInst *CXI2 = cast<AtomicCmpXchgInst>(I2);
+    return CXI->isVolatile() == CXI2->isVolatile() &&
+           CXI->isWeak() == CXI2->isWeak() &&
+           CXI->getSuccessOrdering() == CXI2->getSuccessOrdering() &&
+           CXI->getFailureOrdering() == CXI2->getFailureOrdering() &&
+           CXI->getSynchScope() == CXI2->getSynchScope();
+  }
+  if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I1))
+    return RMWI->getOperation() == cast<AtomicRMWInst>(I2)->getOperation() &&
+           RMWI->isVolatile() == cast<AtomicRMWInst>(I2)->isVolatile() &&
+           RMWI->getOrdering() == cast<AtomicRMWInst>(I2)->getOrdering() &&
+           RMWI->getSynchScope() == cast<AtomicRMWInst>(I2)->getSynchScope();
+
----------------
This looks a lot like `haveSameSpecialState` in Instruction.cpp, it would be best to reuse that code.

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:1111-1117
@@ +1110,9 @@
+  SimilarFunctions.clear();
+  for (std::list<FunctionComparator *>::iterator
+        I = FunctionsToMerge.begin(), E = FunctionsToMerge.end();
+       I != E; ++I) {
+    FunctionComparator *FC = *I;
+    delete FC;
+  }
+  FunctionsToMerge.clear();
+  FunctionsToCompare.clear();
----------------
Could you use `DeleteContainerPointers` ?

================
Comment at: lib/Transforms/IPO/MergeSimilarFunctions.cpp:1375-1383
@@ +1374,11 @@
+
+// Replace G with an alias to F if possible, or else a thunk to F. Deletes G.
+void MergeSimilarFunctions::writeThunkOrAlias(Function *F, Function *G) {
+  if (isAliasCapable(G)) {
+    writeAlias(F, G);
+    return;
+  }
+
+  writeThunk(F, G);
+}
+
----------------
Why not let global-opt do this?


http://reviews.llvm.org/D22051





More information about the llvm-commits mailing list