diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -575,7 +575,8 @@ /// immediately before the CtxI. bool isGuaranteedNotToBeUndefOrPoison(const Value *V, const Instruction *CtxI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + unsigned Depth = 6); /// Specific patterns of select instructions we can match. enum SelectPatternFlavor { diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4527,7 +4527,11 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V, const Instruction *CtxI, - const DominatorTree *DT) { + const DominatorTree *DT, + unsigned Depth) { + if (!Depth) + return false; + // If the value is a freeze instruction, then it can never // be undef or poison. if (isa(V)) @@ -4536,9 +4540,31 @@ // nor poison if their arguments are not poison/undef. // TODO: Deal with other Constant subclasses. - if (isa(V) || isa(V)) + if (isa(V) || isa(V) || isa(V) || + isa(V) || isa(V)) return true; + // Alloca instruction cannot be undef or poison. + if (isa(V)) + return true; + + if (auto BI = dyn_cast(V)) + return isGuaranteedNotToBeUndefOrPoison(BI->getOperand(0), CtxI, DT, + Depth - 1); + + if (auto GEPI = dyn_cast(V)) { + if (!GEPI->isInBounds()) { + if (llvm::all_of(GEPI->operands(), [&](const Value *V) { + return isGuaranteedNotToBeUndefOrPoison(V, CtxI, DT, Depth - 1); + })) + return true; + } else { + if (GEPI->hasAllZeroIndices()) + return isGuaranteedNotToBeUndefOrPoison(GEPI->getPointerOperand(), + CtxI, DT, Depth - 1); + } + } + if (auto PN = dyn_cast(V)) { if (llvm::all_of(PN->incoming_values(), [](const Use &U) { return isa(U.get()); @@ -4547,8 +4573,8 @@ } if (auto II = dyn_cast(V)) { - if (llvm::all_of(II->operands(), [](const Value *V) { - return isGuaranteedNotToBeUndefOrPoison(V); + if (llvm::all_of(II->operands(), [&](const Value *V) { + return isGuaranteedNotToBeUndefOrPoison(V, CtxI, DT, Depth - 1); })) return true; } diff --git a/llvm/test/Transforms/InstSimplify/freeze.ll b/llvm/test/Transforms/InstSimplify/freeze.ll --- a/llvm/test/Transforms/InstSimplify/freeze.ll +++ b/llvm/test/Transforms/InstSimplify/freeze.ll @@ -19,6 +19,76 @@ ret i32 %x } +define float @make_const2() { +; CHECK-LABEL: @make_const2( +; CHECK-NEXT: ret float 1.000000e+01 +; + %x = freeze float 10.0 + ret float %x +} + +@glb = constant i32 0 + +define i32* @make_const_glb() { +; CHECK-LABEL: @make_const_glb( +; CHECK-NEXT: ret i32* @glb +; + %k = freeze i32* @glb + ret i32* %k +} + +define i32()* @make_const_fn() { +; CHECK-LABEL: @make_const_fn( +; CHECK-NEXT: ret i32 ()* @make_const +; + %k = freeze i32()* @make_const + ret i32()* %k +} + +define i32* @make_const_null() { +; CHECK-LABEL: @make_const_null( +; CHECK-NEXT: ret i32* null +; + %k = freeze i32* null + ret i32* %k +} + +define void @alloca() { +; CHECK-LABEL: @alloca( +; CHECK-NEXT: [[P:%.*]] = alloca i8 +; CHECK-NEXT: call void @f3(i8* [[P]]) +; CHECK-NEXT: ret void +; + %p = alloca i8 + %y = freeze i8* %p + call void @f3(i8* %y) + ret void +} + +define i8* @gep() { +; CHECK-LABEL: @gep( +; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8] +; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* [[P]], i32 0, i32 5 +; CHECK-NEXT: ret i8* [[Q]] +; + %p = alloca [4 x i8] + %q = getelementptr [4 x i8], [4 x i8]* %p, i32 0, i32 5 + %q2 = freeze i8* %q + ret i8* %q2 +} + +define i8* @gep_inbounds() { +; CHECK-LABEL: @gep_inbounds( +; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8] +; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 0 +; CHECK-NEXT: ret i8* [[Q]] +; + %p = alloca [4 x i8] + %q = getelementptr inbounds [4 x i8], [4 x i8]* %p, i32 0, i32 0 + %q2 = freeze i8* %q + ret i8* %q2 +} + define i1 @brcond(i1 %c, i1 %c2) { ; CHECK-LABEL: @brcond( ; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]] @@ -81,3 +151,4 @@ } declare void @f1(i1) declare void @f2() +declare void @f3(i8*)