Skip to content

Commit 2a3b1e6

Browse files
[LV][LAA] Vectorize math lib calls with mem write-only attribute
Teach LAA to consider safe specific math lib calls which are known to have set the memory write-only attribute. Those attributes are set to calls by inferNonMandatoryLibFuncAttrs, in BuildLibCalls.cpp, and the current ones are modf/modff and frexp/frexpf. This happens only when the calls are found through TLI to have vectorized counterparts.
1 parent ff9557f commit 2a3b1e6

File tree

2 files changed

+25
-9
lines changed

2 files changed

+25
-9
lines changed

clang/test/CodeGen/aarch64-veclib-function-calls-linear-ptrs.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ vectorize.
1717

1818
// CHECK-LABEL: define dso_local void @frexp_f64(
1919
// CHECK-SAME: ptr nocapture noundef readonly [[IN:%.*]], ptr nocapture noundef writeonly [[OUT1:%.*]], ptr nocapture noundef writeonly [[OUT2:%.*]], i32 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
20-
// CHECK: [[CALL:%.*]] = tail call double @frexp(double noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR2:[0-9]+]]
20+
// CHECK: [[CALL:%.*]] = tail call double @frexp(double noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR5:[0-9]+]]
2121
//
2222
void frexp_f64(double *in, double *out1, int *out2, int N) {
2323
for (int i = 0; i < N; ++i)
@@ -26,30 +26,27 @@ void frexp_f64(double *in, double *out1, int *out2, int N) {
2626

2727
// CHECK-LABEL: define dso_local void @frexp_f32(
2828
// CHECK-SAME: ptr nocapture noundef readonly [[IN:%.*]], ptr nocapture noundef writeonly [[OUT1:%.*]], ptr nocapture noundef writeonly [[OUT2:%.*]], i32 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
29-
// CHECK: [[CALL:%.*]] = tail call float @frexpf(float noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR2]]
29+
// CHECK: [[CALL:%.*]] = tail call float @frexpf(float noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR5]]
3030
//
3131
void frexp_f32(float *in, float *out1, int *out2, int N) {
3232
for (int i = 0; i < N; ++i)
3333
*out1 = frexpf(in[i], out2+i);
3434
}
3535

36-
37-
// TODO: LAA must allow vectorization.
38-
3936
// CHECK-LABEL: define dso_local void @modf_f64(
4037
// CHECK-SAME: ptr nocapture noundef readonly [[IN:%.*]], ptr nocapture noundef writeonly [[OUT1:%.*]], ptr nocapture noundef writeonly [[OUT2:%.*]], i32 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
41-
// CHECK: [[CALL:%.*]] = tail call double @modf(double noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR3:[0-9]+]]
38+
// CHECK: [[TMP11:%.*]] = tail call <vscale x 2 x double> @armpl_svmodf_f64_x(<vscale x 2 x double> [[WIDE_MASKED_LOAD:%.*]], ptr [[TMP10:%.*]], <vscale x 2 x i1> [[ACTIVE_LANE_MASK:%.*]])
39+
// CHECK: [[CALL:%.*]] = tail call double @modf(double noundef [[TMP14:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR6:[0-9]+]]
4240
//
4341
void modf_f64(double *in, double *out1, double *out2, int N) {
4442
for (int i = 0; i < N; ++i)
4543
out1[i] = modf(in[i], out2+i);
4644
}
4745

48-
// TODO: LAA must allow vectorization.
49-
5046
// CHECK-LABEL: define dso_local void @modf_f32(
5147
// CHECK-SAME: ptr nocapture noundef readonly [[IN:%.*]], ptr nocapture noundef writeonly [[OUT1:%.*]], ptr nocapture noundef writeonly [[OUT2:%.*]], i32 noundef [[N:%.*]]) local_unnamed_addr #[[ATTR0]] {
52-
// CHECK: [[CALL:%.*]] = tail call float @modff(float noundef [[TMP0:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR4:[0-9]+]]
48+
// CHECK: [[TMP11:%.*]] = tail call <vscale x 4 x float> @armpl_svmodf_f32_x(<vscale x 4 x float> [[WIDE_MASKED_LOAD:%.*]], ptr [[TMP10:%.*]], <vscale x 4 x i1> [[ACTIVE_LANE_MASK:%.*]])
49+
// CHECK: [[CALL:%.*]] = tail call float @modff(float noundef [[TMP14:%.*]], ptr noundef [[ADD_PTR:%.*]]) #[[ATTR7:[0-9]+]]
5350
//
5451
void modf_f32(float *in, float *out1, float *out2, int N) {
5552
for (int i = 0; i < N; ++i)

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,20 @@ bool LoopAccessInfo::canAnalyzeLoop() {
22742274
return true;
22752275
}
22762276

2277+
/// Returns whether \p I is a known math library call that has memory write-only
2278+
/// attribute set.
2279+
static bool isMathLibCallMemWriteOnly(const TargetLibraryInfo *TLI,
2280+
const Instruction &I) {
2281+
auto *Call = dyn_cast<CallInst>(&I);
2282+
if (!Call)
2283+
return false;
2284+
2285+
LibFunc Func;
2286+
TLI->getLibFunc(*Call, Func);
2287+
return Func == LibFunc::LibFunc_modf || Func == LibFunc::LibFunc_modff ||
2288+
Func == LibFunc::LibFunc_frexp || Func == LibFunc::LibFunc_frexpf;
2289+
}
2290+
22772291
void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
22782292
const TargetLibraryInfo *TLI,
22792293
DominatorTree *DT) {
@@ -2364,6 +2378,11 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
23642378

23652379
// Save 'store' instructions. Abort if other instructions write to memory.
23662380
if (I.mayWriteToMemory()) {
2381+
// We can safety handle math functions that have vectorized
2382+
// counterparts and have the memory write-only attribute set.
2383+
if (isMathLibCallMemWriteOnly(TLI, I))
2384+
continue;
2385+
23672386
auto *St = dyn_cast<StoreInst>(&I);
23682387
if (!St) {
23692388
recordAnalysis("CantVectorizeInstruction", St)

0 commit comments

Comments
 (0)