[llvm] r183933 - Fix DeleteDeadVarargs not to crash on functions referenced by BlockAddresses
Derek Schuff
dschuff at google.com
Thu Jun 13 13:07:22 PDT 2013
+Mark
On Thu, Jun 13, 2013 at 1:05 PM, Nick Lewycky <nicholas at mxc.ca> wrote:
> Derek Schuff wrote:
>
>> Author: dschuff
>> Date: Thu Jun 13 14:51:17 2013
>> New Revision: 183933
>>
>> URL: http://llvm.org/viewvc/llvm-**project?rev=183933&view=rev<http://llvm.org/viewvc/llvm-project?rev=183933&view=rev>
>> Log:
>> Fix DeleteDeadVarargs not to crash on functions referenced by
>> BlockAddresses
>>
>> This pass was assuming that if hasAddressTaken() returns false for a
>> function, the function's only uses are call sites. That's not true
>> because there can be references by BlockAddresses too.
>>
>> Fix the pass to handle this case. Fix
>> BlockAddress::**replaceUsesOfWithOnConstant() to allow a function's type
>> to be changed by RAUW'ing the function with a bitcast of the recreated
>> function.
>>
>> Patch by Mark Seaborn.
>>
>> Added:
>> llvm/trunk/test/Transforms/**DeadArgElim/2013-05-17-**
>> VarargsAndBlockAddress.ll
>> Modified:
>> llvm/trunk/lib/IR/Constants.**cpp
>> llvm/trunk/lib/Transforms/IPO/**DeadArgumentElimination.cpp
>>
>> Modified: llvm/trunk/lib/IR/Constants.**cpp
>> URL: http://llvm.org/viewvc/llvm-**project/llvm/trunk/lib/IR/**
>> Constants.cpp?rev=183933&r1=**183932&r2=183933&view=diff<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=183933&r1=183932&r2=183933&view=diff>
>> ==============================**==============================**
>> ==================
>> --- llvm/trunk/lib/IR/Constants.**cpp (original)
>> +++ llvm/trunk/lib/IR/Constants.**cpp Thu Jun 13 14:51:17 2013
>> @@ -1389,7 +1389,7 @@ void BlockAddress::**replaceUsesOfWithOnCo
>> BasicBlock *NewBB = getBasicBlock();
>>
>> if (U ==&Op<0>())
>>
>> - NewF = cast<Function>(To);
>> + NewF = cast<Function>(To->**stripPointerCasts());
>>
>
> This makes me extremely nervous. This function is very low level, it seems
> like it shouldn't be doing anything like calling stripPointerCasts(),
> that'd be like rigging SmallVector to call eraseFromParent for you or
> something.
>
> What are the alternatives here, making BlockAddress hold a ConstantExpr
> instead of a Function? Because I can see why that's also very bad.
>
> What happens if To really isn't a function? What if I create an undef of
> function type, then RAUW the function to that? Could you write a testcase
> under unittests/ for that case? (No, it's not clear to me that it worked
> before either.)
>
> Nick
>
>
> else
>> NewBB = cast<BasicBlock>(To);
>>
>>
>> Modified: llvm/trunk/lib/Transforms/IPO/**DeadArgumentElimination.cpp
>> URL: http://llvm.org/viewvc/llvm-**project/llvm/trunk/lib/**
>> Transforms/IPO/**DeadArgumentElimination.cpp?**rev=183933&r1=183932&r2=**
>> 183933&view=diff<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=183933&r1=183932&r2=183933&view=diff>
>> ==============================**==============================**
>> ==================
>> --- llvm/trunk/lib/Transforms/IPO/**DeadArgumentElimination.cpp
>> (original)
>> +++ llvm/trunk/lib/Transforms/IPO/**DeadArgumentElimination.cpp Thu Jun
>> 13 14:51:17 2013
>> @@ -263,8 +263,10 @@ bool DAE::DeleteDeadVarargs(**Function&Fn
>> // to pass in a smaller number of arguments into the new function.
>> //
>> std::vector<Value*> Args;
>> - while (!Fn.use_empty()) {
>> - CallSite CS(Fn.use_back());
>> + for (Value::use_iterator I = Fn.use_begin(), E = Fn.use_end(); I != E;
>> ) {
>> + CallSite CS(*I++);
>> + if (!CS)
>> + continue;
>> Instruction *Call = CS.getInstruction();
>>
>> // Pass all the same arguments.
>> @@ -330,6 +332,11 @@ bool DAE::DeleteDeadVarargs(**Function&Fn
>> if (DI != FunctionDIs.end())
>> DI->second.replaceFunction(NF)**;
>>
>> + // Fix up any BlockAddresses that refer to the function.
>> + Fn.replaceAllUsesWith(**ConstantExpr::getBitCast(NF, Fn.getType()));
>> + // Delete the bitcast that we just created, so that NF does not
>> + // appear to be address-taken.
>> + NF->removeDeadConstantUsers();
>> // Finally, nuke the old function.
>> Fn.eraseFromParent();
>> return true;
>>
>> Added: llvm/trunk/test/Transforms/**DeadArgElim/2013-05-17-**
>> VarargsAndBlockAddress.ll
>> URL: http://llvm.org/viewvc/llvm-**project/llvm/trunk/test/**
>> Transforms/DeadArgElim/2013-**05-17-VarargsAndBlockAddress.**
>> ll?rev=183933&view=auto<http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/2013-05-17-VarargsAndBlockAddress.ll?rev=183933&view=auto>
>> ==============================**==============================**
>> ==================
>> --- llvm/trunk/test/Transforms/**DeadArgElim/2013-05-17-**VarargsAndBlockAddress.ll
>> (added)
>> +++ llvm/trunk/test/Transforms/**DeadArgElim/2013-05-17-**VarargsAndBlockAddress.ll
>> Thu Jun 13 14:51:17 2013
>> @@ -0,0 +1,25 @@
>> +; RUN: opt %s -deadargelim -S | FileCheck %s
>> +
>> +
>> + at block_addr = global i8* blockaddress(@varargs_func, %l1)
>> +; CHECK: @block_addr = global i8* blockaddress(@varargs_func, %l1)
>> +
>> +
>> +; This function is referenced by a "blockaddress" constant but it is
>> +; not address-taken, so the pass should be able to remove its unused
>> +; varargs.
>> +
>> +define internal i32 @varargs_func(i8* %addr, ...) {
>> + indirectbr i8* %addr, [ label %l1, label %l2 ]
>> +l1:
>> + ret i32 1
>> +l2:
>> + ret i32 2
>> +}
>> +; CHECK: define internal i32 @varargs_func(i8* %addr) {
>> +
>> +define i32 @caller(i8* %addr) {
>> + %r = call i32 (i8*, ...)* @varargs_func(i8* %addr)
>> + ret i32 %r
>> +}
>> +; CHECK: %r = call i32 @varargs_func(i8* %addr)
>>
>>
>> ______________________________**_________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/**mailman/listinfo/llvm-commits<http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130613/b51fc2a6/attachment.html>
More information about the llvm-commits
mailing list