Skip to content

Commit 535719a

Browse files
[InferAttrs] Mark floating-point libcalls as errno-writing
Floating-point libcalls are currently conservatively marked as may write any memory. Restrict these to clobber only `errno`.
1 parent 2af0e2f commit 535719a

File tree

5 files changed

+263
-189
lines changed

5 files changed

+263
-189
lines changed

llvm/include/llvm/IR/Function.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
571571
bool onlyWritesMemory() const;
572572
void setOnlyWritesMemory();
573573

574-
/// Determine if the call can access memmory only using pointers based
574+
/// Determine if the call can access memory only using pointers based
575575
/// on its arguments.
576576
bool onlyAccessesArgMemory() const;
577577
void setOnlyAccessesArgMemory();
@@ -581,11 +581,20 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
581581
bool onlyAccessesInaccessibleMemory() const;
582582
void setOnlyAccessesInaccessibleMemory();
583583

584+
/// Determine if the call can access only errno memory.
585+
bool onlyAccessesErrnoMemory() const;
586+
void setOnlyAccessesErrnoMemory();
587+
584588
/// Determine if the function may only access memory that is
585589
/// either inaccessible from the IR or pointed to by its arguments.
586590
bool onlyAccessesInaccessibleMemOrArgMem() const;
587591
void setOnlyAccessesInaccessibleMemOrArgMem();
588592

