mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-18 07:52:35 +00:00
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41022 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ace2e8ad0c
commit
8d2e88806b
@ -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
|
||||
|
11
test/Transforms/InstCombine/load2.ll
Normal file
11
test/Transforms/InstCombine/load2.ll
Normal 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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user