1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[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

llvm-svn: 328214
This commit is contained in:
Matt Morehouse 2018-03-22 17:07:51 +00:00
parent c65ff81b00
commit 3102888fd3
13 changed files with 76 additions and 0 deletions

View File

@ -588,6 +588,7 @@ enum AttributeKindCodes {
ATTR_KIND_STRICT_FP = 54,
ATTR_KIND_SANITIZE_HWADDRESS = 55,
ATTR_KIND_NOCF_CHECK = 56,
ATTR_KIND_OPT_FOR_FUZZING = 57,
};
enum ComdatSelectionKindCodes {

View File

@ -112,6 +112,9 @@ def NoCfCheck : EnumAttr<"nocf_check">;
/// Function doesn't unwind stack.
def NoUnwind : EnumAttr<"nounwind">;
/// Select optimizations for best fuzzing signal.
def OptForFuzzing : EnumAttr<"optforfuzzing">;
/// opt_size.
def OptimizeForSize : EnumAttr<"optsize">;

View File

@ -650,6 +650,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(noreturn);
KEYWORD(nocf_check);
KEYWORD(nounwind);
KEYWORD(optforfuzzing);
KEYWORD(optnone);
KEYWORD(optsize);
KEYWORD(readnone);

View File

@ -1134,6 +1134,8 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break;
case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break;
case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break;
case lltok::kw_optforfuzzing:
B.addAttribute(Attribute::OptForFuzzing); break;
case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break;
case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break;
case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break;
@ -1471,6 +1473,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
case lltok::kw_noreturn:
case lltok::kw_nocf_check:
case lltok::kw_nounwind:
case lltok::kw_optforfuzzing:
case lltok::kw_optnone:
case lltok::kw_optsize:
case lltok::kw_returns_twice:
@ -1565,6 +1568,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
case lltok::kw_noreturn:
case lltok::kw_nocf_check:
case lltok::kw_nounwind:
case lltok::kw_optforfuzzing:
case lltok::kw_optnone:
case lltok::kw_optsize:
case lltok::kw_returns_twice:

View File

@ -201,6 +201,7 @@ enum Kind {
kw_noreturn,
kw_nocf_check,
kw_nounwind,
kw_optforfuzzing,
kw_optnone,
kw_optsize,
kw_readnone,

View File

@ -1161,6 +1161,7 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
case Attribute::StrictFP: return 1ULL << 55;
case Attribute::SanitizeHWAddress: return 1ULL << 56;
case Attribute::NoCfCheck: return 1ULL << 57;
case Attribute::OptForFuzzing: return 1ULL << 58;
case Attribute::Dereferenceable:
llvm_unreachable("dereferenceable attribute not supported in raw format");
break;
@ -1343,6 +1344,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
return Attribute::NoCfCheck;
case bitc::ATTR_KIND_NO_UNWIND:
return Attribute::NoUnwind;
case bitc::ATTR_KIND_OPT_FOR_FUZZING:
return Attribute::OptForFuzzing;
case bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE:
return Attribute::OptimizeForSize;
case bitc::ATTR_KIND_OPTIMIZE_NONE:

View File

@ -642,6 +642,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
return bitc::ATTR_KIND_NOCF_CHECK;
case Attribute::NoUnwind:
return bitc::ATTR_KIND_NO_UNWIND;
case Attribute::OptForFuzzing:
return bitc::ATTR_KIND_OPT_FOR_FUZZING;
case Attribute::OptimizeForSize:
return bitc::ATTR_KIND_OPTIMIZE_FOR_SIZE;
case Attribute::OptimizeNone:

View File

@ -305,6 +305,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "norecurse";
if (hasAttribute(Attribute::NoUnwind))
return "nounwind";
if (hasAttribute(Attribute::OptForFuzzing))
return "optforfuzzing";
if (hasAttribute(Attribute::OptimizeNone))
return "optnone";
if (hasAttribute(Attribute::OptimizeForSize))

View File

@ -1430,6 +1430,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::Builtin:
case Attribute::NoBuiltin:
case Attribute::Cold:
case Attribute::OptForFuzzing:
case Attribute::OptimizeNone:
case Attribute::JumpTable:
case Attribute::Convergent:

View File

@ -45,6 +45,7 @@ static Attribute::AttrKind parseAttrKind(StringRef Kind) {
.Case("nocf_check", Attribute::NoCfCheck)
.Case("norecurse", Attribute::NoRecurse)
.Case("nounwind", Attribute::NoUnwind)
.Case("optforfuzzing", Attribute::OptForFuzzing)
.Case("optnone", Attribute::OptimizeNone)
.Case("optsize", Attribute::OptimizeForSize)
.Case("readnone", Attribute::ReadNone)

View File

@ -684,6 +684,7 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs,
case Attribute::NonLazyBind:
case Attribute::NoRedZone:
case Attribute::NoUnwind:
case Attribute::OptForFuzzing:
case Attribute::OptimizeNone:
case Attribute::OptimizeForSize:
case Attribute::SafeStack:

View File

@ -2273,6 +2273,10 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
// dependence information for this check, but simplifycfg can't keep it up
// to date, and this catches most of the cases we care about anyway.
BasicBlock *BB = PN->getParent();
const Function *Fn = BB->getParent();
if (Fn && Fn->hasFnAttribute(Attribute::OptForFuzzing))
return false;
BasicBlock *IfTrue, *IfFalse;
Value *IfCond = GetIfCondition(BB, IfTrue, IfFalse);
if (!IfCond ||
@ -5799,6 +5803,9 @@ static BasicBlock *allPredecessorsComeFromSameSource(BasicBlock *BB) {
bool SimplifyCFGOpt::SimplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
BasicBlock *BB = BI->getParent();
const Function *Fn = BB->getParent();
if (Fn && Fn->hasFnAttribute(Attribute::OptForFuzzing))
return false;
// Conditional branch
if (isValueEqualityComparison(BI)) {

View File

@ -0,0 +1,49 @@
; RUN: opt < %s -simplifycfg -S | FileCheck %s
define i32 @foo(i32 %x) optforfuzzing {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%cmp = icmp sgt i32 %0, 16
br i1 %cmp, label %land.rhs, label %land.end
land.rhs:
%1 = load i32, i32* %x.addr, align 4
%cmp1 = icmp slt i32 %1, 32
br label %land.end
land.end:
%2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
%conv = zext i1 %2 to i32
ret i32 %conv
; CHECK-LABEL: define i32 @foo(i32 %x)
; CHECK: br i1 %cmp, label %land.rhs, label %land.end
; CHECK-LABEL: land.rhs:
; CHECK: br label %land.end
; CHECK-LABEL: land.end:
; CHECK: phi {{.*}} %entry {{.*}} %land.rhs
}
define i32 @bar(i32 %x) {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
%0 = load i32, i32* %x.addr, align 4
%cmp = icmp sgt i32 %0, 16
br i1 %cmp, label %land.rhs, label %land.end
land.rhs:
%1 = load i32, i32* %x.addr, align 4
%cmp1 = icmp slt i32 %1, 32
br label %land.end
land.end:
%2 = phi i1 [ false, %entry ], [ %cmp1, %land.rhs ]
%conv = zext i1 %2 to i32
ret i32 %conv
; CHECK-LABEL: define i32 @bar(i32 %x)
; CHECK-NOT: br
}