[llvm] 30201d3 - [ValueTracking] Let isGuaranteedNotToBeUndefOrPoison use canCreateUndefOrPoison

Juneyoung Lee via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 19 17:32:55 PDT 2020


Author: Juneyoung Lee
Date: 2020-07-20T09:21:39+09:00
New Revision: 30201d3b611f034214e6e1bc8c8faae7d1246ec8

URL: https://github.com/llvm/llvm-project/commit/30201d3b611f034214e6e1bc8c8faae7d1246ec8
DIFF: https://github.com/llvm/llvm-project/commit/30201d3b611f034214e6e1bc8c8faae7d1246ec8.diff

LOG: [ValueTracking] Let isGuaranteedNotToBeUndefOrPoison use canCreateUndefOrPoison

 This patch adds support more operations.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D83926

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ValueTracking.h
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll
    llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll
    llvm/test/Transforms/InstSimplify/freeze-noundef.ll
    llvm/test/Transforms/InstSimplify/freeze.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 178f61563cd7..ce5aea2e8d34 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -607,7 +607,8 @@ class Value;
   bool canCreatePoison(const Operator *Op);
 
   /// Return true if this function can prove that V is never undef value
-  /// or poison value.
+  /// or poison value. If V is an aggregate value or vector, check whether all
+  /// elements (except padding) are not undef or poison.
   /// Note that this is 
diff erent from canCreateUndefOrPoison because the
   /// function assumes Op's operands are not poison/undef.
   ///

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 380022c10ace..ed22718d866e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4779,23 +4779,13 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V,
   if (Depth >= MaxDepth)
     return false;
 
-  // If the value is a freeze instruction, then it can never
-  // be undef or poison.
-  if (isa<FreezeInst>(V))
-    return true;
-  // TODO: Some instructions are guaranteed to return neither undef
-  // nor poison if their arguments are not poison/undef.
-
-  if (auto *A = dyn_cast<Argument>(V)) {
-    // NoUndef does not guarantee that paddings are not undef.
+  if (const auto *A = dyn_cast<Argument>(V)) {
     if (A->hasAttribute(Attribute::NoUndef))
       return true;
   }
 
   if (auto *C = dyn_cast<Constant>(V)) {
-    // TODO: We can analyze ConstExpr by opcode to determine if there is any
-    //       possibility of poison.
-    if (isa<UndefValue>(C) || isa<ConstantExpr>(C))
+    if (isa<UndefValue>(C))
       return false;
 
     if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(V) ||
@@ -4804,9 +4794,6 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V,
 
     if (C->getType()->isVectorTy())
       return !C->containsUndefElement() && !C->containsConstantExpression();
-
-    // TODO: Recursively analyze aggregates or other constants.
-    return false;
   }
 
   // Strip cast operations from a pointer value.
@@ -4826,31 +4813,25 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V,
     return isGuaranteedNotToBeUndefOrPoison(V, CtxI, DT, Depth + 1);
   };
 
