Skip to content

Commit 2e57761

Browse files
authored
[VPlan] Simplify select !c, x, y -> select c, y, x (#147268)
This is split off from #133993 On its own this simplification isn't that useful, but it allows us to make the equivalent VPBlendRecipe optimisation more generic by operating on VPInstructions. In order to actually test this without #133993, I've had to also extend the m_Not pattern matcher to also catch VPWidenRecipes, since I couldn't really think of a straightforward way to create a VPInstruction::Select with a negated condition.
1 parent d889a74 commit 2e57761

File tree

3 files changed

+80
-6
lines changed

3 files changed

+80
-6
lines changed

llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -366,12 +366,6 @@ m_Freeze(const Op0_t &Op0) {
366366
return m_VPInstruction<Instruction::Freeze>(Op0);
367367
}
368368

369-
template <typename Op0_t>
370-
inline UnaryVPInstruction_match<Op0_t, VPInstruction::Not>
371-
m_Not(const Op0_t &Op0) {
372-
return m_VPInstruction<VPInstruction::Not>(Op0);
373-
}
374-
375369
template <typename Op0_t>
376370
inline UnaryVPInstruction_match<Op0_t, VPInstruction::BranchOnCond>
377371
m_BranchOnCond(const Op0_t &Op0) {
@@ -491,6 +485,15 @@ m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
491485
{Op0, Op1, Op2});
492486
}
493487

488+
template <typename Op0_t>
489+
inline match_combine_or<UnaryVPInstruction_match<Op0_t, VPInstruction::Not>,
490+
AllBinaryRecipe_match<int_pred_ty<is_all_ones>, Op0_t,
491+
Instruction::Xor, true>>
492+
m_Not(const Op0_t &Op0) {
493+
return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
494+
m_c_Binary<Instruction::Xor>(m_AllOnes(), Op0));
495+
}
496+
494497
template <typename Op0_t, typename Op1_t>
495498
inline match_combine_or<
496499
BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::LogicalAnd>,

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,15 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
10821082
if (match(Def, m_Select(m_VPValue(), m_VPValue(X), m_Deferred(X))))
10831083
return Def->replaceAllUsesWith(X);
10841084

1085+
// select !c, x, y -> select c, y, x
1086+
VPValue *C;
1087+
if (match(Def, m_Select(m_Not(m_VPValue(C)), m_VPValue(X), m_VPValue(Y)))) {
1088+
Def->setOperand(0, C);
1089+
Def->setOperand(1, Y);
1090+
Def->setOperand(2, X);
1091+
return;
1092+
}
1093+
10851094
if (match(Def, m_c_Mul(m_VPValue(A), m_SpecificInt(1))))
10861095
return Def->replaceAllUsesWith(A);
10871096

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5
2+
; RUN: opt -p loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -S < %s | FileCheck %s
3+
4+
define void @neg_cond(ptr noalias %p, ptr noalias %q) {
5+
; CHECK-LABEL: define void @neg_cond(
6+
; CHECK-SAME: ptr noalias [[P:%.*]], ptr noalias [[Q:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*]]:
8+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
9+
; CHECK: [[VECTOR_PH]]:
10+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
11+
; CHECK: [[VECTOR_BODY]]:
12+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
13+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P]], i32 [[INDEX]]
14+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[TMP0]], i32 0
15+
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP1]], align 4
16+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <4 x i32> [[WIDE_LOAD]], splat (i32 42)
17+
; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x i32> splat (i32 42), <4 x i32> splat (i32 43)
18+
; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP1]], align 4
19+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4
20+
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1024
21+
; CHECK-NEXT: br i1 [[TMP5]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
22+
; CHECK: [[MIDDLE_BLOCK]]:
23+
; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
24+
; CHECK: [[SCALAR_PH]]:
25+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 1024, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
26+
; CHECK-NEXT: br label %[[LOOP:.*]]
27+
; CHECK: [[LOOP]]:
28+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
29+
; CHECK-NEXT: [[P_GEP:%.*]] = getelementptr i32, ptr [[P]], i32 [[IV]]
30+
; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P_GEP]], align 4
31+
; CHECK-NEXT: [[Q_GEP:%.*]] = getelementptr i32, ptr [[Q]], i32 [[IV]]
32+
; CHECK-NEXT: [[Y:%.*]] = load i32, ptr [[Q_GEP]], align 4
33+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 42
34+
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[CMP]], true
35+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT]], i32 42, i32 43
36+
; CHECK-NEXT: store i32 [[SEL]], ptr [[P_GEP]], align 4
37+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
38+
; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[IV_NEXT]], 1024
39+
; CHECK-NEXT: br i1 [[DONE]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
40+
; CHECK: [[EXIT]]:
41+
; CHECK-NEXT: ret void
42+
;
43+
entry:
44+
br label %loop
45+
46+
loop:
47+
%iv = phi i32 [0, %entry], [%iv.next, %loop]
48+
%p.gep = getelementptr i32, ptr %p, i32 %iv
49+
%x = load i32, ptr %p.gep
50+
%q.gep = getelementptr i32, ptr %q, i32 %iv
51+
%y = load i32, ptr %q.gep
52+
%cmp = icmp eq i32 %x, 42
53+
%not = xor i1 %cmp, 1
54+
%sel = select i1 %not, i32 42, i32 43
55+
store i32 %sel, ptr %p.gep
56+
%iv.next = add i32 %iv, 1
57+
%done = icmp eq i32 %iv.next, 1024
58+
br i1 %done, label %exit, label %loop
59+
60+
exit:
61+
ret void
62+
}

0 commit comments

Comments
 (0)