[PATCH] GlobalOpt enhancement optimization (hoisting of initialization code into constant global initializers).

Nick Lewycky nlewycky at google.com
Mon Aug 26 13:09:31 PDT 2013


On 26 August 2013 01:40, Puyan Lotfi <plotfi at apple.com> wrote:

> All:
>
> Attached is a patch to GlobalOpt that adds an optimization that takes user
> written constant initialization code for global variables and hoists the
> initialization values into the global initializer. This optimization is
> only done on locally linked globals of integral types (scalars, arrays, and
> structs) that are constant initialized (and zero initialized prior to
> transformation).
>
> The idea is to transform the following code:
>
> A = internal global i32 0, align 4
> isInit = internal global i1 false
>
> define i32* foobar() {
>   %.b = load i1* isInit
>   %1 = zext i1 %.b to i8
>   %2 = trunc i8 %1 to i1
>   br i1 %2, BB4, label BB3
> BB3:
>   store i32 113, i32* A, align 4
>   store i1 true, i1* isInit
>   br label %4
> BB4:
>   ret i32* A
> }
>
> Into:
>
> A = internal global i32 113, align 4
>
> define i32* @_Z8initTestv() {
>   ret i32* A
> }
>
> Could someone on the list review my changes, provide feedback, and if
> possible submit my changes?
>

You'll need to provide testcases before we can submit it for you.


> I also have some test cases I've written but I am still trying to figure
> out how to add them to llvm/test/Transforms/GlobalOpt (I don't see a
> lit.local.cfg in that directory as the docs specify).
>

+/// variables and if the condtions are right proceeds to move the init

Typo, "condtions" --> "conditions"

+/// The following is an example of code we would like to optimize:
+/// S* init () {
+///   static bool isInit = false; static S s;
+///   if (!isInit) { s.x = 42; s.y = 21; isInit = true; }
+///   return &s;
+/// }

I'm curious, is this a pattern people actually write?

+static bool TryToHoistGlobalConstantInitializers(GlobalVariable *GV) {
+  bool isInitCandidate = true;
+  BasicBlock* defBB = NULL;

"BasicBlock* defBB" --> "BasicBlock *defBB".

+  std::vector<ReturnInst*> GVreturnInstUses;
+  std::vector<StoreInst*> GVstoreInstUses;
+  std::set<Function*> initFunction; // weed out dupes

Please see
http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task.

+  // Only consider globals that are interally linked, and constant
initialized.

Typo, "interally" --> "internally".

+  // also return a referenece.

Typo, "referenece" --> "reference".

+  bool GVChanged;
+  do {
+    GVChanged = false;
+    for (Module::global_iterator GVI = M.global_begin(),
+         E = M.global_end(); GVI != E; ++GVI) {
+      if(TryToHoistGlobalConstantInitializers(GVI)) {
+        Changed |= GVChanged = true;
+        break;
+      }
+    }
+  } while (GVChanged);

No. Iterate until convergence is very bad style in the compiler because we
can't prove that it has less than O(n^2) complexity (or alternatively there
are a few places where it is O(n^2) complexity and we believe that's the
best we can do).

Also, there are a few place where your patch seems unfinished:

+  if (!attemptGlobalInitHoist) return false;
+
 //////////////////////////////////////////////////////////////////////////////

Is this a marker indicating where you wanted to split into separate
functions?

+    if (defBB->size() != 1) {
+      /// Assert?
+    }

Decide this before sending out the patch. If you decide not to assert, you
should probably include a testcase that shows why (ie., that would trip the
assert, demonstrating why the assert is wrong).

Nick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130826/eb0fdbdc/attachment.html>


More information about the llvm-commits mailing list