Skip to content

Commit 954ed05

Browse files
committed
[VPlan] Simplify MUL operands at recipe construction.
This moves the logic to create simplified operands using SCEV to MUL recipe creation. This is needed to match the behavior of the legacy's cost model. TODOs are to extend to other opcodes and move to a transform. Note that this also restricts the number of SCEV simplifications we apply to more precisely match the cases handled by the legacy cost model. Fixes #107015.
1 parent 50a02e7 commit 954ed05

File tree

3 files changed

+78
-5
lines changed

3 files changed

+78
-5
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8393,6 +8393,20 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I,
83938393
case Instruction::Sub:
83948394
case Instruction::Xor:
83958395
case Instruction::Freeze:
8396+
if (I->getOpcode() == Instruction::Mul) {
8397+
// Simplify operands of multiplications using SCEV. This is needed at the
8398+
// moment to match the behavior of the legacy cost-model.
8399+
// TODO: Generalize to any opcode and move to VPlan transformation.
8400+
SmallVector<VPValue *> NewOps(Operands);
8401+
ScalarEvolution &SE = *PSE.getSE();
8402+
for (unsigned I = 0; I < Operands.size(); ++I) {
8403+
Value *V = NewOps[I]->getUnderlyingValue();
8404+
if (!isa<Constant>(V) && SE.isSCEVable(V->getType()))
8405+
if (auto *C = dyn_cast<SCEVConstant>(PSE.getSE()->getSCEV(V)))
8406+
NewOps[I] = Plan.getOrAddLiveIn(C->getValue());
8407+
}
8408+
return new VPWidenRecipe(*I, make_range(NewOps.begin(), NewOps.end()));
8409+
}
83968410
return new VPWidenRecipe(*I, make_range(Operands.begin(), Operands.end()));
83978411
};
83988412
}

llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,6 @@ class VPRecipeBuilder {
174174
if (auto *R = Ingredient2Recipe.lookup(I))
175175
return R->getVPSingleValue();
176176
}
177-
ScalarEvolution &SE = *PSE.getSE();
178-
if (!isa<Constant>(V) && SE.isSCEVable(V->getType()))
179-
if (auto *C = dyn_cast<SCEVConstant>(PSE.getSE()->getSCEV(V)))
180-
return Plan.getOrAddLiveIn(C->getValue());
181-
182177
return Plan.getOrAddLiveIn(V);
183178
}
184179
};
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -p loop-vectorize -S %s | FileCheck %s
3+
4+
target triple = "arm64-apple-macosx"
5+
6+
; Test case for https://github.com/llvm/llvm-project/issues/107015.
7+
define i64 @mul_select_operand_known_1_via_scev() {
8+
; CHECK-LABEL: define i64 @mul_select_operand_known_1_via_scev() {
9+
; CHECK-NEXT: [[ENTRY:.*]]:
10+
; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]]
11+
; CHECK: [[VECTOR_PH]]:
12+
; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
13+
; CHECK: [[VECTOR_BODY]]:
14+
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
15+
; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ <i64 12, i64 1>, %[[VECTOR_PH]] ], [ [[VEC_PHI]], %[[VECTOR_BODY]] ]
16+
; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
17+
; CHECK-NEXT: br i1 true, label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
18+
; CHECK: [[MIDDLE_BLOCK]]:
19+
; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vector.reduce.mul.v2i64(<2 x i64> [[VEC_PHI]])
20+
; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
21+
; CHECK: [[SCALAR_PH]]:
22+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ 2, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ]
23+
; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i64 [ [[TMP0]], %[[MIDDLE_BLOCK]] ], [ 12, %[[ENTRY]] ]
24+
; CHECK-NEXT: br label %[[LOOP:.*]]
25+
; CHECK: [[LOOP]]:
26+
; CHECK-NEXT: [[RED:%.*]] = phi i64 [ [[BC_MERGE_RDX]], %[[SCALAR_PH]] ], [ [[RED_NEXT:%.*]], %[[LOOP]] ]
27+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
28+
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[IV]], 1
29+
; CHECK-NEXT: [[CMP1_I:%.*]] = icmp eq i32 [[TMP1]], 0
30+
; CHECK-NEXT: [[NARROW_I:%.*]] = select i1 [[CMP1_I]], i32 1, i32 [[IV]]
31+
; CHECK-NEXT: [[MUL:%.*]] = zext nneg i32 [[NARROW_I]] to i64
32+
; CHECK-NEXT: [[RED_NEXT]] = mul nsw i64 [[RED]], [[MUL]]
33+
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
34+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV]], 1
35+
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
36+
; CHECK: [[EXIT]]:
37+
; CHECK-NEXT: [[RES:%.*]] = phi i64 [ [[RED_NEXT]], %[[LOOP]] ], [ [[TMP0]], %[[MIDDLE_BLOCK]] ]
38+
; CHECK-NEXT: ret i64 [[RES]]
39+
;
40+
entry:
41+
br label %loop
42+
43+
loop:
44+
%red = phi i64 [ 12, %entry ], [ %red.next, %loop ]
45+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
46+
%0 = and i32 %iv, 1
47+
%cmp1.i = icmp eq i32 %0, 0
48+
%narrow.i = select i1 %cmp1.i, i32 1, i32 %iv
49+
%mul = zext nneg i32 %narrow.i to i64
50+
%red.next = mul nsw i64 %red, %mul
51+
%iv.next = add nuw nsw i32 %iv, 1
52+
%ec = icmp eq i32 %iv, 1
53+
br i1 %ec, label %exit, label %loop
54+
55+
exit:
56+
%res = phi i64 [ %red.next, %loop ]
57+
ret i64 %res
58+
}
59+
;.
60+
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
61+
; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
62+
; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
63+
; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]}
64+
;.

0 commit comments

Comments
 (0)