From acb8d9fbe3853394a2537985349993580309b8cd Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 3 Dec 2012 19:59:23 +0000 Subject: [PATCH] Eliminate redundant bitwise operations when using a llvm/ADT/PointerUnion. For comparison, with this code sample: PointerUnion Data; PointerUnion foo1() { Data = new int; return new int; } PointerUnion foo2() { Data = new char; return new char; } Before this patch we would get: define i64 @_Z4foo1v() uwtable ssp { %1 = tail call noalias i8* @_Znwm(i64 4) %2 = ptrtoint i8* %1 to i64 %3 = load i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %4 = and i64 %3, 1 %.masked.i = and i64 %2, -3 %5 = or i64 %4, %.masked.i store i64 %5, i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %6 = tail call noalias i8* @_Znwm(i64 4) %7 = ptrtoint i8* %6 to i64 %8 = and i64 %7, -3 ret i64 %8 } define i64 @_Z4foo2v() uwtable ssp { %1 = tail call noalias i8* @_Znwm(i64 1) %2 = ptrtoint i8* %1 to i64 %3 = load i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %4 = and i64 %3, 1 %5 = or i64 %2, %4 %6 = or i64 %5, 2 store i64 %6, i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %7 = tail call noalias i8* @_Znwm(i64 1) %8 = ptrtoint i8* %7 to i64 %9 = or i64 %8, 2 ret i64 %9 } After the patch: define i64 @_Z4foo1v() uwtable ssp { %1 = tail call noalias i8* @_Znwm(i64 4) %2 = ptrtoint i8* %1 to i64 store i64 %2, i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %3 = tail call noalias i8* @_Znwm(i64 4) %4 = ptrtoint i8* %3 to i64 ret i64 %4 } declare noalias i8* @_Znwm(i64) define i64 @_Z4foo2v() uwtable ssp { %1 = tail call noalias i8* @_Znwm(i64 1) %2 = ptrtoint i8* %1 to i64 %3 = or i64 %2, 2 store i64 %3, i64* getelementptr inbounds (%"class.llvm::PointerUnion"* @Data, i64 0, i32 0, i32 0), align 8 %4 = tail call noalias i8* @_Znwm(i64 1) %5 = ptrtoint i8* %4 to i64 %6 = or i64 %5, 2 ret i64 %6 } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169147 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/PointerIntPair.h | 27 ++++++++++++++++++++++++--- include/llvm/ADT/PointerUnion.h | 21 ++++++++------------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 71c379bad5a..cce2efb6ac9 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -57,11 +57,13 @@ class PointerIntPair { }; public: PointerIntPair() : Value(0) {} - PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + PointerIntPair(PointerTy Ptr, IntType Int) { assert(IntBits <= PtrTraits::NumLowBitsAvailable && "PointerIntPair formed with integer size too large for pointer"); - setPointer(Ptr); - setInt(Int); + setPointerAndInt(Ptr, Int); + } + explicit PointerIntPair(PointerTy Ptr) { + initWithPointer(Ptr); } PointerTy getPointer() const { @@ -91,6 +93,25 @@ public: Value |= IntVal << IntShift; // Set new integer. } + void initWithPointer(PointerTy Ptr) { + intptr_t PtrVal + = reinterpret_cast(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + Value = PtrVal; + } + + void setPointerAndInt(PointerTy Ptr, IntType Int) { + intptr_t PtrVal + = reinterpret_cast(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + intptr_t IntVal = Int; + assert(IntVal < (1 << IntBits) && "Integer too large for field"); + + Value = PtrVal | (IntVal << IntShift); + } + PointerTy const *getAddrOfPointer() const { return const_cast(this)->getAddrOfPointer(); } diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index a9e86d22002..f42515ac77a 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -95,15 +95,11 @@ namespace llvm { public: PointerUnion() {} - PointerUnion(PT1 V) { - Val.setPointer( - const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); - Val.setInt(0); + PointerUnion(PT1 V) : Val( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))) { } - PointerUnion(PT2 V) { - Val.setPointer( - const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); - Val.setInt(1); + PointerUnion(PT2 V) : Val( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V)), 1) { } /// isNull - Return true if the pointer held in the union is null, @@ -160,15 +156,14 @@ namespace llvm { /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. const PointerUnion &operator=(const PT1 &RHS) { - Val.setPointer( + Val.initWithPointer( const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); - Val.setInt(0); return *this; } const PointerUnion &operator=(const PT2 &RHS) { - Val.setPointer( - const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); - Val.setInt(1); + Val.setPointerAndInt( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS)), + 1); return *this; } -- 2.34.1