delete loop by eraseFromParent command in llvm - llvm

*I would delete the Loop. I used the following code:
cout << "begin to delete loop" << endl;
for (Loop::block_iterator bi = L->block_begin(), bi2; bi != L->block_end(); bi = bi2) {
bi2 = bi;
bi2++;
BasicBlock * BB = *bi;
for (BasicBlock::iterator ii = BB->begin(), ii2; ii != BB->end(); ii= ii2) {
ii2 = ii;
ii2++;
Instruction *inst = ii;
inst->eraseFromParent();
}
BB->eraseFromParent();
}
But I get the following error:
Use still stuck around after Def is destroyed: %t1 = icmp sle i32 %t0, 9
opt: /home/llvm/src/lib/VMCore/Value.cpp:75: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.
0 opt 0x0848e569
Stack dump:
What suggestions do you have for solve this problem?*

The solution of you problem is as follows:
make sure that for each instruction in the loop to drop all references, then simply erase all the BasicBlocks of the loop.
here is my sample code
for (Loop::block_iterator block = CPLoop->block_begin(), end = CPLoop->block_end(); block != end; block++) {
BasicBlock * bb = *block;
for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II) {
Instruction * insII = &(*II);
insII->dropAllReferences();
}
}
for (Loop::block_iterator block = CPLoop->block_begin(), end = CPLoop->block_end(); block != end; block++) {
BasicBlock * bb = *block;
bb->removeFromParent();
}
I hope this helps

What I write is only a guess, cause I am just starting with LLVM, but I hope it will be helpful.
In SSA form each instruction:
uses values provided by previously executed instructions
provides value (with is result of executing this instruction), which is used by others.
Those are called use-def and def-use chains.
If you try to remove instruction which result (a.k.a. "provided Value") is used by other instructions, than you break instruction chain.
You might be interested in iteratating over users of instruction you remove, using :
LLVM Programmer's Manual : Iterating over def-use & use-def chains. Thanks to that, you can iterate over users (u) of value provided by instruction, you want to remove (inst), and change their reference to another one (like inst: add u v --> add X v). Ones you make sure no one is using instruction you want to remove, remove it. (Depending if analysis passes are already made you might be required to let llvm pass manager know that CFG analysis needs to be updated - unless you update them by yourself).

You are invalidating the iterator with the call to
inst->eraseFromParent();
Store all Instruction* in an std::vector or similar and batch delete them at the end of your pass.
This should solve your problem.

There is an alternative solution for "deleting" a loop: Just permanently disable it. I.e. modify the IR code from sth. like this:
...
br label %loop
loop:
<loop body>
br i1 %exitcond, label %exit, label %loop
exit:
...
to sth. like this:
...
br i1 0, label %loop, label %exit
loop:
<loop body>
br i1 %exitcond, label %exit, label %loop
exit:
...
You will probably run optimizations (like dead code elimination) on your generated IR anyways, so why fight with all the references to the loop (e.g. in LoopInfos or ValueMaps)?

Related

Google app script IF condition not matching 0, empty and null

