Skip to content

Commit 1619ad6

Browse files
committed
[RFC][llvm] Added llvm.loop.vectorize.reassociation.enable metadata.
This metadata allows unsafe reassociations of computations during the loop vectorization. For example, it allows vectorizing loops with floating-point reductions without the need to compile the whole function/program with -fassociative-math.
1 parent e6529dc commit 1619ad6

File tree

4 files changed

+82
-3
lines changed

4 files changed

+82
-3
lines changed

llvm/docs/LangRef.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7593,6 +7593,22 @@ Note that setting ``llvm.loop.interleave.count`` to 1 disables interleaving
75937593
multiple iterations of the loop. If ``llvm.loop.interleave.count`` is set to 0
75947594
then the interleave count will be determined automatically.
75957595

7596+
'``llvm.loop.vectorize.reassociation.enable``' Metadata
7597+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7598+
7599+
This metadata selectively allows or disallows reassociating computations,
7600+
which otherwise may be unsafe to reassociate, during the loop vectorization.
7601+
For example, a floating point ``ADD`` reduction without ``reassoc`` fast-math
7602+
flags may be vectorized provided that this metadata allows it. The first
7603+
operand is the string ``llvm.loop.vectorize.reassociation.enable``
7604+
and the second operand is a bit. If the bit operand value is 1 unsafe
7605+
reassociations aqre enabled. A value of 0 disables unsafe reassociations.
7606+
7607+
.. code-block:: llvm
7608+
7609+
!0 = !{!"llvm.loop.vectorize.reassociation.enable", i1 0}
7610+
!1 = !{!"llvm.loop.vectorize.reassociation.enable", i1 1}
7611+
75967612
'``llvm.loop.vectorize.enable``' Metadata
75977613
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
75987614

llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ class LoopVectorizeHints {
6464
HK_FORCE,
6565
HK_ISVECTORIZED,
6666
HK_PREDICATE,
67-
HK_SCALABLE
67+
HK_SCALABLE,
68+
HK_REASSOCIATE,
6869
};
6970

