[llvm-commits] [llvm] r41022 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/load2.ll
Chris Lattner
sabre at nondot.org
Sat Aug 11 11:48:49 PDT 2007
Author: lattner
Date: Sat Aug 11 13:48:48 2007
New Revision: 41022
URL: http://llvm.org/viewvc/llvm-project?rev=41022&view=rev
Log:
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
Added:
llvm/trunk/test/Transforms/InstCombine/load2.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=41022&r1=41021&r2=41022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Aug 11 13:48:48 2007
@@ -8782,6 +8782,28 @@
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 @@
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
Added: llvm/trunk/test/Transforms/InstCombine/load2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/load2.ll?rev=41022&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/load2.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/load2.ll Sat Aug 11 13:48:48 2007
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep load
+
+ at 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
+}
+
More information about the llvm-commits
mailing list