I have issues with Google app script IF condition.
Problem i am facing its not returning value TRUE rather going to next/ Else statements.
Code i am having:
const numberOfRowsToUpdate = deliveryDate.length;
// For each item making the for loop to work
for (i=0 ; i < numberOfRowsToUpdate;i++) {
debugger;
var dp = depositAmount[i];
if(dp!==""|| dp!==0 || dp !==null || dp!==isblank())
{ .... <statements>
}
}
I want to check whether particular cell of the array is empty / zero / returning null value.
thanks in advance for the help.
SUGGESTION
I have used a similar script I'm using for a spreadsheet in which I need to search through every row for some data, but obviously adpating it to your case, and since I don't have your full code (and still can't comment asking for more info due to my recent joining in SO), I had to simplify it, in hope it will work for you.
What I did was use your incrementing i index from the for loop and use it to scan every row, while adjusting it to fit your array index, because we can't have i = 0 as a row index, and it would skip the first value on the array if left as i = 1).
SCRIPT
function test(){
const n = 6;
var depositAmount = [7,2,0,2,0,8];
// For each item making the for loop to work
var ss = SpreadsheetApp.getActive();
Logger.log(ss.getName());
for (var i=1 ; i <= n ;i++) {
debugger;
ss.getRange("A"+i).setValue(1);
var dp = depositAmount[i-1];
Logger.log(dp)
if(dp != "" || dp != 0 /*|| dp != null || dp != isblank()*/)
{
ss.getRange("B"+i).setValue(dp);
}
else
{
ss.getRange("C"+i).setValue("VOID")
Logger.log(i-1+"th index of array is "+ss.getRange("C"+i).getValue());
}
}
};
RESULTS
After running it with the four original conditions you used, i didn't get the expected result, as you must have, leading to this:
.
While studying your original code, I stumbled upon this question about the differences between == and ===, as well as != and !==.
So before I used this in our favor, I tried the old trial and error method, using only one condition at a time, and then stacking them up. Not only I managed to find out the !== operator didn't work properly for this case, but also the comparison with null and the isblank() function (at least in my case, because i haven't defined it, and I'm not sure it is a built-in function) also don't work with either operator.
Therefore, using the != operator helps you better than the strict !==.
The result of the final script is that:
.
NOTES
I also tried using a null value within the array ([7,2,0,2,,8]), but it would always break away from the loop, never scanning the whole array, and I don't know how to circle that.
Here is the Execution Log for this script:
EDIT
While fooling around, I found this question and the answer by Etienne de Villers might be even faster to apply, or at least more useful for your purposes.

How to insert a basic block between two block in LLVM

This is similar to Inserting a block between two blocks in LLVM however the solution description is unclear to me - or better - I tried to do it like described but it does not work (for me).
What I want to do:
Wherever a basic block has more then one successor, I want to insert a basic block.
So if basic block A does a conditional jump to B or C, I want to insert a basic block between A and B and between A and C. And it should also work if there is a jump table.
So what I do is:
while (...) {
// get next basic block and ensure it has at least 2 successors:
BasicBlock *origBB = getNextBB();
Instruction *TI = origBB->getTerminator()
if (!TI || TI->getNumSuccessors() < 2)
continue;
// collect successors:
std::vector<BasicBlock *> Successors;
for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB); SI != SE; ++SI) {
BasicBlock *succ = *SI;
Successors.push_back(succ);
}
// now for each successor:
for (uint32_t i = 0; i < Successors.size(); i++) {
// Create a new basic block
BasicBlock *BB = BasicBlock::Create(C, "", &F, nullptr);
// F.getBasicBlockList().push_back(BB); <= this did not work, seem to result in endless loop
IRBuilder<> IRB(BB);
// put instructions into BB
... // omitted
// then add the terminator:
IRB.CreateBr(Successors[i]);
// Now we have to fix the original BB to our new basic block:
TI->setSuccessor(i, BB);
}
}
When I run this LLVM pass I get the following error:
PHI node entries do not match predecessors!
OK so I thought I have to remove the corresponding predecessor from the successor and added the following code after the setSuccessor():
origBB->replaceSuccessorsPhiUsesWith(Successors[j], BB);
BasicBlock *S = Successors[i];
S->removePredecessor(origBB);
Then however I get the error Instruction does not dominate all uses!
I am sure the solution is very simple - but I cannot find it :-(
Thanks a lot for any help or pointers!
OK I am anwsering my own question here.
The comment proposing a) using splitBlock() is going into the wrong direction as it is about inserting into an edge so the result would be wrong. b) updating the phi would actually solve the issue. However this is very complex as a simple replacePhiUsesWith cannot be used - the case where A->B and A is a loop head and B a loob tail (so going back to B) will result in a compilation error, so all phis have to be carefully evaluated.
So the solution is actually very simple, which I found browsing through the source code of llvm: SplitEdge(). It does exactly what I want, inserting a a basic block between the edge of two basic blocks!
It is not obvious as the function is not documented in the doxygen class list, so other than by browsing sources and includes it cannot be found.
So here how to use it:
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
void inYourFunction() {
...
// Insert the new block into the edge between thisBB and a successorBB
BasicBlock *insertedBB = SplitEdge(thisBB, successorBB);
if (!insertedBB) {
// SplitEdge can fail, e.g. if the successor is a landing pad
return;
}
// Then put instructions into the new BB
BasicBlock::iterator IP = newBB->getFirstInsertionPt();
IRBuilder<> IRB(&(*IP));
// and then work with IRB
// You need not to take care of the branch to successorBB - it is already there
...
}
Thats it, its that simple.

How do I print out an Instruction in LLVM?

