[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