593+
/// Determine if the function may only access memory that is
594+
/// either pointed to by its arguments or errno memory.
595+
bool onlyAccessesArgMemOrErrnoMem() const;
596+
void setOnlyAccessesArgMemOrErrnoMem(ModRefInfo ArgMR);
597+
589598
/// Determine if the function cannot return.
590599
bool doesNotReturn() const {
591600
return hasFnAttribute(Attribute::NoReturn);

llvm/include/llvm/Support/ModRef.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ template <typename LocationEnum> class MemoryEffectsBase {
161161
return FRMB;
162162
}
163163

164+
/// Create MemoryEffectsBase that can only access argument or errno memory.
165+
static MemoryEffectsBase
166+
argumentOrErrnoMemOnly(ModRefInfo ArgMR = ModRefInfo::ModRef,
167+
ModRefInfo ErrnoMR = ModRefInfo::ModRef) {
168+
MemoryEffectsBase FRMB = none();
169+
FRMB.setModRef(Location::ArgMem, ArgMR);
170+
FRMB.setModRef(Location::ErrnoMem, ErrnoMR);
171+
return FRMB;
172+
}
173+
164174
/// Create MemoryEffectsBase from an encoded integer value (used by memory
165175
/// attribute).
166176
static MemoryEffectsBase createFromIntValue(uint32_t Data) {
@@ -237,6 +247,13 @@ template <typename LocationEnum> class MemoryEffectsBase {
237247
.doesNotAccessMemory();
238248
}
239249

250+
/// Whether this function only (at most) accesses argument and errno memory.
251+
bool onlyAccessesArgumentOrErrnoMem() const {
252+
return getWithoutLoc(Location::ArgMem)
253+
.getWithoutLoc(Location::ErrnoMem)
254+
.doesNotAccessMemory();
255+
}
256+
240257
/// Intersect with other MemoryEffectsBase.
241258
MemoryEffectsBase operator&(MemoryEffectsBase Other) const {
242259
return MemoryEffectsBase(Data & Other.Data);

llvm/lib/IR/Function.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ void Function::setOnlyWritesMemory() {
904904
setMemoryEffects(getMemoryEffects() & MemoryEffects::writeOnly());
905905
}
906906

907-
/// Determine if the call can access memmory only using pointers based
907+
/// Determine if the call can access memory only using pointers based
908908
/// on its arguments.
909909
bool Function::onlyAccessesArgMemory() const {
910910
return getMemoryEffects().onlyAccessesArgPointees();
@@ -922,6 +922,15 @@ void Function::setOnlyAccessesInaccessibleMemory() {
922922
setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly());
923923
}
924924

925+
/// Determine if the call can access only errno memory.
926+
bool Function::onlyAccessesErrnoMemory() const {
927+
return getMemoryEffects().onlyAccessesErrnoMem();
928+
}
929+
void Function::setOnlyAccessesErrnoMemory() {
930+
setMemoryEffects(getMemoryEffects() &
931+
MemoryEffects::errnoMemOnly(ModRefInfo::Mod));
932+
}
933+
925934
/// Determine if the function may only access memory that is
926935
/// either inaccessible from the IR or pointed to by its arguments.
927936
bool Function::onlyAccessesInaccessibleMemOrArgMem() const {
@@ -932,6 +941,16 @@ void Function::setOnlyAccessesInaccessibleMemOrArgMem() {
932941
MemoryEffects::inaccessibleOrArgMemOnly());
933942
}
934943

944+
/// Determine if the function may only access memory that is
945+
/// either inaccessible from the IR or pointed to by its arguments.
946+
bool Function::onlyAccessesArgMemOrErrnoMem() const {
947+
return getMemoryEffects().onlyAccessesArgumentOrErrnoMem();
948+
}
949+
void Function::setOnlyAccessesArgMemOrErrnoMem(ModRefInfo ArgMR) {
950+
setMemoryEffects(getMemoryEffects() & MemoryEffects::argumentOrErrnoMemOnly(
951+
ArgMR, ModRefInfo::Mod));
952+
}
953+
935954
bool Function::isTargetIntrinsic() const {
936955
return Intrinsic::isTargetIntrinsic(IntID);
937956
}

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 68 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ STATISTIC(NumInaccessibleMemOnly,
3939
STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
4040
STATISTIC(NumWriteOnly, "Number of functions inferred as writeonly");
4141
STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly");
42+
STATISTIC(NumErrnoMemOnly, "Number of functions inferred as errnomemonly");
4243
STATISTIC(NumInaccessibleMemOrArgMemOnly,
4344
"Number of functions inferred as inaccessiblemem_or_argmemonly");
45+
STATISTIC(NumArgumentMemOrErrnoMemOnly,
46+
"Number of functions inferred as argmem_or_errnomemonly");
4447
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
4548
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
4649
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
@@ -84,6 +87,14 @@ static bool setOnlyAccessesInaccessibleMemory(Function &F) {
8487
return true;
8588
}
8689

90+
static bool setOnlyAccessesErrnoMemory(Function &F) {
91+
if (F.onlyAccessesErrnoMemory())
92+
return false;
93+
F.setOnlyAccessesErrnoMemory();
94+
++NumErrnoMemOnly;
95+
return true;
96+
}
97+
8798
static bool setOnlyReadsMemory(Function &F) {
8899
if (F.onlyReadsMemory())
89100
return false;
@@ -116,6 +127,16 @@ static bool setOnlyAccessesInaccessibleMemOrArgMem(Function &F) {
116127
return true;
117128
}
118129

130+
static bool
131+
setOnlyAccessesArgMemOrErrnoMem(Function &F,
132+
ModRefInfo ArgMR = ModRefInfo::ModRef) {
133+
if (F.onlyAccessesArgMemOrErrnoMem())
134+
return false;
135+
F.setOnlyAccessesArgMemOrErrnoMem(ArgMR);
136+
++NumArgumentMemOrErrnoMemOnly;
137+
return true;
138+
}
139+
119140
static bool setDoesNotThrow(Function &F) {
120141
if (F.doesNotThrow())
121142
return false;
@@ -1145,14 +1166,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11451166
case LibFunc_ldexp:
11461167
case LibFunc_ldexpf:
11471168
case LibFunc_ldexpl:
1169+
Changed |= setOnlyAccessesErrnoMemory(F);
11481170
Changed |= setWillReturn(F);
11491171
break;
1150-
case LibFunc_remquo:
1151-
case LibFunc_remquof:
1152-
case LibFunc_remquol:
1153-
Changed |= setDoesNotCapture(F, 2);
1154-
[[fallthrough]];
1155-
case LibFunc_abs:
11561172
case LibFunc_acos:
11571173
case LibFunc_acosf:
11581174
case LibFunc_acosh:
@@ -1174,15 +1190,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11741190
case LibFunc_atanhf:
11751191
case LibFunc_atanhl:
11761192
case LibFunc_atanl:
1177-
case LibFunc_cbrt:
1178-
case LibFunc_cbrtf:
1179-
case LibFunc_cbrtl:
11801193
case LibFunc_ceil:
11811194
case LibFunc_ceilf:
11821195
case LibFunc_ceill:
1183-
case LibFunc_copysign:
1184-
case LibFunc_copysignf:
1185-
case LibFunc_copysignl:
11861196
case LibFunc_cos:
11871197
case LibFunc_cosh:
11881198
case LibFunc_coshf:
@@ -1206,37 +1216,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12061216
case LibFunc_expm1:
12071217
case LibFunc_expm1f:
12081218
case LibFunc_expm1l:
1209-
case LibFunc_fabs:
1210-
case LibFunc_fabsf:
1211-
case LibFunc_fabsl:
12121219
case LibFunc_fdim:
12131220
case LibFunc_fdiml:
12141221
case LibFunc_fdimf:
1215-
case LibFunc_ffs:
1216-
case LibFunc_ffsl:
1217-
case LibFunc_ffsll:
1218-
case LibFunc_floor:
1219-
case LibFunc_floorf:
1220-
case LibFunc_floorl:
1221-
case LibFunc_fls:
1222-
case LibFunc_flsl:
1223-
case LibFunc_flsll:
1224-
case LibFunc_fmax:
1225-
case LibFunc_fmaxf:
1226-
case LibFunc_fmaxl:
1227-
case LibFunc_fmin:
1228-
case LibFunc_fminf:
1229-
case LibFunc_fminl:
12301222
case LibFunc_fmod:
12311223
case LibFunc_fmodf:
12321224
case LibFunc_fmodl:
12331225
case LibFunc_hypot:
12341226
case LibFunc_hypotf:
12351227
case LibFunc_hypotl:
1236-
case LibFunc_isascii:
1237-
case LibFunc_isdigit:
1238-
case LibFunc_labs:
1239-
case LibFunc_llabs:
12401228
case LibFunc_log:
12411229
case LibFunc_log10:
12421230
case LibFunc_log10f:
@@ -1255,9 +1243,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12551243
case LibFunc_ilogbl:
12561244
case LibFunc_logf:
12571245
case LibFunc_logl:
1258-
case LibFunc_nearbyint:
1259-
case LibFunc_nearbyintf:
1260-
case LibFunc_nearbyintl:
12611246
case LibFunc_pow:
12621247
case LibFunc_powf:
12631248
case LibFunc_powl:
@@ -1294,26 +1279,68 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12941279
case LibFunc_tanhf:
12951280
case LibFunc_tanhl:
12961281
case LibFunc_tanl:
1282+
Changed |= setDoesNotThrow(F);
1283+
Changed |= setDoesNotFreeMemory(F);
1284+
Changed |= setWillReturn(F);
1285+
Changed |= setOnlyAccessesErrnoMemory(F);
1286+
break;
1287+
case LibFunc_abs:
1288+
case LibFunc_cbrt:
1289+
case LibFunc_cbrtf:
1290+
case LibFunc_cbrtl:
1291+
case LibFunc_copysign:
1292+
case LibFunc_copysignf:
1293+
case LibFunc_copysignl:
1294+
case LibFunc_fabs:
1295+
case LibFunc_fabsf:
1296+
case LibFunc_fabsl:
1297+
case LibFunc_ffs:
1298+
case LibFunc_ffsl:
1299+
case LibFunc_ffsll:
1300+
case LibFunc_floor:
1301+
case LibFunc_floorf:
1302+
case LibFunc_floorl:
1303+
case LibFunc_fls:
1304+
case LibFunc_flsl:
1305+
case LibFunc_flsll:
1306+
case LibFunc_fmax:
1307+
case LibFunc_fmaxf:
1308+
case LibFunc_fmaxl:
1309+
case LibFunc_fmin:
1310+
case LibFunc_fminf:
1311+
case LibFunc_fminl:
1312+
case LibFunc_labs:
1313+
case LibFunc_llabs:
1314+
case LibFunc_nearbyint:
1315+
case LibFunc_nearbyintf:
1316+
case LibFunc_nearbyintl:
12971317
case LibFunc_toascii:
12981318
case LibFunc_trunc:
12991319
case LibFunc_truncf:
13001320
case LibFunc_truncl:
1321+
Changed |= setDoesNotAccessMemory(F);
1322+
[[fallthrough]];
1323+
case LibFunc_isascii:
1324+
case LibFunc_isdigit:
13011325
Changed |= setDoesNotThrow(F);
13021326
Changed |= setDoesNotFreeMemory(F);
1303-
Changed |= setOnlyWritesMemory(F);
13041327
Changed |= setWillReturn(F);
13051328
break;
13061329
case LibFunc_sincos:
13071330
case LibFunc_sincosf:
13081331
case LibFunc_sincosl:
1332+
Changed |= setDoesNotCapture(F, 1);
1333+
Changed |= setOnlyWritesMemory(F, 1);
1334+
[[fallthrough]];
1335+
case LibFunc_remquo:
1336+
case LibFunc_remquof:
1337+
case LibFunc_remquol:
13091338
Changed |= setDoesNotThrow(F);
13101339
Changed |= setDoesNotFreeMemory(F);
1311-
Changed |= setOnlyWritesMemory(F);
1312-
Changed |= setOnlyWritesMemory(F, 1);
13131340
Changed |= setOnlyWritesMemory(F, 2);
1314-
Changed |= setDoesNotCapture(F, 1);
13151341
Changed |= setDoesNotCapture(F, 2);
13161342
Changed |= setWillReturn(F);
1343+
Changed |= setOnlyAccessesArgMemOrErrnoMem(F, ModRefInfo::Mod);
13171344
break;
13181345
default:
13191346
// FIXME: It'd be really nice to cover all the library functions we're

0 commit comments

Comments
 (0)