Transform a load from an undef/zero global into an undef/global even if we

have complex pointer manipulation going on.  This allows us to compile
stuff like this:

__m128i foo(__m128i x){
                static const unsigned int c_0[4] = { 0, 0, 0, 0 };
                __m128i v_Zero = _mm_loadu_si128((__m128i*)c_0);
                x  = _mm_unpacklo_epi8(x,  v_Zero);
                return x;
}

into:

_foo:
        xorps   %xmm1, %xmm1
        punpcklbw       %xmm1, %xmm0
        ret

llvm-svn: 41022
This commit is contained in:
Chris Lattner 2007-08-11 18:48:48 +00:00
parent 750b3dfcf5
commit 99c8ee2977
2 changed files with 44 additions and 0 deletions

View File

@ -8782,6 +8782,28 @@ static bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) {
return false;
}
/// GetUnderlyingObject - Trace through a series of getelementptrs and bitcasts
/// until we find the underlying object a pointer is referring to or something
/// we don't understand. Note that the returned pointer may be offset from the
/// input, because we ignore GEP indices.
static Value *GetUnderlyingObject(Value *Ptr) {
while (1) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
if (CE->getOpcode() == Instruction::BitCast ||
CE->getOpcode() == Instruction::GetElementPtr)
Ptr = CE->getOperand(0);
else
return Ptr;
} else if (BitCastInst *BCI = dyn_cast<BitCastInst>(Ptr)) {
Ptr = BCI->getOperand(0);
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr)) {
Ptr = GEP->getOperand(0);
} else {
return Ptr;
}
}
}
Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
Value *Op = LI.getOperand(0);
@ -8860,6 +8882,17 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
return Res;
}
}
// If this load comes from anywhere in a constant global, and if the global
// is all undef or zero, we know what it loads.
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GetUnderlyingObject(Op))) {
if (GV->isConstant() && GV->hasInitializer()) {
if (GV->getInitializer()->isNullValue())
return ReplaceInstUsesWith(LI, Constant::getNullValue(LI.getType()));
else if (isa<UndefValue>(GV->getInitializer()))
return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType()));
}
}
if (Op->hasOneUse()) {
// Change select and PHI nodes to select values instead of addresses: this

View File

@ -0,0 +1,11 @@
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep load
@GLOBAL = internal constant [4 x i32] zeroinitializer
define <16 x i8> @foo(<2 x i64> %x) {
entry:
%tmp = load <16 x i8> * bitcast ([4 x i32]* @GLOBAL to <16 x i8>*)
ret <16 x i8> %tmp
}