Skip to content

Commit 9de327c

Browse files
committed
[LV] Generalize predication checks from 2c8836c for operands.
This fixes another case where the VPlan-based and legacy cost models disagree. If any of the operands is predicated, it can't be trivially hoisted and we should consider the cost for evaluating it each loop iteration. Fixes #108697.
1 parent 848cb21 commit 9de327c

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6551,14 +6551,17 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I,
65516551
Op2 = cast<SCEVConstant>(PSE.getSCEV(Op2))->getValue();
65526552
}
65536553
auto Op2Info = TTI.getOperandInfo(Op2);
6554-
auto IsInvariant = [this](Value *Op) {
6554+
std::function<bool(Value *)> IsInvariant =
6555+
[this, &IsInvariant](Value *Op) -> bool {
65556556
if (!Legal->isInvariant(Op))
65566557
return false;
6557-
// Consider Op2 invariant, if it is not a predicated instruction in the
6558-
// loop. In that case, it is not trivially hoistable.
6558+
// Consider Op2invariant, if it or its operands aren't predicated
6559+
// instruction in the loop. In that case, it is not trivially hoistable.
65596560
return !isa<Instruction>(Op) ||
65606561
!TheLoop->contains(cast<Instruction>(Op)) ||
6561-
!isPredicatedInst(cast<Instruction>(Op));
6562+
(!isPredicatedInst(cast<Instruction>(Op)) &&
6563+
all_of(cast<Instruction>(Op)->operands(),
6564+
[&IsInvariant](Value *Op) { return IsInvariant(Op); }));
65626565
};
65636566
if (Op2Info.Kind == TargetTransformInfo::OK_AnyValue && IsInvariant(Op2))
65646567
Op2Info.Kind = TargetTransformInfo::OK_UniformValue;

llvm/test/Transforms/LoopVectorize/X86/predicated-instruction-cost.ll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,52 @@ loop.latch:
5252
exit:
5353
ret void
5454
}
55+
56+
; Test case for https://github.com/llvm/llvm-project/issues/108697.
57+
define void @test_wide_shift_uses_predicated_invariant_instruction(i32 %d, i1 %c, ptr %dst) {
58+
; CHECK-LABEL: define void @test_wide_shift_uses_predicated_invariant_instruction(
59+
; CHECK-SAME: i32 [[D:%.*]], i1 [[C:%.*]], ptr [[DST:%.*]]) {
60+
; CHECK-NEXT: [[ENTRY:.*]]:
61+
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
62+
; CHECK: [[LOOP_HEADER]]:
63+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
64+
; CHECK-NEXT: br i1 [[C]], label %[[LOOP_LATCH]], label %[[ELSE:.*]]
65+
; CHECK: [[ELSE]]:
66+
; CHECK-NEXT: [[REM:%.*]] = urem i32 100, [[D]]
67+
; CHECK-NEXT: [[SEXT:%.*]] = shl i32 [[REM]], 12
68+
; CHECK-NEXT: [[SHL_I:%.*]] = shl i32 999, [[SEXT]]
69+
; CHECK-NEXT: br label %[[LOOP_LATCH]]
70+
; CHECK: [[LOOP_LATCH]]:
71+
; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SHL_I]], %[[ELSE]] ], [ 0, %[[LOOP_HEADER]] ]
72+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[DST]], i32 [[IV]]
73+
; CHECK-NEXT: store i32 [[P]], ptr [[GEP]], align 4
74+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
75+
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32 [[IV_NEXT]], 100
76+
; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP_HEADER]]
77+
; CHECK: [[EXIT]]:
78+
; CHECK-NEXT: ret void
79+
;
80+
entry:
81+
br label %loop.header
82+
83+
loop.header:
84+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
85+
br i1 %c, label %loop.latch, label %else
86+
87+
else:
88+
%rem = urem i32 100, %d
89+
%sext = shl i32 %rem, 12
90+
%shl.i = shl i32 999, %sext
91+
br label %loop.latch
92+
93+
loop.latch:
94+
%p = phi i32 [ %shl.i, %else ], [ 0, %loop.header ]
95+
%gep = getelementptr inbounds i32, ptr %dst, i32 %iv
96+
store i32 %p, ptr %gep
97+
%iv.next = add i32 %iv, 1
98+
%ec = icmp eq i32 %iv.next, 100
99+
br i1 %ec, label %exit, label %loop.header
100+
101+
exit:
102+
ret void
103+
}

0 commit comments

Comments
 (0)