Skip to content

Commit 2813acb

Browse files
committed
Update m_Undef to match vectors/aggrs with undefs and poisons mixed
This fixes https://reviews.llvm.org/D93990#2666922 by teaching `m_Undef` to match vectors/aggrs with poison elements. As suggested, fixes in InstCombine files to use the `m_Undef` matcher instead of `isa<UndefValue>` will be followed. Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D100122
1 parent dd68942 commit 2813acb

File tree

4 files changed

+82
-5
lines changed

4 files changed

+82
-5
lines changed

llvm/include/llvm/Analysis/InstructionSimplify.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include "llvm/IR/Instruction.h"
3939
#include "llvm/IR/Operator.h"
40+
#include "llvm/IR/PatternMatch.h"
4041

4142
namespace llvm {
4243

@@ -133,7 +134,9 @@ struct SimplifyQuery {
133134
bool isUndefValue(Value *V) const {
134135
if (!CanUseUndef)
135136
return false;
136-
return isa<UndefValue>(V);
137+
138+
using namespace PatternMatch;
139+
return match(V, m_Undef());
137140
}
138141
};
139142

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,52 @@ inline class_match<BinaryOperator> m_BinOp() {
8888
/// Matches any compare instruction and ignore it.
8989
inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }
9090

91-
/// Match an arbitrary undef constant.
92-
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
91+
struct undef_match {
92+
static bool check(const Value *V) {
93+
if (isa<UndefValue>(V))
94+
return true;
95+
96+
const auto *CA = dyn_cast<ConstantAggregate>(V);
97+
if (!CA)
98+
return false;
99+
100+
SmallPtrSet<const ConstantAggregate *, 8> Seen;
101+
SmallVector<const ConstantAggregate *, 8> Worklist;
102+
103+
// Either UndefValue, PoisonValue, or an aggregate that only contains
104+
// these is accepted by matcher.
105+
// CheckValue returns false if CA cannot satisfy this constraint.
106+
auto CheckValue = [&](const ConstantAggregate *CA) {
107+
for (const Value *Op : CA->operand_values()) {
108+
if (isa<UndefValue>(Op))
109+
continue;
110+
111+
const auto *CA = dyn_cast<ConstantAggregate>(Op);
112+
if (!CA)
113+
return false;
114+
if (Seen.insert(CA).second)
115+
Worklist.emplace_back(CA);
116+
}
117+
118+
return true;
119+
};
120+
121+
if (!CheckValue(CA))
122+
return false;
123+
124+
while (!Worklist.empty()) {
125+
if (!CheckValue(Worklist.pop_back_val()))
126+
return false;
127+
}
128+
return true;
129+
}
130+
template <typename ITy> bool match(ITy *V) { return check(V); }
131+
};
132+
133+
/// Match an arbitrary undef constant. This matches poison as well.
134+
/// If this is an aggregate and contains a non-aggregate element that is
135+
/// neither undef nor poison, the aggregate is not matched.
136+
inline auto m_Undef() { return undef_match(); }
93137

94138
/// Match an arbitrary poison constant.
95139
inline class_match<PoisonValue> m_Poison() { return class_match<PoisonValue>(); }

llvm/test/Transforms/InstSimplify/icmp-constant.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,8 +1069,7 @@ bb3:
10691069

10701070
define <2 x i1> @heterogeneous_constvector(<2 x i8> %x) {
10711071
; CHECK-LABEL: @heterogeneous_constvector(
1072-
; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 undef, i8 poison>
1073-
; CHECK-NEXT: ret <2 x i1> [[C]]
1072+
; CHECK-NEXT: ret <2 x i1> zeroinitializer
10741073
;
10751074
%c = icmp ult <2 x i8> %x, <i8 undef, i8 poison>
10761075
ret <2 x i1> %c

llvm/unittests/IR/PatternMatch.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,37 @@ TEST_F(PatternMatchTest, VectorOps) {
10221022
EXPECT_TRUE(A == Val);
10231023
}
10241024

1025+
TEST_F(PatternMatchTest, UndefPoisonMix) {
1026+
Type *ScalarTy = IRB.getInt8Ty();
1027+
ArrayType *ArrTy = ArrayType::get(ScalarTy, 2);
1028+
StructType *StTy = StructType::get(ScalarTy, ScalarTy);
1029+
StructType *StTy2 = StructType::get(ScalarTy, StTy);
1030+
StructType *StTy3 = StructType::get(StTy, ScalarTy);
1031+
Constant *Zero = ConstantInt::getNullValue(ScalarTy);
1032+
UndefValue *U = UndefValue::get(ScalarTy);
1033+
UndefValue *P = PoisonValue::get(ScalarTy);
1034+
1035+
EXPECT_TRUE(match(ConstantVector::get({U, P}), m_Undef()));
1036+
EXPECT_TRUE(match(ConstantVector::get({P, U}), m_Undef()));
1037+
1038+
EXPECT_TRUE(match(ConstantArray::get(ArrTy, {U, P}), m_Undef()));
1039+
EXPECT_TRUE(match(ConstantArray::get(ArrTy, {P, U}), m_Undef()));
1040+
1041+
auto *UP = ConstantStruct::get(StTy, {U, P});
1042+
EXPECT_TRUE(match(ConstantStruct::get(StTy2, {U, UP}), m_Undef()));
1043+
EXPECT_TRUE(match(ConstantStruct::get(StTy2, {P, UP}), m_Undef()));
1044+
EXPECT_TRUE(match(ConstantStruct::get(StTy3, {UP, U}), m_Undef()));
1045+
EXPECT_TRUE(match(ConstantStruct::get(StTy3, {UP, P}), m_Undef()));
1046+
1047+
EXPECT_FALSE(match(ConstantStruct::get(StTy, {U, Zero}), m_Undef()));
1048+
EXPECT_FALSE(match(ConstantStruct::get(StTy, {Zero, U}), m_Undef()));
1049+
EXPECT_FALSE(match(ConstantStruct::get(StTy, {P, Zero}), m_Undef()));
1050+
EXPECT_FALSE(match(ConstantStruct::get(StTy, {Zero, P}), m_Undef()));
1051+
1052+
EXPECT_FALSE(match(ConstantStruct::get(StTy2, {Zero, UP}), m_Undef()));
1053+
EXPECT_FALSE(match(ConstantStruct::get(StTy3, {UP, Zero}), m_Undef()));
1054+
}
1055+
10251056
TEST_F(PatternMatchTest, VectorUndefInt) {
10261057
Type *ScalarTy = IRB.getInt8Ty();
10271058
Type *VectorTy = FixedVectorType::get(ScalarTy, 4);

0 commit comments

Comments
 (0)