-  if (auto *I = dyn_cast<Instruction>(V)) {
-    switch (I->getOpcode()) {
-    case Instruction::GetElementPtr: {
-      auto *GEPI = dyn_cast<GetElementPtrInst>(I);
-      if (!GEPI->isInBounds() && llvm::all_of(GEPI->operands(), OpCheck))
-        return true;
-      break;
-    }
-    case Instruction::FCmp: {
-      auto *FI = dyn_cast<FCmpInst>(I);
-      if (FI->getFastMathFlags().none() &&
-          llvm::all_of(FI->operands(), OpCheck))
-        return true;
-      break;
-    }
-    case Instruction::BitCast:
-    case Instruction::PHI:
-    case Instruction::ICmp:
-      if (llvm::all_of(I->operands(), OpCheck))
+  if (auto *Opr = dyn_cast<Operator>(V)) {
+    // If the value is a freeze instruction, then it can never
+    // be undef or poison.
+    if (isa<FreezeInst>(V))
+      return true;
+
+    if (const auto *CB = dyn_cast<CallBase>(V)) {
+      if (CB->hasRetAttr(Attribute::NoUndef))
         return true;
-      break;
-    default:
-      break;
     }
 
+    if (canCreateUndefOrPoison(Opr))
+      return false;
+
+    if (all_of(Opr->operands(), OpCheck))
+      return true;
+  }
+
+  if (auto *I = dyn_cast<Instruction>(V)) {
     if (programUndefinedIfPoison(I) && I->getType()->isIntegerTy(1))
       // Note: once we have an agreement that poison is a value-wise concept,
       // we can remove the isIntegerTy(1) constraint.

diff  --git a/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll b/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll
index 4b640b98e302..277d3de7c712 100644
--- a/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll
+++ b/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll
@@ -106,12 +106,11 @@ define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) {
 ; CHECK-NEXT:    [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[T1]], [[T0_FROZEN]]
 ; CHECK-NEXT:    [[T3_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
-; CHECK-NEXT:    [[T3_DECOMPOSED_FROZEN:%.*]] = freeze i32 [[T3_DECOMPOSED]]
 ; CHECK-NEXT:    [[Y_FROZEN:%.*]] = freeze i32 [[Y]]
-; CHECK-NEXT:    [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED_FROZEN]], [[Y_FROZEN]]
+; CHECK-NEXT:    [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y_FROZEN]]
 ; CHECK-NEXT:    [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = mul i32 [[T4]], [[Y_FROZEN]]
-; CHECK-NEXT:    [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED_FROZEN]], [[TMP2]]
+; CHECK-NEXT:    [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]]
 ; CHECK-NEXT:    ret i32 [[T6_DECOMPOSED]]
 ;
   %t0 = mul nsw i32 %Z, %Y

diff  --git a/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll
index 3692d7d224f1..9e6d85d9920a 100644
--- a/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll
+++ b/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll
@@ -175,12 +175,11 @@ define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) {
 ; CHECK-NEXT:    [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[T1]], [[T0_FROZEN]]
 ; CHECK-NEXT:    [[T3_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
-; CHECK-NEXT:    [[T3_DECOMPOSED_FROZEN:%.*]] = freeze i32 [[T3_DECOMPOSED]]
 ; CHECK-NEXT:    [[Y_FROZEN:%.*]] = freeze i32 [[Y]]
-; CHECK-NEXT:    [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED_FROZEN]], [[Y_FROZEN]]
+; CHECK-NEXT:    [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y_FROZEN]]
 ; CHECK-NEXT:    [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
 ; CHECK-NEXT:    [[TMP2:%.*]] = mul i32 [[T4]], [[Y_FROZEN]]
-; CHECK-NEXT:    [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED_FROZEN]], [[TMP2]]
+; CHECK-NEXT:    [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]]
 ; CHECK-NEXT:    ret i32 [[T6_DECOMPOSED]]
 ;
   %t0 = mul nsw i32 %Z, %Y

diff  --git a/llvm/test/Transforms/InstSimplify/freeze-noundef.ll b/llvm/test/Transforms/InstSimplify/freeze-noundef.ll
index 424477891058..f2e897b507e3 100644
--- a/llvm/test/Transforms/InstSimplify/freeze-noundef.ll
+++ b/llvm/test/Transforms/InstSimplify/freeze-noundef.ll
@@ -19,12 +19,10 @@ define i1 @icmp(i8 noundef %x, i8 noundef %y) {
   ret i1 %f
 }
 
-; TODO: should look into binary operations
 define i1 @or(i1 noundef %x, i1 noundef %x2) {
 ; CHECK-LABEL: @or(
 ; CHECK-NEXT:    [[Y:%.*]] = or i1 [[X:%.*]], [[X2:%.*]]
-; CHECK-NEXT:    [[Z:%.*]] = freeze i1 [[Y]]
-; CHECK-NEXT:    ret i1 [[Z]]
+; CHECK-NEXT:    ret i1 [[Y]]
 ;
   %y = or i1 %x, %x2
   %z = freeze i1 %y
@@ -42,12 +40,10 @@ define i1 @or2(i1 noundef %x, i1 %x2) {
   ret i1 %z
 }
 
-; TODO: should look into binary operations
 define i8 @add(i8 noundef %x) {
 ; CHECK-LABEL: @add(
 ; CHECK-NEXT:    [[Y:%.*]] = add i8 [[X:%.*]], 1
-; CHECK-NEXT:    [[Z:%.*]] = freeze i8 [[Y]]
-; CHECK-NEXT:    ret i8 [[Z]]
+; CHECK-NEXT:    ret i8 [[Y]]
 ;
   %y = add i8 %x, 1
   %z = freeze i8 %y
@@ -77,21 +73,18 @@ define {i8, i32} @aggr({i8, i32} noundef %x) {
 define i32 @extract({i8, i32} noundef %x) {
 ; CHECK-LABEL: @extract(
 ; CHECK-NEXT:    [[Y:%.*]] = extractvalue { i8, i32 } [[X:%.*]], 1
-; CHECK-NEXT:    [[Z:%.*]] = freeze i32 [[Y]]
-; CHECK-NEXT:    ret i32 [[Z]]
+; CHECK-NEXT:    ret i32 [[Y]]
 ;
   %y = extractvalue {i8, i32} %x, 1
   %z = freeze i32 %y
   ret i32 %z
 }
 
-; TODO: should look into extract operations
 define i32 @extract2({i8, {i8, i32}} noundef %x) {
 ; CHECK-LABEL: @extract2(
 ; CHECK-NEXT:    [[Y:%.*]] = extractvalue { i8, { i8, i32 } } [[X:%.*]], 1
 ; CHECK-NEXT:    [[Z:%.*]] = extractvalue { i8, i32 } [[Y]], 1
-; CHECK-NEXT:    [[W:%.*]] = freeze i32 [[Z]]
-; CHECK-NEXT:    ret i32 [[W]]
+; CHECK-NEXT:    ret i32 [[Z]]
 ;
   %y = extractvalue {i8, {i8, i32}} %x, 1
   %z = extractvalue {i8, i32} %y, 1

diff  --git a/llvm/test/Transforms/InstSimplify/freeze.ll b/llvm/test/Transforms/InstSimplify/freeze.ll
index 306f293f7be7..8659687f07e7 100644
--- a/llvm/test/Transforms/InstSimplify/freeze.ll
+++ b/llvm/test/Transforms/InstSimplify/freeze.ll
@@ -116,13 +116,28 @@ define <2 x float> @constvector_FP_noopt() {
 
 define float @constant_expr() {
 ; CHECK-LABEL: @constant_expr(
-; CHECK-NEXT:    [[R:%.*]] = freeze float bitcast (i32 ptrtoint (i16* @g to i32) to float)
-; CHECK-NEXT:    ret float [[R]]
+; CHECK-NEXT:    ret float bitcast (i32 ptrtoint (i16* @g to i32) to float)
 ;
   %r = freeze float bitcast (i32 ptrtoint (i16* @g to i32) to float)
   ret float %r
 }
 
+define i8* @constant_expr2() {
+; CHECK-LABEL: @constant_expr2(
+; CHECK-NEXT:    ret i8* bitcast (i16* @g to i8*)
+;
+  %r = freeze i8* bitcast (i16* @g to i8*)
+  ret i8* %r
+}
+
+define i32* @constant_expr3() {
+; CHECK-LABEL: @constant_expr3(
+; CHECK-NEXT:    ret i32* getelementptr (i32, i32* @glb, i64 3)
+;
+  %r = freeze i32* getelementptr (i32, i32* @glb, i64 3)
+  ret i32* %r
+}
+
 ; Negative test
 
 define <2 x i31> @vector_element_constant_expr() {
@@ -136,7 +151,7 @@ define <2 x i31> @vector_element_constant_expr() {
 
 define void @alloca() {
 ; CHECK-LABEL: @alloca(
-; CHECK-NEXT:    [[P:%.*]] = alloca i8
+; CHECK-NEXT:    [[P:%.*]] = alloca i8, align 1
 ; CHECK-NEXT:    call void @f3(i8* [[P]])
 ; CHECK-NEXT:    ret void
 ;
@@ -148,7 +163,7 @@ define void @alloca() {
 
 define i8* @gep() {
 ; CHECK-LABEL: @gep(
-; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8]
+; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
 ; CHECK-NEXT:    [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* [[P]], i32 0, i32 6
 ; CHECK-NEXT:    ret i8* [[Q]]
 ;
@@ -171,7 +186,7 @@ define i8* @gep_noopt(i32 %arg) {
 
 define i8* @gep_inbounds() {
 ; CHECK-LABEL: @gep_inbounds(
-; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8]
+; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
 ; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 0
 ; CHECK-NEXT:    ret i8* [[Q]]
 ;
@@ -183,7 +198,7 @@ define i8* @gep_inbounds() {
 
 define i8* @gep_inbounds_noopt(i32 %arg) {
 ; CHECK-LABEL: @gep_inbounds_noopt(
-; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8]
+; CHECK-NEXT:    [[P:%.*]] = alloca [4 x i8], align 1
 ; CHECK-NEXT:    [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 [[ARG:%.*]]
 ; CHECK-NEXT:    [[Q2:%.*]] = freeze i8* [[Q]]
 ; CHECK-NEXT:    ret i8* [[Q2]]


        


More information about the llvm-commits mailing list