for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
i.print(errs()); ???
I am writing an LLVM PASS and I want to get the list of instructions inside the basic block, but how do print them out on the console so I can see them? The code above shows the code i have tried, it iterates through every instruction in the basic block but I get the error below for the print function.
error: ‘llvm::BasicBlock::iterator’ has no member named ‘print’
i.print(errs());
Is there a better approach to printing out instructions?
The problem is that you are trying to print the iterator and not an instruction. You can try one of the following approaches. You can print the instructions in a basic block by either printing the basic block or printing each instruction:
BasicBlock* bb = ...; //
errs() << *bb;
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; ++i) {
Instruction* ii = &*i;
errs() << *ii << "\n";
Both prints will output the same results.

How to Insert a LLVM Instruction?

I've been searching for hours and I can't find anything that could help me. I'm working on a project that involves a FunctionPass. I've implemented a runOnFunction(Function &f) method and that's working fine. Basically it needs to:
1) Detect a store instruction
2) Convert the memory address of the store instruction to an Integer
3) Alter the integer using a bitwise AND operation (0000FFFF)
4) Convert the integer back into the pointer
So far I've got the following:
virtual bool runOnFunction(Function &F) {
for (Function::iterator bb = F.begin(), bbe = F.end(); bb != bbe; ++bb) {
BasicBlock& b = *bb;
for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie; ++i) {
if(StoreInst *si = dyn_cast<StoreInst>(&*i)) {
PtrToIntInst* ptrToInt = new PtrToIntInst(si->getPointerOperand(), IntegerType::get(si->getContext(), 32), "", si);
}
}
}
return true;
}
I can't for the life of me figure out how to actually insert the instruction, or even find a way to create an AND instruction. If anyone could point me in the right direction, that would be great.
Thanks in advance.
I recommend taking a look at the Programmer's Manual - it has a pretty decent coverage of the basics.
In particular, there's a section about creating and inserting new instructions. The simplest way is just to provide an existing instruction as the last argument for the new instruction's constructor, which will then insert that instruction immediately before the existing one.
Alternatively, you can pass the enclosing basic block if you just want to add to its end (but remember you need to take care of the terminator!). Finally, you can just call getInstList() on the enclosing basic block, then insert or push_back to insert new instructions there.
As an aside, you don't have to iterate over all blocks and then over all instructions in each, you can just iterate over the instructions directly; see the section about the instruction iterator in the programmer's manual.
virtual bool runOnFunction(Function &F) {
for (Function::iterator bb = F.begin(), bbe = F.end(); bb != bbe; ++bb) {
BasicBlock &b = *bb;
for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie; ++i) {
if (StoreInst *si = dyn_cast<StoreInst>(&*i)) {
IRBuilder Builder(si);
Value *StoreAddr = Builder.CreatePtrToInt(si->getPointerOperand(), Builder.getInt32Ty());
Value *Masked = Builder.CreateAnd(StoreAddr, 0xffff);
Value *AlignedAddr = Builder.CreateIntToPtr(Masked, si->getPointerOperand()->getType());
// ...
}
}
}
return true;
}
You can use an IRBuilder to easily insert new instructions before another instruction or at the end of a basic block.
Alternatively, if you need to insert an instruction after another one, you need to use the instruction list in the containing basic block:
BasicBlock *pb = ...;
Instruction *pi = ...;
Instruction *newInst = new Instruction(...);
pb->getInstList().insertAfter(pi, newInst);
Code and solution taken from here.

std::list.splice() causes program to crash

I looked at a few examples and as far as I can tell I'm using the splice method correctly. However, when I run the program in debug mode under Visual C++, the call stack shows my call to splice eventually reaches this line where it crashes:
_Mynextiter = _Parent_proxy->_Myfirstiter;
The code:
for(std::list<Rect>::iterator i = rects.begin(); i != rects.end();)
{
if(i->isOverlapping(newRect))
{
Rect oldRect = (*i);
i = rects.erase(i);
std::list<Rect> & lr = oldRect.split(newRect);
//doesn't work either
//rects.splice(rects.begin(), lr, lr.begin(), lr.end());
rects.splice(rects.begin(), lr);
}
else i++;
}
It seems you are using std::list<T>::splice() the right way, if I refer to any manual pages on the internet.
At the contrary, I don't really like the reference in the line:
std::list<Rect> & lr = oldRect.split(newRect);
I don't know what is doing Rect::split() but you should try to copy its result. Does that help?