@@ -41,7 +41,7 @@ static void RunTest(
41
41
}
42
42
}
43
43
44
- void AssertMatchesExactlyAttributes (CallInst *Assume, Value *WasOn,
44
+ static void AssertMatchesExactlyAttributes (CallInst *Assume, Value *WasOn,
45
45
StringRef AttrToMatch) {
46
46
Regex Reg (AttrToMatch);
47
47
SmallVector<StringRef, 1 > Matches;
@@ -57,7 +57,7 @@ void AssertMatchesExactlyAttributes(CallInst *Assume, Value *WasOn,
57
57
}
58
58
}
59
59
60
- void AssertHasTheRightValue (CallInst *Assume, Value *WasOn,
60
+ static void AssertHasTheRightValue (CallInst *Assume, Value *WasOn,
61
61
Attribute::AttrKind Kind, unsigned Value, bool Both,
62
62
AssumeQuery AQ = AssumeQuery::Highest) {
63
63
if (!Both) {
@@ -80,7 +80,7 @@ void AssertHasTheRightValue(CallInst *Assume, Value *WasOn,
80
80
}
81
81
}
82
82
83
- TEST (AssumeQueryAPI, Basic ) {
83
+ TEST (AssumeQueryAPI, hasAttributeInAssume ) {
84
84
StringRef Head =
85
85
" declare void @llvm.assume(i1)\n "
86
86
" declare void @func(i32*, i32*)\n "
@@ -216,3 +216,174 @@ TEST(AssumeQueryAPI, Basic) {
216
216
}));
217
217
RunTest (Head, Tail, Tests);
218
218
}
219
+
220
+ static void AssertFindExactlyAttributes (RetainedKnowledgeMap &Map, Value *WasOn,
221
+ StringRef AttrToMatch) {
222
+ Regex Reg (AttrToMatch);
223
+ SmallVector<StringRef, 1 > Matches;
224
+ for (StringRef Attr : {
225
+ #define GET_ATTR_NAMES
226
+ #define ATTRIBUTE_ENUM (ENUM_NAME, DISPLAY_NAME ) StringRef(#DISPLAY_NAME),
227
+ #include " llvm/IR/Attributes.inc"
228
+ }) {
229
+ bool ShouldHaveAttr = Reg.match (Attr, &Matches) && Matches[0 ] == Attr;
230
+
231
+ if (ShouldHaveAttr != (Map.find (RetainedKnowledgeKey{WasOn, Attribute::getAttrKindFromName (Attr)}) != Map.end ())) {
232
+ ASSERT_TRUE (false );
233
+ }
234
+ }
235
+ }
236
+
237
+ static void AssertMapHasRightValue (RetainedKnowledgeMap &Map,
238
+ RetainedKnowledgeKey Key, MinMax MM) {
239
+ auto LookupIt = Map.find (Key);
240
+ ASSERT_TRUE (LookupIt != Map.end ());
241
+ ASSERT_TRUE (LookupIt->second .Min == MM.Min );
242
+ ASSERT_TRUE (LookupIt->second .Max == MM.Max );
243
+ }
244
+
245
+ TEST (AssumeQueryAPI, fillMapFromAssume) {
246
+ StringRef Head =
247
+ " declare void @llvm.assume(i1)\n "
248
+ " declare void @func(i32*, i32*)\n "
249
+ " declare void @func1(i32*, i32*, i32*, i32*)\n "
250
+ " declare void @func_many(i32*) \" no-jump-tables\" nounwind "
251
+ " \" less-precise-fpmad\" willreturn norecurse\n "
252
+ " define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {\n " ;
253
+ StringRef Tail = " ret void\n "
254
+ " }" ;
255
+ std::vector<std::pair<StringRef, llvm::function_ref<void (Instruction *)>>>
256
+ Tests;
257
+ Tests.push_back (std::make_pair (
258
+ " call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
259
+ " 8 noalias %P1)\n " ,
260
+ [](Instruction *I) {
261
+ CallInst *Assume = BuildAssumeFromInst (I);
262
+ Assume->insertBefore (I);
263
+
264
+ RetainedKnowledgeMap Map;
265
+ fillMapFromAssume (*Assume, Map);
266
+ AssertFindExactlyAttributes (Map, I->getOperand (0 ),
267
+ " (nonnull|align|dereferenceable)" );
268
+ AssertFindExactlyAttributes (Map, I->getOperand (1 ),
269
+ " (noalias|align)" );
270
+ AssertMapHasRightValue (
271
+ Map, {I->getOperand (0 ), Attribute::Dereferenceable}, {16 , 16 });
272
+ AssertMapHasRightValue (Map, {I->getOperand (0 ), Attribute::Alignment},
273
+ {4 , 4 });
274
+ AssertMapHasRightValue (Map, {I->getOperand (0 ), Attribute::Alignment},
275
+ {4 , 4 });
276
+ }));
277
+ Tests.push_back (std::make_pair (
278
+ " call void @func1(i32* nonnull align 32 dereferenceable(48) %P, i32* "
279
+ " nonnull "
280
+ " align 8 dereferenceable(28) %P, i32* nonnull align 64 "
281
+ " dereferenceable(4) "
282
+ " %P, i32* nonnull align 16 dereferenceable(12) %P)\n " ,
283
+ [](Instruction *I) {
284
+ CallInst *Assume = BuildAssumeFromInst (I);
285
+ Assume->insertBefore (I);
286
+
287
+ RetainedKnowledgeMap Map;
288
+ fillMapFromAssume (*Assume, Map);
289
+
290
+ AssertFindExactlyAttributes (Map, I->getOperand (0 ),
291
+ " (nonnull|align|dereferenceable)" );
292
+ AssertFindExactlyAttributes (Map, I->getOperand (1 ),
293
+ " (nonnull|align|dereferenceable)" );
294
+ AssertFindExactlyAttributes (Map, I->getOperand (2 ),
295
+ " (nonnull|align|dereferenceable)" );
296
+ AssertFindExactlyAttributes (Map, I->getOperand (3 ),
297
+ " (nonnull|align|dereferenceable)" );
298
+ AssertMapHasRightValue (
299
+ Map, {I->getOperand (0 ), Attribute::Dereferenceable}, {4 , 48 });
300
+ AssertMapHasRightValue (Map, {I->getOperand (0 ), Attribute::Alignment},
301
+ {8 , 64 });
302
+ }));
303
+ Tests.push_back (std::make_pair (
304
+ " call void @func_many(i32* align 8 %P1) cold\n " , [](Instruction *I) {
305
+ ShouldPreserveAllAttributes.setValue (true );
306
+ CallInst *Assume = BuildAssumeFromInst (I);
307
+ Assume->insertBefore (I);
308
+
309
+ RetainedKnowledgeMap Map;
310
+ fillMapFromAssume (*Assume, Map);
311
+
312
+ AssertFindExactlyAttributes (
313
+ Map, nullptr , " (nounwind|norecurse|willreturn|cold)" );
314
+ ShouldPreserveAllAttributes.setValue (false );
315
+ }));
316
+ Tests.push_back (
317
+ std::make_pair (" call void @llvm.assume(i1 true)\n " , [](Instruction *I) {
318
+ RetainedKnowledgeMap Map;
319
+ fillMapFromAssume (*cast<CallInst>(I), Map);
320
+
321
+ AssertFindExactlyAttributes (Map, nullptr , " " );
322
+ ASSERT_TRUE (Map.empty ());
323
+ }));
324
+ Tests.push_back (std::make_pair (
325
+ " call void @func1(i32* readnone align 32 "
326
+ " dereferenceable(48) noalias %P, i32* "
327
+ " align 8 dereferenceable(28) %P1, i32* align 64 "
328
+ " dereferenceable(4) "
329
+ " %P2, i32* nonnull align 16 dereferenceable(12) %P3)\n " ,
330
+ [](Instruction *I) {
331
+ CallInst *Assume = BuildAssumeFromInst (I);
332
+ Assume->insertBefore (I);
333
+
334
+ RetainedKnowledgeMap Map;
335
+ fillMapFromAssume (*Assume, Map);
336
+
337
+ AssertFindExactlyAttributes (Map, I->getOperand (0 ),
338
+ " (readnone|align|dereferenceable|noalias)" );
339
+ AssertFindExactlyAttributes (Map, I->getOperand (1 ),
340
+ " (align|dereferenceable)" );
341
+ AssertFindExactlyAttributes (Map, I->getOperand (2 ),
342
+ " (align|dereferenceable)" );
343
+ AssertFindExactlyAttributes (Map, I->getOperand (3 ),
344
+ " (nonnull|align|dereferenceable)" );
345
+ AssertMapHasRightValue (Map, {I->getOperand (0 ), Attribute::Alignment},
346
+ {32 , 32 });
347
+ AssertMapHasRightValue (
348
+ Map, {I->getOperand (0 ), Attribute::Dereferenceable}, {48 , 48 });
349
+ AssertMapHasRightValue (
350
+ Map, {I->getOperand (0 ), Attribute::NoAlias}, {0 , 0 });
351
+ AssertMapHasRightValue (
352
+ Map, {I->getOperand (1 ), Attribute::Dereferenceable}, {28 , 28 });
353
+ AssertMapHasRightValue (Map, {I->getOperand (1 ), Attribute::Alignment},
354
+ {8 , 8 });
355
+ AssertMapHasRightValue (Map, {I->getOperand (2 ), Attribute::Alignment},
356
+ {64 , 64 });
357
+ AssertMapHasRightValue (
358
+ Map, {I->getOperand (2 ), Attribute::Dereferenceable}, {4 , 4 });
359
+ AssertMapHasRightValue (Map, {I->getOperand (3 ), Attribute::Alignment},
360
+ {16 , 16 });
361
+ AssertMapHasRightValue (
362
+ Map, {I->getOperand (3 ), Attribute::Dereferenceable}, {12 , 12 });
363
+ }));
364
+
365
+ // / Keep this test last as it modifies the function.
366
+ Tests.push_back (std::make_pair (
367
+ " call void @func(i32* nonnull align 4 dereferenceable(16) %P, i32* align "
368
+ " 8 noalias %P1)\n " ,
369
+ [](Instruction *I) {
370
+ CallInst *Assume = BuildAssumeFromInst (I);
371
+ Assume->insertBefore (I);
372
+
373
+ RetainedKnowledgeMap Map;
374
+ fillMapFromAssume (*Assume, Map);
375
+
376
+ Value *New = I->getFunction ()->getArg (3 );
377
+ Value *Old = I->getOperand (0 );
378
+ AssertFindExactlyAttributes (Map, New, " " );
379
+ AssertFindExactlyAttributes (Map, Old,
380
+ " (nonnull|align|dereferenceable)" );
381
+ Old->replaceAllUsesWith (New);
382
+ Map.clear ();
383
+ fillMapFromAssume (*Assume, Map);
384
+ AssertFindExactlyAttributes (Map, New,
385
+ " (nonnull|align|dereferenceable)" );
386
+ AssertFindExactlyAttributes (Map, Old, " " );
387
+ }));
388
+ RunTest (Head, Tail, Tests);
389
+ }
0 commit comments