Eliminate redundant bitwise operations when using a llvm/ADT/PointerUnion.

For comparison, with this code sample:

PointerUnion<int *, char *> Data;
PointerUnion<int *, char *> foo1() {
	Data = new int;
	return new int;
}
PointerUnion<int *, char *> 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
This commit is contained in:
Argyrios Kyrtzidis 2012-12-03 19:59:23 +00:00
parent ba917da3d3
commit acb8d9fbe3
2 changed files with 32 additions and 16 deletions

View File

@ -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<intptr_t>(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<intptr_t>(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<PointerIntPair *>(this)->getAddrOfPointer();
}

View File

@ -95,15 +95,11 @@ namespace llvm {
public:
PointerUnion() {}
PointerUnion(PT1 V) {
Val.setPointer(
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
Val.setInt(0);
PointerUnion(PT1 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
}
PointerUnion(PT2 V) {
Val.setPointer(
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
Val.setInt(1);
PointerUnion(PT2 V) : Val(
const_cast<void *>(PointerLikeTypeTraits<PT2>::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<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
Val.setInt(0);
return *this;
}
const PointerUnion &operator=(const PT2 &RHS) {
Val.setPointer(
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
Val.setInt(1);
Val.setPointerAndInt(
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
1);
return *this;
}