[llvm-branch-commits] [llvm] c6b62ef - [ConstantFold] Fold operations to poison if possible
Juneyoung Lee via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Nov 28 09:33:26 PST 2020
Author: Juneyoung Lee
Date: 2020-11-29T02:28:40+09:00
New Revision: c6b62efb9103466b6cefca1bd99a5b04b4ced044
URL: https://github.com/llvm/llvm-project/commit/c6b62efb9103466b6cefca1bd99a5b04b4ced044
DIFF: https://github.com/llvm/llvm-project/commit/c6b62efb9103466b6cefca1bd99a5b04b4ced044.diff
LOG: [ConstantFold] Fold operations to poison if possible
This patch updates ConstantFold, so operations are folded into poison if possible.
<alive2 proofs>
casts: https://alive2.llvm.org/ce/z/WSj7rw
binary operations (arithmetic): https://alive2.llvm.org/ce/z/_7dEyJ
binary operations (bitwise): https://alive2.llvm.org/ce/z/cezjVN
vector/aggregate operations: https://alive2.llvm.org/ce/z/BQ7hWz
unary ops: https://alive2.llvm.org/ce/z/yBRs4q
other ops: https://alive2.llvm.org/ce/z/iXbcFD
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D92203
Added:
llvm/test/Transforms/InstSimplify/ConstProp/poison.ll
Modified:
llvm/lib/IR/ConstantFold.cpp
llvm/lib/IR/Constants.cpp
llvm/test/Transforms/InstSimplify/ConstProp/InsertElement.ll
llvm/unittests/IR/ConstantsTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index b8502673a829..a52cd725d530 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -522,6 +522,9 @@ static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, Type *DestTy,
Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
Type *DestTy) {
+ if (isa<PoisonValue>(V))
+ return PoisonValue::get(DestTy);
+
if (isa<UndefValue>(V)) {
// zext(undef) = 0, because the top bits will be zero.
// sext(undef) = 0, because the top bits will all be the same.
@@ -759,7 +762,9 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
Constant *V2Element = ConstantExpr::getExtractElement(V2,
ConstantInt::get(Ty, i));
auto *Cond = cast<Constant>(CondV->getOperand(i));
- if (V1Element == V2Element) {
+ if (isa<PoisonValue>(Cond)) {
+ V = PoisonValue::get(V1Element->getType());
+ } else if (V1Element == V2Element) {
V = V1Element;
} else if (isa<UndefValue>(Cond)) {
V = isa<UndefValue>(V1Element) ? V1Element : V2Element;
@@ -775,6 +780,9 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
return ConstantVector::get(Result);
}
+ if (isa<PoisonValue>(Cond))
+ return PoisonValue::get(V1->getType());
+
if (isa<UndefValue>(Cond)) {
if (isa<UndefValue>(V1)) return V1;
return V2;
@@ -782,9 +790,17 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
if (V1 == V2) return V1;
+ if (isa<PoisonValue>(V1))
+ return V2;
+ if (isa<PoisonValue>(V2))
+ return V1;
+
// If the true or false value is undef, we can fold to the other value as
// long as the other value isn't poison.
auto NotPoison = [](Constant *C) {
+ if (isa<PoisonValue>(C))
+ return false;
+
// TODO: We can analyze ConstExpr by opcode to determine if there is any
// possibility of poison.
if (isa<ConstantExpr>(C))
@@ -821,9 +837,13 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val,
Constant *Idx) {
auto *ValVTy = cast<VectorType>(Val->getType());
+ // extractelt poison, C -> poison
+ // extractelt C, undef -> poison
+ if (isa<PoisonValue>(Val) || isa<UndefValue>(Idx))
+ return PoisonValue::get(ValVTy->getElementType());
+
// extractelt undef, C -> undef
- // extractelt C, undef -> undef
- if (isa<UndefValue>(Val) || isa<UndefValue>(Idx))
+ if (isa<UndefValue>(Val))
return UndefValue::get(ValVTy->getElementType());
auto *CIdx = dyn_cast<ConstantInt>(Idx);
@@ -831,9 +851,9 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val,
return nullptr;
if (auto *ValFVTy = dyn_cast<FixedVectorType>(Val->getType())) {
- // ee({w,x,y,z}, wrong_value) -> undef
+ // ee({w,x,y,z}, wrong_value) -> poison
if (CIdx->uge(ValFVTy->getNumElements()))
- return UndefValue::get(ValFVTy->getElementType());
+ return PoisonValue::get(ValFVTy->getElementType());
}
// ee (gep (ptr, idx0, ...), idx) -> gep (ee (ptr, idx), ee (idx0, idx), ...)
@@ -882,7 +902,7 @@ Constant *llvm::ConstantFoldInsertElementInstruction(Constant *Val,
Constant *Elt,
Constant *Idx) {
if (isa<UndefValue>(Idx))
- return UndefValue::get(Val->getType());
+ return PoisonValue::get(Val->getType());
ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx);
if (!CIdx) return nullptr;
@@ -1084,6 +1104,10 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
return C1;
}
+ // Binary operations propagate poison.
+ if (isa<PoisonValue>(C1) || isa<PoisonValue>(C2))
+ return PoisonValue::get(C1->getType());
+
// Handle scalar UndefValue and scalable vector UndefValue. Fixed-length
// vectors are always evaluated per element.
bool IsScalableVector = isa<ScalableVectorType>(C1->getType());
@@ -1922,6 +1946,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
return Constant::getAllOnesValue(ResultTy);
// Handle some degenerate cases first
+ if (isa<PoisonValue>(C1) || isa<PoisonValue>(C2))
+ return PoisonValue::get(ResultTy);
+
if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
CmpInst::Predicate Predicate = CmpInst::Predicate(pred);
bool isIntegerPredicate = ICmpInst::isIntPredicate(Predicate);
@@ -2307,6 +2334,9 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
Type *GEPTy = GetElementPtrInst::getGEPReturnType(
PointeeTy, C, makeArrayRef((Value *const *)Idxs.data(), Idxs.size()));
+ if (isa<PoisonValue>(C))
+ return PoisonValue::get(GEPTy);
+
if (isa<UndefValue>(C))
return UndefValue::get(GEPTy);
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 764d32e39b05..7ebe461fd0c2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -418,6 +418,9 @@ Constant *Constant::getAggregateElement(unsigned Elt) const {
if (const auto *CAZ = dyn_cast<ConstantAggregateZero>(this))
return Elt < CAZ->getNumElements() ? CAZ->getElementValue(Elt) : nullptr;
+ if (const auto *PV = dyn_cast<PoisonValue>(this))
+ return Elt < PV->getNumElements() ? PV->getElementValue(Elt) : nullptr;
+
if (const auto *UV = dyn_cast<UndefValue>(this))
return Elt < UV->getNumElements() ? UV->getElementValue(Elt) : nullptr;
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/InsertElement.ll b/llvm/test/Transforms/InstSimplify/ConstProp/InsertElement.ll
index 98ba4c6f0036..a9a27a5df01f 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/InsertElement.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/InsertElement.ll
@@ -37,7 +37,7 @@ define <4 x i64> @insertelement_undef() {
define i64 @extract_undef_index_from_zero_vec() {
; CHECK-LABEL: @extract_undef_index_from_zero_vec(
-; CHECK-NEXT: ret i64 undef
+; CHECK-NEXT: ret i64 poison
;
%E = extractelement <2 x i64> zeroinitializer, i64 undef
ret i64 %E
@@ -45,7 +45,7 @@ define i64 @extract_undef_index_from_zero_vec() {
define i64 @extract_undef_index_from_nonzero_vec() {
; CHECK-LABEL: @extract_undef_index_from_nonzero_vec(
-; CHECK-NEXT: ret i64 undef
+; CHECK-NEXT: ret i64 poison
;
%E = extractelement <2 x i64> <i64 -1, i64 -1>, i64 undef
ret i64 %E
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll b/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll
new file mode 100644
index 000000000000..b35456e5470b
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll
@@ -0,0 +1,116 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instsimplify -S | FileCheck %s
+
+declare void @use(...)
+
+define void @casts() {
+; CHECK-LABEL: @casts(
+; CHECK-NEXT: call void (...) @use(i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i32 poison, i8 poison, float poison, float poison, float poison, float poison)
+; CHECK-NEXT: ret void
+;
+ %i1 = trunc i32 poison to i8
+ %i2 = zext i4 poison to i8
+ %i3 = sext i4 poison to i8
+ %i4 = fptoui float poison to i8
+ %i5 = fptosi float poison to i8
+ %i6 = bitcast float poison to i32
+ %i7 = ptrtoint i8* poison to i8
+ %f1 = fptrunc double poison to float
+ %f2 = fpext half poison to float
+ %f3 = uitofp i8 poison to float
+ %f4 = sitofp i8 poison to float
+ call void (...) @use(i8 %i1, i8 %i2, i8 %i3, i8 %i4, i8 %i5, i32 %i6, i8 %i7, float %f1, float %f2, float %f3, float %f4)
+ ret void
+}
+
+define void @casts2() {
+; CHECK-LABEL: @casts2(
+; CHECK-NEXT: call void (...) @use(i8* poison, i8* poison)
+; CHECK-NEXT: ret void
+;
+ %p1 = inttoptr i8 poison to i8*
+ %p2 = addrspacecast i8 addrspace(1)* poison to i8*
+ call void (...) @use(i8* %p1, i8* %p2)
+ ret void
+}
+
+define void @unaryops() {
+; CHECK-LABEL: @unaryops(
+; CHECK-NEXT: call void (...) @use(float poison)
+; CHECK-NEXT: ret void
+;
+ %f1 = fneg float poison
+ call void (...) @use(float %f1)
+ ret void
+}
+
+define void @binaryops_arith() {
+; CHECK-LABEL: @binaryops_arith(
+; CHECK-NEXT: call void (...) @use(i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, float poison, float poison, float poison, float poison, float poison, float poison, float poison)
+; CHECK-NEXT: ret void
+;
+ %i1 = add i8 poison, 1
+ %i2 = sub i8 poison, 1
+ %i3 = mul i8 poison, 2
+ %i4 = udiv i8 poison, 2
+ %i5 = udiv i8 2, poison
+ %i6 = sdiv i8 poison, 2
+ %i7 = sdiv i8 2, poison
+ %i8 = urem i8 poison, 2
+ %i9 = urem i8 2, poison
+ %i10 = srem i8 poison, 2
+ %i11 = srem i8 2, poison
+ %f1 = fadd float poison, 1.0
+ %f2 = fsub float poison, 1.0
+ %f3 = fmul float poison, 2.0
+ %f4 = fdiv float poison, 2.0
+ %f5 = fdiv float 2.0, poison
+ %f6 = frem float poison, 2.0
+ %f7 = frem float 2.0, poison
+ call void (...) @use(i8 %i1, i8 %i2, i8 %i3, i8 %i4, i8 %i5, i8 %i6, i8 %i7, i8 %i8, i8 %i9, i8 %i10, i8 %i11, float %f1, float %f2, float %f3, float %f4, float %f5, float %f6, float %f7)
+ ret void
+}
+
+define void @binaryops_bitwise() {
+; CHECK-LABEL: @binaryops_bitwise(
+; CHECK-NEXT: call void (...) @use(i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison)
+; CHECK-NEXT: ret void
+;
+ %i1 = shl i8 poison, 1
+ %i2 = shl i8 1, poison
+ %i3 = lshr i8 poison, 1
+ %i4 = lshr i8 1, poison
+ %i5 = ashr i8 poison, 1
+ %i6 = ashr i8 1, poison
+ %i7 = and i8 poison, 1
+ %i8 = or i8 poison, 1
+ %i9 = xor i8 poison, 1
+ call void (...) @use(i8 %i1, i8 %i2, i8 %i3, i8 %i4, i8 %i5, i8 %i6, i8 %i7, i8 %i8, i8 %i9)
+ ret void
+}
+
+define void @vec_aggr_ops() {
+; CHECK-LABEL: @vec_aggr_ops(
+; CHECK-NEXT: call void (...) @use(i8 poison, i8 poison, <2 x i8> poison, i8 poison)
+; CHECK-NEXT: ret void
+;
+ %i1 = extractelement <2 x i8> poison, i64 0
+ %i2 = extractelement <2 x i8> zeroinitializer, i64 poison
+ %i3 = insertelement <2 x i8> zeroinitializer, i8 0, i64 poison
+ %i4 = extractvalue {i8, i8} poison, 0
+ call void (...) @use(i8 %i1, i8 %i2, <2 x i8> %i3, i8 %i4)
+ ret void
+}
+
+define void @other_ops(i8 %x) {
+; CHECK-LABEL: @other_ops(
+; CHECK-NEXT: call void (...) @use(i1 poison, i1 poison, i8 poison, i8 poison, i8* poison)
+; CHECK-NEXT: ret void
+;
+ %i1 = icmp eq i8 poison, 1
+ %i2 = fcmp oeq float poison, 1.0
+ %i3 = select i1 poison, i8 1, i8 2
+ %i4 = select i1 true, i8 poison, i8 %x
+ call void (...) @use(i1 %i1, i1 %i2, i8 %i3, i8 %i4, i8* getelementptr (i8, i8* poison, i64 1))
+ ret void
+}
diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp
index 5fb2d2dfc7ac..e1e45c7ae856 100644
--- a/llvm/unittests/IR/ConstantsTest.cpp
+++ b/llvm/unittests/IR/ConstantsTest.cpp
@@ -216,9 +216,10 @@ TEST(ConstantsTest, AsInstructionsTest) {
Constant *Two = ConstantInt::get(Int64Ty, 2);
Constant *Big = ConstantInt::get(Context, APInt{256, uint64_t(-1), true});
Constant *Elt = ConstantInt::get(Int16Ty, 2015);
- Constant *Undef16 = UndefValue::get(Int16Ty);
+ Constant *Poison16 = PoisonValue::get(Int16Ty);
Constant *Undef64 = UndefValue::get(Int64Ty);
Constant *UndefV16 = UndefValue::get(P6->getType());
+ Constant *PoisonV16 = PoisonValue::get(P6->getType());
#define P0STR "ptrtoint (i32** @dummy to i32)"
#define P1STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to float)"
@@ -288,15 +289,15 @@ TEST(ConstantsTest, AsInstructionsTest) {
CHECK(ConstantExpr::getExtractElement(P6, One), "extractelement <2 x i16> "
P6STR ", i32 1");
- EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Two));
- EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Big));
- EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Undef64));
+ EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Two));
+ EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Big));
+ EXPECT_EQ(Poison16, ConstantExpr::getExtractElement(P6, Undef64));
EXPECT_EQ(Elt, ConstantExpr::getExtractElement(
ConstantExpr::getInsertElement(P6, Elt, One), One));
EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Two));
EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Big));
- EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Undef64));
+ EXPECT_EQ(PoisonV16, ConstantExpr::getInsertElement(P6, Elt, Undef64));
}
#ifdef GTEST_HAS_DEATH_TEST
More information about the llvm-branch-commits
mailing list