From e70403f1977ee7c22814d8a45aff0bb39f95a194 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Sat, 7 Nov 2015 01:56:00 +0000 Subject: [PATCH] [FunctionAttrs] Add handling for operand bundles Summary: Teach the FunctionAttrs to do the right thing for IR with operand bundles. Reviewers: reames, chandlerc Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14408 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252387 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/FunctionAttrs.cpp | 35 ++++++++++++++++--- test/Feature/OperandBundles/function-attrs.ll | 24 +++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 test/Feature/OperandBundles/function-attrs.ll diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 6024137bfe3..b63ffb4a72c 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -328,7 +328,21 @@ struct ArgumentUsesTracker : public CaptureTracker { unsigned UseIndex = std::distance(const_cast(CS.arg_begin()), U); - assert(UseIndex < CS.arg_size() && "Non-argument use?"); + assert(UseIndex < CS.data_operands_size() && + "Indirect function calls should have been filtered above!"); + + if (UseIndex >= CS.getNumArgOperands()) { + // Data operand, but not a argument operand -- must be a bundle operand + assert(CS.hasOperandBundles() && "Must be!"); + + // CaptureTracking told us that we're being captured by an operand bundle + // use. In this case it does not matter if the callee is within our SCC + // or not -- we've been captured in some unknown way, and we have to be + // conservative. + Captured = true; + return true; + } + if (UseIndex >= F->arg_size()) { assert(F->isVarArg() && "More params than args in non-varargs call"); Captured = true; @@ -443,14 +457,27 @@ determinePointerReadAttrs(Argument *A, unsigned UseIndex = std::distance(CS.arg_begin(), U); - assert(UseIndex < CS.arg_size() && "Non-argument use?"); - if (UseIndex >= F->arg_size()) { + assert(UseIndex < CS.data_operands_size() && "Non-argument use?"); + + bool IsOperandBundleUse = UseIndex >= CS.getNumArgOperands(); + + if (UseIndex >= F->arg_size() && !IsOperandBundleUse) { assert(F->isVarArg() && "More params than args in non-varargs call"); return Attribute::None; } Captures &= !CS.doesNotCapture(UseIndex); - if (!SCCNodes.count(std::next(F->arg_begin(), UseIndex))) { + + // Since the optimizer (by design) cannot see the data flow corresponding + // to a operand bundle use, these cannot participate in the optimistic SCC + // analysis. Instead, we model the operand bundle uses as arguments in + // call to a function external to the SCC. + if (!SCCNodes.count(std::next(F->arg_begin(), UseIndex)) || + IsOperandBundleUse) { + + // The accessors used on CallSite here do the right thing for calls and + // invokes with operand bundles. + if (!CS.onlyReadsMemory() && !CS.onlyReadsMemory(UseIndex)) return Attribute::None; if (!CS.doesNotAccessMemory(UseIndex)) diff --git a/test/Feature/OperandBundles/function-attrs.ll b/test/Feature/OperandBundles/function-attrs.ll new file mode 100644 index 00000000000..3d429b3e9d9 --- /dev/null +++ b/test/Feature/OperandBundles/function-attrs.ll @@ -0,0 +1,24 @@ +; RUN: opt -S -functionattrs < %s | FileCheck %s + +declare void @f_readonly() readonly +declare void @f_readnone() readnone + +define void @test_0(i32* %x) { +; FunctionAttrs must not infer readonly / readnone for %x + +; CHECK-LABEL: define void @test_0(i32* %x) { + entry: + ; CHECK: call void @f_readonly() [ "foo"(i32* %x) ] + call void @f_readonly() [ "foo"(i32* %x) ] + ret void +} + +define void @test_1(i32* %x) { +; FunctionAttrs must not infer readonly / readnone for %x + +; CHECK-LABEL: define void @test_1(i32* %x) { + entry: + ; CHECK: call void @f_readnone() [ "foo"(i32* %x) ] + call void @f_readnone() [ "foo"(i32* %x) ] + ret void +} -- 2.34.1