Author: lattner Date: Thu Aug 9 14:05:49 2007 New Revision: 40971 URL: http://llvm.org/viewvc/llvm-project?rev=40971&view=rev Log: when we see a unaligned load from an insufficiently aligned global or alloca, increase the alignment of the load, turning it into an aligned load.
This allows us to compile: #include <xmmintrin.h> __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: punpcklbw _c_0.5944, %xmm0 ret .data .lcomm _c_0.5944,16,4 # c_0.5944 instead of: _foo: movdqu _c_0.5944, %xmm1 punpcklbw %xmm1, %xmm0 ret .data .lcomm _c_0.5944,16,2 # c_0.5944 Added: llvm/trunk/test/Transforms/InstCombine/align-inc.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=40971&r1=40970&r2=40971&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Aug 9 14:05:49 2007 @@ -7492,13 +7492,23 @@ return 0; } -/// GetKnownAlignment - If the specified pointer has an alignment that we can -/// determine, return it, otherwise return 0. -static unsigned GetKnownAlignment(Value *V, TargetData *TD) { +/// GetOrEnforceKnownAlignment - If the specified pointer has an alignment that +/// we can determine, return it, otherwise return 0. If PrefAlign is specified, +/// and it is more than the alignment of the ultimate object, see if we can +/// increase the alignment of the ultimate object, making this check succeed. +static unsigned GetOrEnforceKnownAlignment(Value *V, TargetData *TD, + unsigned PrefAlign = 0) { if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { unsigned Align = GV->getAlignment(); if (Align == 0 && TD) Align = TD->getPrefTypeAlignment(GV->getType()->getElementType()); + + // If there is a large requested alignment and we can, bump up the alignment + // of the global. + if (PrefAlign > Align && GV->hasInitializer()) { + GV->setAlignment(PrefAlign); + Align = PrefAlign; + } return Align; } else if (AllocationInst *AI = dyn_cast<AllocationInst>(V)) { unsigned Align = AI->getAlignment(); @@ -7516,18 +7526,20 @@ (unsigned)TD->getABITypeAlignment(Type::Int64Ty)); } } + + // If there is a requested alignment and if this is an alloca, round up. We + // don't do this for malloc, because some systems can't respect the request. + if (PrefAlign > Align && isa<AllocaInst>(AI)) { + AI->setAlignment(PrefAlign); + Align = PrefAlign; + } return Align; } else if (isa<BitCastInst>(V) || (isa<ConstantExpr>(V) && cast<ConstantExpr>(V)->getOpcode() == Instruction::BitCast)) { - User *CI = cast<User>(V); - if (isa<PointerType>(CI->getOperand(0)->getType())) - return GetKnownAlignment(CI->getOperand(0), TD); - return 0; + return GetOrEnforceKnownAlignment(cast<User>(V)->getOperand(0), + TD, PrefAlign); } else if (User *GEPI = dyn_castGetElementPtr(V)) { - unsigned BaseAlignment = GetKnownAlignment(GEPI->getOperand(0), TD); - if (BaseAlignment == 0) return 0; - // If all indexes are zero, it is just the alignment of the base pointer. bool AllZeroOperands = true; for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i) @@ -7536,9 +7548,15 @@ AllZeroOperands = false; break; } - if (AllZeroOperands) - return BaseAlignment; - + + if (AllZeroOperands) { + // Treat this like a bitcast. + return GetOrEnforceKnownAlignment(GEPI->getOperand(0), TD, PrefAlign); + } + + unsigned BaseAlignment = GetOrEnforceKnownAlignment(GEPI->getOperand(0),TD); + if (BaseAlignment == 0) return 0; + // Otherwise, if the base alignment is >= the alignment we expect for the // base pointer type, then we know that the resultant pointer is aligned at // least as much as its type requires. @@ -7608,15 +7626,15 @@ // If we can determine a pointer alignment that is bigger than currently // set, update the alignment. if (isa<MemCpyInst>(MI) || isa<MemMoveInst>(MI)) { - unsigned Alignment1 = GetKnownAlignment(MI->getOperand(1), TD); - unsigned Alignment2 = GetKnownAlignment(MI->getOperand(2), TD); + unsigned Alignment1 = GetOrEnforceKnownAlignment(MI->getOperand(1), TD); + unsigned Alignment2 = GetOrEnforceKnownAlignment(MI->getOperand(2), TD); unsigned Align = std::min(Alignment1, Alignment2); if (MI->getAlignment()->getZExtValue() < Align) { MI->setAlignment(ConstantInt::get(Type::Int32Ty, Align)); Changed = true; } } else if (isa<MemSetInst>(MI)) { - unsigned Alignment = GetKnownAlignment(MI->getDest(), TD); + unsigned Alignment = GetOrEnforceKnownAlignment(MI->getDest(), TD); if (MI->getAlignment()->getZExtValue() < Alignment) { MI->setAlignment(ConstantInt::get(Type::Int32Ty, Alignment)); Changed = true; @@ -7634,7 +7652,7 @@ case Intrinsic::x86_sse2_loadu_dq: // Turn PPC lvx -> load if the pointer is known aligned. // Turn X86 loadups -> load if the pointer is known aligned. - if (GetKnownAlignment(II->getOperand(1), TD) >= 16) { + if (GetOrEnforceKnownAlignment(II->getOperand(1), TD, 16) >= 16) { Value *Ptr = InsertCastBefore(Instruction::BitCast, II->getOperand(1), PointerType::get(II->getType()), CI); return new LoadInst(Ptr); @@ -7643,7 +7661,7 @@ case Intrinsic::ppc_altivec_stvx: case Intrinsic::ppc_altivec_stvxl: // Turn stvx -> store if the pointer is known aligned. - if (GetKnownAlignment(II->getOperand(2), TD) >= 16) { + if (GetOrEnforceKnownAlignment(II->getOperand(2), TD, 16) >= 16) { const Type *OpPtrTy = PointerType::get(II->getOperand(1)->getType()); Value *Ptr = InsertCastBefore(Instruction::BitCast, II->getOperand(2), OpPtrTy, CI); @@ -7655,7 +7673,7 @@ case Intrinsic::x86_sse2_storeu_dq: case Intrinsic::x86_sse2_storel_dq: // Turn X86 storeu -> store if the pointer is known aligned. - if (GetKnownAlignment(II->getOperand(1), TD) >= 16) { + if (GetOrEnforceKnownAlignment(II->getOperand(1), TD, 16) >= 16) { const Type *OpPtrTy = PointerType::get(II->getOperand(2)->getType()); Value *Ptr = InsertCastBefore(Instruction::BitCast, II->getOperand(1), OpPtrTy, CI); @@ -8768,7 +8786,7 @@ Value *Op = LI.getOperand(0); // Attempt to improve the alignment. - unsigned KnownAlign = GetKnownAlignment(Op, TD); + unsigned KnownAlign = GetOrEnforceKnownAlignment(Op, TD); if (KnownAlign > LI.getAlignment()) LI.setAlignment(KnownAlign); @@ -8968,7 +8986,7 @@ } // Attempt to improve the alignment. - unsigned KnownAlign = GetKnownAlignment(Ptr, TD); + unsigned KnownAlign = GetOrEnforceKnownAlignment(Ptr, TD); if (KnownAlign > SI.getAlignment()) SI.setAlignment(KnownAlign); Added: llvm/trunk/test/Transforms/InstCombine/align-inc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/align-inc.ll?rev=40971&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/align-inc.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/align-inc.ll Thu Aug 9 14:05:49 2007 @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {GLOBAL.*align 16} +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {tmp = load} + [EMAIL PROTECTED] = internal constant [4 x i32] zeroinitializer + +declare <16 x i8> @llvm.x86.sse2.loadu.dq(i8*) + + +define <16 x i8> @foo(<2 x i64> %x) { +entry: + %tmp = tail call <16 x i8> @llvm.x86.sse2.loadu.dq( i8* bitcast ([4 x i32]* @GLOBAL to i8*) ) + ret <16 x i8> %tmp +} + _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits