[llvm] r200016 - InstSimplify: Make shift, select and GEP simplifications vector-aware.

Benjamin Kramer benny.kra at googlemail.com
Fri Jan 24 09:09:54 PST 2014


Author: d0k
Date: Fri Jan 24 11:09:53 2014
New Revision: 200016

URL: http://llvm.org/viewvc/llvm-project?rev=200016&view=rev
Log:
InstSimplify: Make shift, select and GEP simplifications vector-aware.

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/compare.ll
    llvm/trunk/test/Transforms/InstSimplify/undef.ll
    llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=200016&r1=200015&r2=200016&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Fri Jan 24 11:09:53 2014
@@ -1288,6 +1288,33 @@ Value *llvm::SimplifyFRemInst(Value *Op0
   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<Constant>(Amount);
+  if (!C)
+    return false;
+
+  // X shift by undef -> undef because it may shift by the bitwidth.
+  if (isa<UndefValue>(C))
+    return true;
+
+  // Shifting by the bitwidth or more is undefined.
+  if (ConstantInt *CI = dyn_cast<ConstantInt>(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<ConstantVector>(C) || isa<ConstantDataVector>(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 Opc
   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<ConstantInt>(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 *
                                  unsigned MaxRecurse) {
   // select true, X, Y  -> X
   // select false, X, Y -> Y
-  if (ConstantInt *CB = dyn_cast<ConstantInt>(CondVal))
-    return CB->getZExtValue() ? TrueVal : FalseVal;
+  if (Constant *CB = dyn_cast<Constant>(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 *C
 /// fold the result.  If not, this returns null.
 static Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const Query &Q, unsigned) {
   // The type of the GEP pointer operand.
-  PointerType *PtrTy = dyn_cast<PointerType>(Ops[0]->getType());
-  // The GEP pointer operand is not a pointer, it's a vector of pointers.
-  if (!PtrTy)
-    return 0;
+  PointerType *PtrTy = cast<PointerType>(Ops[0]->getType()->getScalarType());
 
   // getelementptr P -> P.
   if (Ops.size() == 1)
@@ -2744,14 +2766,15 @@ static Value *SimplifyGEPInst(ArrayRef<V
     // 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<VectorType>(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<ConstantInt>(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();

Modified: llvm/trunk/test/Transforms/InstSimplify/compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/compare.ll?rev=200016&r1=200015&r2=200016&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/compare.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/compare.ll Fri Jan 24 11:09:53 2014
@@ -739,3 +739,21 @@ define i1 @non_inbounds_gep_compare2(i64
   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
+}

Modified: llvm/trunk/test/Transforms/InstSimplify/undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/undef.ll?rev=200016&r1=200015&r2=200016&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/undef.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/undef.ll Fri Jan 24 11:09:53 2014
@@ -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, <i8 8, i8 9, i8 undef, i8 -1>
+  ret <4 x i8> %b
+}

Modified: llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll?rev=200016&r1=200015&r2=200016&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/vector_gep.ll Fri Jan 24 11:09:53 2014
@@ -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> <i32 0, i32 0>
@@ -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> <i32 1, i32 1, i32 1, i32 1>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+  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> <i32 1, i32 1, i32 1, i32 1>
+  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> <i64 1, i64 2, i64 3, i64 4> to <4 x i8*>
+  %gep = getelementptr <4 x i8*> %c, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x i8*> %gep
+
+; CHECK-LABEL: @test5
+; CHECK-NEXT: ret <4 x i8*> getelementptr (<4 x i8*> <i8* inttoptr (i64 1 to i8*), i8* inttoptr (i64 2 to i8*), i8* inttoptr (i64 3 to i8*), i8* inttoptr (i64 4 to i8*)>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>)
+}





More information about the llvm-commits mailing list