[PATCH] Disable inlining between sanitized and non-sanitized functions
Evgeniy Stepanov
eugenis at google.com
Tue Jun 25 05:15:09 PDT 2013
Hi chandlerc,
Inlining between functions with different values of sanitize_* attributes leads to over- or under-sanitizing, which is always bad.
Note that this will win even over always_inline attribute. Which is probably desirable.
http://llvm-reviews.chandlerc.com/D1035
Files:
test/Transforms/Inline/attributes.ll
lib/Transforms/IPO/Inliner.cpp
Index: test/Transforms/Inline/attributes.ll
===================================================================
--- test/Transforms/Inline/attributes.ll
+++ test/Transforms/Inline/attributes.ll
@@ -0,0 +1,59 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
+
+; Test that different values of sanitizer attribute prevent inlining.
+
+define i32 @test1f(i32 %i) {
+ ret i32 %i
+}
+
+define i32 @test1(i32 %W) {
+ %X = call i32 @test1f(i32 7)
+ %Y = add i32 %X, %W
+ ret i32 %Y
+; CHECK: @test1(
+; CHECK-NEXT: %Y = add i32 7, %W
+; CHECK-NEXT: ret i32 %Y
+}
+
+
+define i32 @test2f(i32 %i) sanitize_address {
+ ret i32 %i
+}
+
+define i32 @test2(i32 %W) sanitize_address {
+ %X = call i32 @test2f(i32 7)
+ %Y = add i32 %X, %W
+ ret i32 %Y
+; CHECK: @test2(
+; CHECK-NEXT: %Y = add i32 7, %W
+; CHECK-NEXT: ret i32 %Y
+}
+
+
+define i32 @test3f(i32 %i) sanitize_address {
+ ret i32 %i
+}
+
+define i32 @test3(i32 %W) {
+ %X = call i32 @test3f(i32 7)
+ %Y = add i32 %X, %W
+ ret i32 %Y
+; CHECK: @test3(
+; CHECK-NEXT: %X = call i32 @test3f
+; CHECK: ret i32 %Y
+}
+
+
+define i32 @test4f(i32 %i) {
+ ret i32 %i
+}
+
+define i32 @test4(i32 %W) sanitize_address {
+ %X = call i32 @test4f(i32 7)
+ %Y = add i32 %X, %W
+ ret i32 %Y
+; CHECK: @test4(
+; CHECK-NEXT: %X = call i32 @test4f
+; CHECK: ret i32 %Y
+}
Index: lib/Transforms/IPO/Inliner.cpp
===================================================================
--- lib/Transforms/IPO/Inliner.cpp
+++ lib/Transforms/IPO/Inliner.cpp
@@ -371,6 +371,30 @@
return false;
}
+/// FunctionsHaveCompatibleAttributes - Return true if there are no attribute
+/// conflicts between Caller and Callee that prevent inlining.
+static bool FunctionsHaveCompatibleAttributes(Function *Caller, Function *Callee) {
+ AttributeSet CallerAttr = Caller->getAttributes(),
+ CalleeAttr = Callee->getAttributes();
+
+ if (CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeAddress) !=
+ CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeAddress))
+ return false;
+ if (CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeMemory) !=
+ CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeMemory))
+ return false;
+ if (CallerAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeThread) !=
+ CalleeAttr.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::SanitizeThread))
+ return false;
+ return true;
+}
+
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraph>();
const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();
@@ -463,7 +487,10 @@
} else {
// We can only inline direct calls to non-declarations.
if (Callee == 0 || Callee->isDeclaration()) continue;
-
+
+ if (!FunctionsHaveCompatibleAttributes(Caller, Callee))
+ continue;
+
// If this call site was obtained by inlining another function, verify
// that the include path for the function did not include the callee
// itself. If so, we'd be recursively inlining the same function,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1035.1.patch
Type: text/x-patch
Size: 3551 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130625/c925bf39/attachment.bin>
More information about the llvm-commits
mailing list