[llvm] r218337 - GlobalOpt: Preserve comdats of unoptimized initializers

Rafael EspĂ­ndola rafael.espindola at gmail.com
Mon Sep 29 09:18:26 PDT 2014


Thanks!

On Tuesday, September 23, 2014, Reid Kleckner <reid at kleckner.net> wrote:

> Author: rnk
> Date: Tue Sep 23 17:33:01 2014
> New Revision: 218337
>
> URL: http://llvm.org/viewvc/llvm-project?rev=218337&view=rev
> Log:
> GlobalOpt: Preserve comdats of unoptimized initializers
>
> Rather than slurping in and splatting out the whole ctor list, preserve
> the existing array entries without trying to understand them.  Only
> remove the entries that we know we can optimize away.  This way we don't
> need to wire through priority and comdats or anything else we might add.
>
> Fixes a linker issue where the .init_array or .ctors entry would point
> to discarded initialization code if the comdat group from the TU with
> the faulty global_ctors entry was dropped.
>
> Added:
>     llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll
> Modified:
>     llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp
>
> Modified: llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp?rev=218337&r1=218336&r2=218337&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/CtorUtils.cpp Tue Sep 23 17:33:01 2014
> @@ -11,6 +11,7 @@
>  //
>
>  //===----------------------------------------------------------------------===//
>
> +#include "llvm/ADT/BitVector.h"
>  #include "llvm/Transforms/Utils/CtorUtils.h"
>  #include "llvm/IR/Constants.h"
>  #include "llvm/IR/Function.h"
> @@ -24,41 +25,22 @@
>  namespace llvm {
>
>  namespace {
> -/// Given a specified llvm.global_ctors list, install the
> -/// specified array.
> -void installGlobalCtors(GlobalVariable *GCL,
> -                        const std::vector<Function *> &Ctors) {
> -  // If we made a change, reassemble the initializer list.
> -  Constant *CSVals[3];
> -
> -  StructType *StructTy =
> -
> cast<StructType>(GCL->getType()->getElementType()->getArrayElementType());
> -
> -  // Create the new init list.
> -  std::vector<Constant *> CAList;
> -  for (Function *F : Ctors) {
> -    Type *Int32Ty = Type::getInt32Ty(GCL->getContext());
> -    if (F) {
> -      CSVals[0] = ConstantInt::get(Int32Ty, 65535);
> -      CSVals[1] = F;
> -    } else {
> -      CSVals[0] = ConstantInt::get(Int32Ty, 0x7fffffff);
> -      CSVals[1] = Constant::getNullValue(StructTy->getElementType(1));
> -    }
> -    // FIXME: Only allow the 3-field form in LLVM 4.0.
> -    size_t NumElts = StructTy->getNumElements();
> -    if (NumElts > 2)
> -      CSVals[2] = Constant::getNullValue(StructTy->getElementType(2));
> -    CAList.push_back(
> -        ConstantStruct::get(StructTy, makeArrayRef(CSVals, NumElts)));
> -  }
> -
> -  // Create the array initializer.
> -  Constant *CA =
> -      ConstantArray::get(ArrayType::get(StructTy, CAList.size()), CAList);
> +/// Given a specified llvm.global_ctors list, remove the listed elements.
> +void removeGlobalCtors(GlobalVariable *GCL, const BitVector
> &CtorsToRemove) {
> +  // Filter out the initializer elements to remove.
> +  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
> +  SmallVector<Constant *, 10> CAList;
> +  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
> +    if (!CtorsToRemove.test(I))
> +      CAList.push_back(OldCA->getOperand(I));
> +
> +  // Create the new array initializer.
> +  ArrayType *ATy =
> +      ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
> +  Constant *CA = ConstantArray::get(ATy, CAList);
>
>    // If we didn't change the number of elements, don't create a new GV.
> -  if (CA->getType() == GCL->getInitializer()->getType()) {
> +  if (CA->getType() == OldCA->getType()) {
>      GCL->setInitializer(CA);
>      return;
>    }
> @@ -82,7 +64,7 @@ void installGlobalCtors(GlobalVariable *
>
>  /// Given a llvm.global_ctors list that we can understand,
>  /// return a list of the functions and null terminator as a vector.
> -std::vector<Function*> parseGlobalCtors(GlobalVariable *GV) {
> +std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
>    if (GV->getInitializer()->isNullValue())
>      return std::vector<Function *>();
>    ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
> @@ -147,17 +129,15 @@ bool optimizeGlobalCtorsList(Module &M,
>    bool MadeChange = false;
>
>    // Loop over global ctors, optimizing them when we can.
> -  for (unsigned i = 0; i != Ctors.size(); ++i) {
> +  unsigned NumCtors = Ctors.size();
> +  BitVector CtorsToRemove(NumCtors);
> +  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
>      Function *F = Ctors[i];
>      // Found a null terminator in the middle of the list, prune off the
> rest of
>      // the list.
> -    if (!F) {
> -      if (i != Ctors.size() - 1) {
> -        Ctors.resize(i + 1);
> -        MadeChange = true;
> -      }
> -      break;
> -    }
> +    if (!F)
> +      continue;
> +
>      DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
>
>      // We cannot simplify external ctor functions.
> @@ -166,9 +146,10 @@ bool optimizeGlobalCtorsList(Module &M,
>
>      // If we can evaluate the ctor at compile time, do.
>      if (ShouldRemove(F)) {
> -      Ctors.erase(Ctors.begin() + i);
> +      Ctors[i] = nullptr;
> +      CtorsToRemove.set(i);
> +      NumCtors--;
>        MadeChange = true;
> -      --i;
>        continue;
>      }
>    }
> @@ -176,7 +157,7 @@ bool optimizeGlobalCtorsList(Module &M,
>    if (!MadeChange)
>      return false;
>
> -  installGlobalCtors(GlobalCtors, Ctors);
> +  removeGlobalCtors(GlobalCtors, CtorsToRemove);
>    return true;
>  }
>
>
> Added: llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll?rev=218337&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll (added)
> +++ llvm/trunk/test/Transforms/GlobalOpt/preserve-comdats.ll Tue Sep 23
> 17:33:01 2014
> @@ -0,0 +1,37 @@
> +; RUN: opt -globalopt -S < %s | FileCheck %s
> +
> +$comdat_global = comdat any
> +
> + at comdat_global = weak_odr global i8 0, comdat $comdat_global
> + at simple_global = internal global i8 0
> +; CHECK: @comdat_global = weak_odr global i8 0, comdat $comdat_global
> +; CHECK: @simple_global = internal global i8 42
> +
> + at llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }] [
> +    { i32, void ()*, i8* } { i32 65535, void ()* @init_comdat_global, i8*
> @comdat_global },
> +    { i32, void ()*, i8* } { i32 65535, void ()* @init_simple_global, i8*
> null }
> +]
> +; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8*
> }]
> +; CHECK: [{ i32, void ()*, i8* } { i32 65535, void ()*
> @init_comdat_global, i8* @comdat_global }]
> +
> +define void @init_comdat_global() {
> +  store i8 42, i8* @comdat_global
> +  ret void
> +}
> +; CHECK: define void @init_comdat_global()
> +
> +define internal void @init_simple_global() comdat $comdat_global {
> +  store i8 42, i8* @simple_global
> +  ret void
> +}
> +; CHECK-NOT: @init_simple_global()
> +
> +define i8* @use_simple() {
> +  ret i8* @simple_global
> +}
> +; CHECK: define i8* @use_simple()
> +
> +define i8* @use_comdat() {
> +  ret i8* @comdat_global
> +}
> +; CHECK: define i8* @use_comdat()
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu <javascript:;>
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140929/c2e94a4a/attachment.html>


More information about the llvm-commits mailing list