diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index bf9b3857610..67b29d25a2b 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -1288,6 +1288,33 @@ Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, const DataLayout *TD, return ::SimplifyFRemInst(Op0, Op1, Query (TD, TLI, DT), RecursionLimit); } +/// isUndefShift - Returns true if a shift by \c Amount always yields undef. +static bool isUndefShift(Value *Amount) { + Constant *C = dyn_cast(Amount); + if (!C) + return false; + + // X shift by undef -> undef because it may shift by the bitwidth. + if (isa(C)) + return true; + + // Shifting by the bitwidth or more is undefined. + if (ConstantInt *CI = dyn_cast(C)) + if (CI->getValue().getLimitedValue() >= + CI->getType()->getScalarSizeInBits()) + return true; + + // If all lanes of a vector shift are undefined the whole shift is. + if (isa(C) || isa(C)) { + for (unsigned I = 0, E = C->getType()->getVectorNumElements(); I != E; ++I) + if (!isUndefShift(C->getAggregateElement(I))) + return false; + return true; + } + + return false; +} + /// SimplifyShift - Given operands for an Shl, LShr or AShr, see if we can /// fold the result. If not, this returns null. static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, @@ -1307,15 +1334,9 @@ static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, if (match(Op1, m_Zero())) return Op0; - // X shift by undef -> undef because it may shift by the bitwidth. - if (match(Op1, m_Undef())) - return Op1; - - // Shifting by the bitwidth or more is undefined. - if (ConstantInt *CI = dyn_cast(Op1)) - if (CI->getValue().getLimitedValue() >= - Op0->getType()->getScalarSizeInBits()) - return UndefValue::get(Op0->getType()); + // Fold undefined shifts. + if (isUndefShift(Op1)) + return UndefValue::get(Op0->getType()); // If the operation is with the result of a select instruction, check whether // operating on either branch of the select always yields the same value. @@ -2699,8 +2720,12 @@ static Value *SimplifySelectInst(Value *CondVal, Value *TrueVal, unsigned MaxRecurse) { // select true, X, Y -> X // select false, X, Y -> Y - if (ConstantInt *CB = dyn_cast(CondVal)) - return CB->getZExtValue() ? TrueVal : FalseVal; + if (Constant *CB = dyn_cast(CondVal)) { + if (CB->isAllOnesValue()) + return TrueVal; + if (CB->isNullValue()) + return FalseVal; + } // select C, X, X -> X if (TrueVal == FalseVal) @@ -2731,10 +2756,7 @@ Value *llvm::SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, /// fold the result. If not, this returns null. static Value *SimplifyGEPInst(ArrayRef Ops, const Query &Q, unsigned) { // The type of the GEP pointer operand. - PointerType *PtrTy = dyn_cast(Ops[0]->getType()); - // The GEP pointer operand is not a pointer, it's a vector of pointers. - if (!PtrTy) - return 0; + PointerType *PtrTy = cast(Ops[0]->getType()->getScalarType()); // getelementptr P -> P. if (Ops.size() == 1) @@ -2744,14 +2766,15 @@ static Value *SimplifyGEPInst(ArrayRef Ops, const Query &Q, unsigned) { // Compute the (pointer) type returned by the GEP instruction. Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, Ops.slice(1)); Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace()); + if (VectorType *VT = dyn_cast(Ops[0]->getType())) + GEPTy = VectorType::get(GEPTy, VT->getNumElements()); return UndefValue::get(GEPTy); } if (Ops.size() == 2) { // getelementptr P, 0 -> P. - if (ConstantInt *C = dyn_cast(Ops[1])) - if (C->isZero()) - return Ops[0]; + if (match(Ops[1], m_Zero())) + return Ops[0]; // getelementptr P, N -> P if P points to a type of zero size. if (Q.TD) { Type *Ty = PtrTy->getElementType(); diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll index abb38695e71..ee6be0458cb 100644 --- a/test/Transforms/InstSimplify/compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -739,3 +739,21 @@ define i1 @non_inbounds_gep_compare2(i64* %a) { ret i1 %cmp ; CHECK-NEXT: ret i1 true } + +define <4 x i8> @vectorselectfold(<4 x i8> %a, <4 x i8> %b) { + %false = icmp ne <4 x i8> zeroinitializer, zeroinitializer + %sel = select <4 x i1> %false, <4 x i8> %a, <4 x i8> %b + ret <4 x i8> %sel + +; CHECK-LABEL: @vectorselectfold +; CHECK-NEXT: ret <4 x i8> %b +} + +define <4 x i8> @vectorselectfold2(<4 x i8> %a, <4 x i8> %b) { + %true = icmp eq <4 x i8> zeroinitializer, zeroinitializer + %sel = select <4 x i1> %true, <4 x i8> %a, <4 x i8> %b + ret <4 x i8> %sel + +; CHECK-LABEL: @vectorselectfold +; CHECK-NEXT: ret <4 x i8> %a +} diff --git a/test/Transforms/InstSimplify/undef.ll b/test/Transforms/InstSimplify/undef.ll index 23cd50f92b4..181c2efa2dc 100644 --- a/test/Transforms/InstSimplify/undef.ll +++ b/test/Transforms/InstSimplify/undef.ll @@ -153,3 +153,10 @@ define i64 @test18(i64 %a) { %r = call i64 (i64)* undef(i64 %a) ret i64 %r } + +; CHECK-LABEL: @test19 +; CHECK: ret <4 x i8> undef +define <4 x i8> @test19(<4 x i8> %a) { + %b = shl <4 x i8> %a, + ret <4 x i8> %b +} diff --git a/test/Transforms/InstSimplify/vector_gep.ll b/test/Transforms/InstSimplify/vector_gep.ll index 5ac1ddef64f..17814637b3d 100644 --- a/test/Transforms/InstSimplify/vector_gep.ll +++ b/test/Transforms/InstSimplify/vector_gep.ll @@ -1,4 +1,7 @@ -;RUN: opt -instsimplify -disable-output < %s +; RUN: opt -S -instsimplify < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + declare void @helper(<2 x i8*>) define void @test(<2 x i8*> %a) { %A = getelementptr <2 x i8*> %a, <2 x i32> @@ -6,3 +9,47 @@ define void @test(<2 x i8*> %a) { ret void } +define <4 x i8*> @test1(<4 x i8*> %a) { + %gep = getelementptr <4 x i8*> %a, <4 x i32> zeroinitializer + ret <4 x i8*> %gep + +; CHECK-LABEL: @test1 +; CHECK-NEXT: ret <4 x i8*> %a +} + +define <4 x i8*> @test2(<4 x i8*> %a) { + %gep = getelementptr <4 x i8*> %a + ret <4 x i8*> %gep + +; CHECK-LABEL: @test2 +; CHECK-NEXT: ret <4 x i8*> %a +} + +%struct = type { double, float } + +define <4 x float*> @test3() { + %gep = getelementptr <4 x %struct*> undef, <4 x i32> , <4 x i32> + ret <4 x float*> %gep + +; CHECK-LABEL: @test3 +; CHECK-NEXT: ret <4 x float*> undef +} + +%struct.empty = type { } + +define <4 x %struct.empty*> @test4(<4 x %struct.empty*> %a) { + %gep = getelementptr <4 x %struct.empty*> %a, <4 x i32> + ret <4 x %struct.empty*> %gep + +; CHECK-LABEL: @test4 +; CHECK-NEXT: ret <4 x %struct.empty*> %a +} + +define <4 x i8*> @test5() { + %c = inttoptr <4 x i64> to <4 x i8*> + %gep = getelementptr <4 x i8*> %c, <4 x i32> + ret <4 x i8*> %gep + +; CHECK-LABEL: @test5 +; CHECK-NEXT: ret <4 x i8*> getelementptr (<4 x i8*> , <4 x i32> ) +}