Skip to content

Commit 139add5

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 d0188eb commit 139add5

File tree

5 files changed

+227
-189
lines changed

5 files changed

+227
-189
lines changed

llvm/include/llvm/IR/Function.h

Lines changed: 1 addition & 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();

llvm/include/llvm/Support/ModRef.h

Lines changed: 10 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) {

llvm/lib/IR/Function.cpp

Lines changed: 1 addition & 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();

llvm/lib/Transforms/Utils/BuildLibCalls.cpp

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,13 @@ 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(NumWriteErrnoMemOnly,
43+
"Number of functions inferred as memory(errnomem: write)");
4244
STATISTIC(NumInaccessibleMemOrArgMemOnly,
4345
"Number of functions inferred as inaccessiblemem_or_argmemonly");
46+
STATISTIC(
47+
NumWriteArgumentMemOrErrnoMemOnly,
48+
"Number of functions inferred as memory(argmem: write, errnomem: write)");
4449
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
4550
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
4651
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
@@ -120,6 +125,21 @@ static bool setOnlyAccessesInaccessibleMemOrArgMem(Function &F) {
120125
return true;
121126
}
122127

128+
static bool setOnlyWritesErrnoMemory(Function &F) {
129+
if (!setMemoryEffects(F, MemoryEffects::errnoMemOnly(ModRefInfo::Mod)))
130+
return false;
131+
++NumWriteErrnoMemOnly;
132+
return true;
133+
}
134+
135+
static bool setOnlyWritesArgMemOrErrnoMem(Function &F) {
136+
if (!setMemoryEffects(F, MemoryEffects::argumentOrErrnoMemOnly(
137+
ModRefInfo::Mod, ModRefInfo::Mod)))
138+
return false;
139+
++NumWriteArgumentMemOrErrnoMemOnly;
140+
return true;
141+
}
142+
123143
static bool setDoesNotThrow(Function &F) {
124144
if (F.doesNotThrow())
125145
return false;
@@ -1149,14 +1169,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11491169
case LibFunc_ldexp:
11501170
case LibFunc_ldexpf:
11511171
case LibFunc_ldexpl:
1172+
Changed |= setOnlyWritesErrnoMemory(F);
11521173
Changed |= setWillReturn(F);
11531174
break;
1154-
case LibFunc_remquo:
1155-
case LibFunc_remquof:
1156-
case LibFunc_remquol:
1157-
Changed |= setDoesNotCapture(F, 2);
1158-
[[fallthrough]];
1159-
case LibFunc_abs:
11601175
case LibFunc_acos:
11611176
case LibFunc_acosf:
11621177
case LibFunc_acosh:
@@ -1178,15 +1193,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
11781193
case LibFunc_atanhf:
11791194
case LibFunc_atanhl:
11801195
case LibFunc_atanl:
1181-
case LibFunc_cbrt:
1182-
case LibFunc_cbrtf:
1183-
case LibFunc_cbrtl:
11841196
case LibFunc_ceil:
11851197
case LibFunc_ceilf:
11861198
case LibFunc_ceill:
1187-
case LibFunc_copysign:
1188-
case LibFunc_copysignf:
1189-
case LibFunc_copysignl:
11901199
case LibFunc_cos:
11911200
case LibFunc_cosh:
11921201
case LibFunc_coshf:
@@ -1210,37 +1219,15 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12101219
case LibFunc_expm1:
12111220
case LibFunc_expm1f:
12121221
case LibFunc_expm1l:
1213-
case LibFunc_fabs:
1214-
case LibFunc_fabsf:
1215-
case LibFunc_fabsl:
12161222
case LibFunc_fdim:
12171223
case LibFunc_fdiml:
12181224
case LibFunc_fdimf:
1219-
case LibFunc_ffs:
1220-
case LibFunc_ffsl:
1221-
case LibFunc_ffsll:
1222-
case LibFunc_floor:
1223-
case LibFunc_floorf:
1224-
case LibFunc_floorl:
1225-
case LibFunc_fls:
1226-
case LibFunc_flsl:
1227-
case LibFunc_flsll:
1228-
case LibFunc_fmax:
1229-
case LibFunc_fmaxf:
1230-
case LibFunc_fmaxl:
1231-
case LibFunc_fmin:
1232-
case LibFunc_fminf:
1233-
case LibFunc_fminl:
12341225
case LibFunc_fmod:
12351226
case LibFunc_fmodf:
12361227
case LibFunc_fmodl:
12371228
case LibFunc_hypot:
12381229
case LibFunc_hypotf:
12391230
case LibFunc_hypotl:
1240-
case LibFunc_isascii:
1241-
case LibFunc_isdigit:
1242-
case LibFunc_labs:
1243-
case LibFunc_llabs:
12441231
case LibFunc_log:
12451232
case LibFunc_log10:
12461233
case LibFunc_log10f:
@@ -1259,9 +1246,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12591246
case LibFunc_ilogbl:
12601247
case LibFunc_logf:
12611248
case LibFunc_logl:
1262-
case LibFunc_nearbyint:
1263-
case LibFunc_nearbyintf:
1264-
case LibFunc_nearbyintl:
12651249
case LibFunc_pow:
12661250
case LibFunc_powf:
12671251
case LibFunc_powl:
@@ -1298,26 +1282,68 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
12981282
case LibFunc_tanhf:
12991283
case LibFunc_tanhl:
13001284
case LibFunc_tanl:
1285+
Changed |= setDoesNotThrow(F);
1286+
Changed |= setDoesNotFreeMemory(F);
1287+
Changed |= setWillReturn(F);
1288+
Changed |= setOnlyWritesErrnoMemory(F);
1289+
break;
1290+
case LibFunc_abs:
1291+
case LibFunc_cbrt:
1292+
case LibFunc_cbrtf:
1293+
case LibFunc_cbrtl:
1294+
case LibFunc_copysign:
1295+
case LibFunc_copysignf:
1296+
case LibFunc_copysignl:
1297+
case LibFunc_fabs:
1298+
case LibFunc_fabsf:
1299+
case LibFunc_fabsl:
1300+
case LibFunc_ffs:
1301+
case LibFunc_ffsl:
1302+
case LibFunc_ffsll:
1303+
case LibFunc_floor:
1304+
case LibFunc_floorf:
1305+
case LibFunc_floorl:
1306+
case LibFunc_fls:
1307+
case LibFunc_flsl:
1308+
case LibFunc_flsll:
1309+
case LibFunc_fmax:
1310+
case LibFunc_fmaxf:
1311+
case LibFunc_fmaxl:
1312+
case LibFunc_fmin:
1313+
case LibFunc_fminf:
1314+
case LibFunc_fminl:
1315+
case LibFunc_labs:
1316+
case LibFunc_llabs:
1317+
case LibFunc_nearbyint:
1318+
case LibFunc_nearbyintf:
1319+
case LibFunc_nearbyintl:
13011320
case LibFunc_toascii:
13021321
case LibFunc_trunc:
13031322
case LibFunc_truncf:
13041323
case LibFunc_truncl:
1324+
Changed |= setDoesNotAccessMemory(F);
1325+
[[fallthrough]];
1326+
case LibFunc_isascii:
1327+
case LibFunc_isdigit:
13051328
Changed |= setDoesNotThrow(F);
13061329
Changed |= setDoesNotFreeMemory(F);
1307-
Changed |= setOnlyWritesMemory(F);
13081330
Changed |= setWillReturn(F);
13091331
break;
13101332
case LibFunc_sincos:
13111333
case LibFunc_sincosf:
13121334
case LibFunc_sincosl:
1335+
Changed |= setDoesNotCapture(F, 1);
1336+
Changed |= setOnlyWritesMemory(F, 1);
1337+
[[fallthrough]];
1338+
case LibFunc_remquo:
1339+
case LibFunc_remquof:
1340+
case LibFunc_remquol:
13131341
Changed |= setDoesNotThrow(F);
13141342
Changed |= setDoesNotFreeMemory(F);
1315-
Changed |= setOnlyWritesMemory(F);
1316-
Changed |= setOnlyWritesMemory(F, 1);
13171343
Changed |= setOnlyWritesMemory(F, 2);
1318-
Changed |= setDoesNotCapture(F, 1);
13191344
Changed |= setDoesNotCapture(F, 2);
13201345
Changed |= setWillReturn(F);
1346+
Changed |= setOnlyWritesArgMemOrErrnoMem(F);
13211347
break;
13221348
default:
13231349
// FIXME: It'd be really nice to cover all the library functions we're

0 commit comments

Comments
 (0)