llvm.org GIT mirror llvm / 7d085b6
[SimplifyCFG] Create attribute for fuzzing-specific optimizations. Summary: When building with libFuzzer, converting control flow to selects or obscuring the original operands of CMPs reduces the effectiveness of libFuzzer's heuristics. This patch provides an attribute to disable or modify certain optimizations for optimal fuzzing signal. Provides a less aggressive alternative to https://reviews.llvm.org/D44057. Reviewers: vitalybuka, davide, arsenm, hfinkel Reviewed By: vitalybuka Subscribers: junbuml, mehdi_amini, wdng, javed.absar, hiraditya, llvm-commits, kcc Differential Revision: https://reviews.llvm.org/D44232 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328214 91177308-0d34-0410-b5e6-96231b3b80d8 Matt Morehouse 2 years ago
13 changed file(s) with 76 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
587587 ATTR_KIND_STRICT_FP = 54,
588588 ATTR_KIND_SANITIZE_HWADDRESS = 55,
589589 ATTR_KIND_NOCF_CHECK = 56,
590 ATTR_KIND_OPT_FOR_FUZZING = 57,
590591 };
591592
592593 enum ComdatSelectionKindCodes {
110110
111111 /// Function doesn't unwind stack.
112112 def NoUnwind : EnumAttr<"nounwind">;
113
114 /// Select optimizations for best fuzzing signal.
115 def OptForFuzzing : EnumAttr<"optforfuzzing">;
113116
114117 /// opt_size.
115118 def OptimizeForSize : EnumAttr<"optsize">;
649649 KEYWORD(noreturn);
650650 KEYWORD(nocf_check);
651651 KEYWORD(nounwind);
652 KEYWORD(optforfuzzing);
652653 KEYWORD(optnone);
653654 KEYWORD(optsize);
654655 KEYWORD(readnone);
11331133 case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break;
11341134 case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
11351135 case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
1136 case lltok::kw_optforfuzzing:
1137 B.addAttribute(Attribute::OptForFuzzing); break;
11361138 case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break;
11371139 case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break;
11381140 case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break;
14701472 case lltok::kw_noreturn:
14711473 case lltok::kw_nocf_check:
14721474 case lltok::kw_nounwind:
1475 case lltok::kw_optforfuzzing:
14731476 case lltok::kw_optnone:
14741477 case lltok::kw_optsize:
14751478 case lltok::kw_returns_twice:
15641567 case lltok::kw_noreturn:
15651568 case lltok::kw_nocf_check:
15661569 case lltok::kw_nounwind:
1570 case lltok::kw_optforfuzzing:
15671571 case lltok::kw_optnone:
15681572 case lltok::kw_optsize:
15691573 case lltok::kw_returns_twice:
200200 kw_noreturn,
201201 kw_nocf_check,
202202 kw_nounwind,
203 kw_optforfuzzing,
203204 kw_optnone,
204205 kw_optsize,
205206 kw_readnone,
11601160 case Attribute::StrictFP: return 1ULL << 55;
11611161 case Attribute::SanitizeHWAddress: return 1ULL << 56;
11621162 case Attribute::NoCfCheck: return 1ULL << 57;
1163 case Attribute::OptForFuzzing: return 1ULL << 58;
11631164 case Attribute::Dereferenceable:
11641165 llvm_unreachable("dereferenceable attribute not supported in raw format");
11651166 break;
13421343 return Attribute::NoCfCheck;
13431344 case bitc::ATTR_KIND_NO_UNWIND:
13441345 return Attribute::NoUnwind;
1346 case bitc::ATTR_KIND_OPT_FOR_FUZZING:
1347 return Attribute::OptForFuzzing;
13451348 case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE:
13461349 return Attribute::OptimizeForSize;
13471350 case bitc::ATTR_KIND_OPTIMIZE_NONE:
641641 return bitc::ATTR_KIND_NOCF_CHECK;
642642 case Attribute::NoUnwind:
643643 return bitc::ATTR_KIND_NO_UNWIND;
644 case Attribute::OptForFuzzing:
645 return bitc::ATTR_KIND_OPT_FOR_FUZZING;
644646 case Attribute::OptimizeForSize:
645647 return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE;
646648 case Attribute::OptimizeNone:
304304 return "norecurse";
305305 if (hasAttribute(Attribute::NoUnwind))
306306 return "nounwind";
307 if (hasAttribute(Attribute::OptForFuzzing))
308 return "optforfuzzing";
307309 if (hasAttribute(Attribute::OptimizeNone))
308310 return "optnone";
309311 if (hasAttribute(Attribute::OptimizeForSize))
14291429 case Attribute::Builtin:
14301430 case Attribute::NoBuiltin:
14311431 case Attribute::Cold:
1432 case Attribute::OptForFuzzing:
14321433 case Attribute::OptimizeNone:
14331434 case Attribute::JumpTable:
14341435 case Attribute::Convergent:
4444 .Case("nocf_check", Attribute::NoCfCheck)
4545 .Case("norecurse", Attribute::NoRecurse)
4646 .Case("nounwind", Attribute::NoUnwind)
47 .Case("optforfuzzing", Attribute::OptForFuzzing)
4748 .Case("optnone", Attribute::OptimizeNone)
4849 .Case("optsize", Attribute::OptimizeForSize)
4950 .Case("readnone", Attribute::ReadNone)
683683 case Attribute::NonLazyBind:
684684 case Attribute::NoRedZone:
685685 case Attribute::NoUnwind:
686 case Attribute::OptForFuzzing:
686687 case Attribute::OptimizeNone:
687688 case Attribute::OptimizeForSize:
688689 case Attribute::SafeStack:
22722272 // dependence information for this check, but simplifycfg can't keep it up
22732273 // to date, and this catches most of the cases we care about anyway.
22742274 BasicBlock *BB = PN->getParent();
2275 const Function *Fn = BB->getParent();
2276 if (Fn && Fn->hasFnAttribute(Attribute::OptForFuzzing))
2277 return false;
2278
22752279 BasicBlock *IfTrue, *IfFalse;
22762280 Value *IfCond = GetIfCondition(BB, IfTrue, IfFalse);
22772281 if (!IfCond ||
57985802
57995803 bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
58005804 BasicBlock *BB = BI->getParent();
5805 const Function *Fn = BB->getParent();
5806 if (Fn && Fn->hasFnAttribute(Attribute::OptForFuzzing))
5807 return false;
58015808
58025809 // Conditional branch
58035810 if (isValueEqualityComparison(BI)) {
0 ; RUN: opt < %s -simplifycfg -S | FileCheck %s
1
2 define i32 @foo(i32 %x) optforfuzzing {
3 entry:
4 %x.addr = alloca i32, align 4
5 store i32 %x, i32* %x.addr, align 4
6 %0 = load i32, i32* %x.addr, align 4
7 %cmp = icmp sgt i32 %0, 16
8 br i1 %cmp, label %land.rhs, label %land.end
9
10 land.rhs:
11 %1 = load i32, i32* %x.addr, align 4
12 %cmp1 = icmp slt i32 %1, 32
13 br label %land.end
14
15 land.end:
16 %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
17 %conv = zext i1 %2 to i32
18 ret i32 %conv
19
20 ; CHECK-LABEL: define i32 @foo(i32 %x)
21 ; CHECK: br i1 %cmp, label %land.rhs, label %land.end
22 ; CHECK-LABEL: land.rhs:
23 ; CHECK: br label %land.end
24 ; CHECK-LABEL: land.end:
25 ; CHECK: phi {{.*}} %entry {{.*}} %land.rhs
26 }
27
28 define i32 @bar(i32 %x) {
29 entry:
30 %x.addr = alloca i32, align 4
31 store i32 %x, i32* %x.addr, align 4
32 %0 = load i32, i32* %x.addr, align 4
33 %cmp = icmp sgt i32 %0, 16
34 br i1 %cmp, label %land.rhs, label %land.end
35
36 land.rhs:
37 %1 = load i32, i32* %x.addr, align 4
38 %cmp1 = icmp slt i32 %1, 32
39 br label %land.end
40
41 land.end:
42 %2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
43 %conv = zext i1 %2 to i32
44 ret i32 %conv
45
46 ; CHECK-LABEL: define i32 @bar(i32 %x)
47 ; CHECK-NOT: br
48 }