[llvm] r208856 - Teach the constant folder to look through bitcast constant expressions

Hal Finkel hfinkel at anl.gov
Thu May 15 06:19:30 PDT 2014


----- Original Message -----
> From: "Chandler Carruth" <chandlerc at gmail.com>
> To: llvm-commits at cs.uiuc.edu
> Sent: Thursday, May 15, 2014 4:56:29 AM
> Subject: [llvm] r208856 - Teach the constant folder to look through bitcast	constant expressions
> 
> Author: chandlerc
> Date: Thu May 15 04:56:28 2014
> New Revision: 208856
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=208856&view=rev
> Log:
> Teach the constant folder to look through bitcast constant
> expressions
> much more effectively when trying to constant fold a load of a
> constant.
> Previously, we only handled bitcasts by trying to find a totally
> generic
> byte representation of the constant and use that. Now, we look
> through
> the bitcast to see what constant we might fold the load into, and
> then
> try to form a constant expression cast of the found value that would
> be
> equivalent to loading the value.
> 
> You might wonder why on earth this actually matters. Well, turns out
> that the Itanium ABI causes us to create a single array for a vtable
> where the first elements are virtual base offsets, followed by the
> virtual function pointers. Because the array is homogenous the
> element
> type is consistently i8* and we inttoptr the virtual base offsets
> into
> the initial elements.

Side question: I did not realize that this was going on, but how does AA do with the resulting pointers? Normally any use of inttoptr really pessimizes things.

 -Hal

> 
> Then constructors bitcast these pointers to i64 pointers prior to
> loading them. Boom, no more constant folding of virtual base offsets.
> This is the first fix to LLVM to address the *insane* performance
> Eric
> Niebler discovered with Clang on his range comprehensions[1]. There
> is
> more to come though, this doesn't *really* fix the problem fully.
> 
> [1]: http://ericniebler.com/2014/04/27/range-comprehensions/
> 
> Modified:
>     llvm/trunk/lib/Analysis/ConstantFolding.cpp
>     llvm/trunk/test/Transforms/ConstProp/loads.ll
> 
> Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=208856&r1=208855&r2=208856&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
> +++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Thu May 15 04:56:28
> 2014
> @@ -466,6 +466,52 @@ static Constant *FoldReinterpretLoadFrom
>    return ConstantInt::get(IntType->getContext(), ResultVal);
>  }
>  
> +static Constant *ConstantFoldLoadThroughBitcast(ConstantExpr *CE,
> +                                                const DataLayout
> *DL) {
> +  if (!DL)
> +    return nullptr;
> +  auto *DestPtrTy = dyn_cast<PointerType>(CE->getType());
> +  if (!DestPtrTy)
> +    return nullptr;
> +  Type *DestTy = DestPtrTy->getElementType();
> +
> +  Constant *C = ConstantFoldLoadFromConstPtr(CE->getOperand(0), DL);
> +  if (!C)
> +    return nullptr;
> +
> +  do {
> +    Type *SrcTy = C->getType();
> +
> +    // If the type sizes are the same and a cast is legal, just
> directly
> +    // cast the constant.
> +    if (DL->getTypeSizeInBits(DestTy) ==
> DL->getTypeSizeInBits(SrcTy)) {
> +      Instruction::CastOps Cast = Instruction::BitCast;
> +      // If we are going from a pointer to int or vice versa, we
> spell the cast
> +      // differently.
> +      if (SrcTy->isIntegerTy() && DestTy->isPointerTy())
> +        Cast = Instruction::IntToPtr;
> +      else if (SrcTy->isPointerTy() && DestTy->isIntegerTy())
> +        Cast = Instruction::PtrToInt;
> +
> +      if (CastInst::castIsValid(Cast, C, DestTy))
> +        return ConstantExpr::getCast(Cast, C, DestTy);
> +    }
> +
> +    // If this isn't an aggregate type, there is nothing we can do
> to drill down
> +    // and find a bitcastable constant.
> +    if (!SrcTy->isAggregateType())
> +      return nullptr;
> +
> +    // We're simulating a load through a pointer that was bitcast to
> point to
> +    // a different type, so we can try to walk down through the
> initial
> +    // elements of an aggregate to see if some part of th e
> aggregate is
> +    // castable to implement the "load" semantic model.
> +    C = C->getAggregateElement(0u);
> +  } while (C);
> +
> +  return nullptr;
> +}
> +
>  /// ConstantFoldLoadFromConstPtr - Return the value that a load from
>  C would
>  /// produce if it is constant and determinable.  If this is not
>  determinable,
>  /// return null.
> @@ -491,6 +537,10 @@ Constant *llvm::ConstantFoldLoadFromCons
>      }
>    }
>  
> +  if (CE->getOpcode() == Instruction::BitCast)
> +    if (Constant *LoadedC = ConstantFoldLoadThroughBitcast(CE, TD))
> +      return LoadedC;
> +
>    // Instead of loading constant c string, use corresponding integer
>    value
>    // directly if string length is small enough.
>    StringRef Str;
> 
> Modified: llvm/trunk/test/Transforms/ConstProp/loads.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ConstProp/loads.ll?rev=208856&r1=208855&r2=208856&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/ConstProp/loads.ll (original)
> +++ llvm/trunk/test/Transforms/ConstProp/loads.ll Thu May 15 04:56:28
> 2014
> @@ -219,3 +219,37 @@ entry:
>  ; BE-LABEL: @test15(
>  ; BE: ret i64 2
>  }
> +
> + at gv7 = constant [4 x i8*] [i8* null, i8* inttoptr (i64 -14 to i8*),
> i8* null, i8* null]
> +define i64 @test16.1() {
> +  %v = load i64* bitcast ([4 x i8*]* @gv7 to i64*), align 8
> +  ret i64 %v
> +
> +; LE-LABEL: @test16.1(
> +; LE: ret i64 0
> +
> +; BE-LABEL: @test16.1(
> +; BE: ret i64 0
> +}
> +
> +define i64 @test16.2() {
> +  %v = load i64* bitcast (i8** getelementptr inbounds ([4 x i8*]*
> @gv7, i64 0, i64 1) to i64*), align 8
> +  ret i64 %v
> +
> +; LE-LABEL: @test16.2(
> +; LE: ret i64 -14
> +
> +; BE-LABEL: @test16.2(
> +; BE: ret i64 -14
> +}
> +
> +define i64 @test16.3() {
> +  %v = load i64* bitcast (i8** getelementptr inbounds ([4 x i8*]*
> @gv7, i64 0, i64 2) to i64*), align 8
> +  ret i64 %v
> +
> +; LE-LABEL: @test16.3(
> +; LE: ret i64 0
> +
> +; BE-LABEL: @test16.3(
> +; BE: ret i64 0
> +}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list