7071
/// Hint - associates name and validation with the hint value.
@@ -97,6 +98,10 @@ class LoopVectorizeHints {
9798
/// Says whether we should use fixed width or scalable vectorization.
9899
Hint Scalable;
99100

101+
/// Says whether unsafe reassociation of computations is allowed
102+
/// during the loop vectorization.
103+
Hint Reassociate;
104+
100105
/// Return the loop metadata prefix.
101106
static StringRef Prefix() { return "llvm.loop."; }
102107

@@ -162,6 +167,13 @@ class LoopVectorizeHints {
162167
return (ScalableForceKind)Scalable.Value == SK_FixedWidthOnly;
163168
}
164169

170+
enum ForceKind getReassociate() const {
171+
if ((ForceKind)Reassociate.Value == FK_Undefined &&
172+
hasDisableAllTransformsHint(TheLoop))
173+
return FK_Disabled;
174+
return (ForceKind)Reassociate.Value;
175+
}
176+
165177
/// If hints are provided that force vectorization, use the AlwaysPrint
166178
/// pass name to force the frontend to print the diagnostic.
167179
const char *vectorizeAnalysisPassName() const;

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ bool LoopVectorizeHints::Hint::validate(unsigned Val) {
9797
case HK_ISVECTORIZED:
9898
case HK_PREDICATE:
9999
case HK_SCALABLE:
100+
case HK_REASSOCIATE:
100101
return (Val == 0 || Val == 1);
101102
}
102103
return false;
@@ -112,6 +113,8 @@ LoopVectorizeHints::LoopVectorizeHints(const Loop *L,
112113
IsVectorized("isvectorized", 0, HK_ISVECTORIZED),
113114
Predicate("vectorize.predicate.enable", FK_Undefined, HK_PREDICATE),
114115
Scalable("vectorize.scalable.enable", SK_Unspecified, HK_SCALABLE),
116+
Reassociate("vectorize.reassociation.enable", FK_Undefined,
117+
HK_REASSOCIATE),
115118
TheLoop(L), ORE(ORE) {
116119
// Populate values with existing loop metadata.
117120
getHintsFromMetadata();
@@ -251,6 +254,7 @@ bool LoopVectorizeHints::allowReordering() const {
251254
ElementCount EC = getWidth();
252255
return HintsAllowReordering &&
253256
(getForce() == LoopVectorizeHints::FK_Enabled ||
257+
getReassociate() == LoopVectorizeHints::FK_Enabled ||
254258
EC.getKnownMinValue() > 1);
255259
}
256260

@@ -300,8 +304,8 @@ void LoopVectorizeHints::setHint(StringRef Name, Metadata *Arg) {
300304
return;
301305
unsigned Val = C->getZExtValue();
302306

303-
Hint *Hints[] = {&Width, &Interleave, &Force,
304-
&IsVectorized, &Predicate, &Scalable};
307+
Hint *Hints[] = {&Width, &Interleave, &Force, &IsVectorized,
308+
&Predicate, &Scalable, &Reassociate};
305309
for (auto *H : Hints) {
306310
if (Name == H->Name) {
307311
if (H->validate(Val))
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; Check that the loop with a floating-point reduction is vectorized
2+
; due to llvm.loop.vectorize.reassociation.enable metadata.
3+
; RUN: opt -passes=loop-vectorize -S < %s 2>&1 | FileCheck %s
4+
5+
source_filename = "FIRModule"
6+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
7+
target triple = "x86_64-unknown-linux-gnu"
8+
9+
; Function Attrs: nofree norecurse nosync nounwind memory(argmem: readwrite)
10+
define void @test_(ptr captures(none) %0, ptr readonly captures(none) %1) local_unnamed_addr #0 {
11+
; CHECK-LABEL: define void @test_(
12+
; CHECK-NEXT: fadd contract <4 x float> {{.*}}
13+
; CHECK-NEXT: call contract float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> {{.*}})
14+
;
15+
%invariant.gep = getelementptr i8, ptr %1, i64 -4
16+
%.promoted = load float, ptr %0, align 4
17+
br label %3
18+
19+
3: ; preds = %2, %3
20+
%indvars.iv = phi i64 [ 1, %2 ], [ %indvars.iv.next, %3 ]
21+
%4 = phi float [ %.promoted, %2 ], [ %6, %3 ]
22+
%gep = getelementptr float, ptr %invariant.gep, i64 %indvars.iv
23+
%5 = load float, ptr %gep, align 4
24+
%6 = fadd contract float %4, %5
25+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
26+
%exitcond.not = icmp eq i64 %indvars.iv.next, 1001
27+
br i1 %exitcond.not, label %7, label %3, !llvm.loop !2
28+
29+
7: ; preds = %3
30+
%.lcssa = phi float [ %6, %3 ]
31+
store float %.lcssa, ptr %0, align 4
32+
ret void
33+
}
34+
35+
attributes #0 = { nofree norecurse nosync nounwind memory(argmem: readwrite) "target-cpu"="x86-64" }
36+
37+
!llvm.ident = !{!0}
38+
!llvm.module.flags = !{!1}
39+
40+
!0 = !{!"flang version 21.0.0"}
41+
!1 = !{i32 2, !"Debug Info Version", i32 3}
42+
!2 = distinct !{!2, !3}
43+
!3 = !{!"llvm.loop.vectorize.reassociation.enable", i1 true}
44+
45+
; CHECK-NOT: llvm.loop.vectorize.reassociation.enable
46+
; CHECK: [[META3]] = !{!"llvm.loop.isvectorized", i32 1}
47+
; CHECK: [[META4]] = !{!"llvm.loop.unroll.runtime.disable"}

0 commit comments

Comments
 (0)