L->isLoopInvariant giving wrong results?

Hi,
I’m trying to write a simple pass to print out Loop invariant instructions, using the
Loop::isLoopInvariant(Instruction *I)
function. it is giving me false value on instructions which should be loop invariant.

the code i am using is:

bool MyLoopPass::runOnLoop(Loop * L, LPPassManager &lpm){
BasicBlock* lat=L->getLoopLatch();
for (BasicBlock::iterator i = lat->begin(), e = lat->end(); i != e; ++i){
Instruction* hijk= i;
if(L->isLoopInvariant(hijk))
errs() << “hurray " << *hijk << " is loop invariant\n”;
else
errs() << “bad luck\n”;
}
return false;
}

the loop latch prints as:

bb: ; preds = %bb1
store i32 21, i32* %ij, align 4
store i32 10, i32* %j, align 4
%0 = load i32* %i, align 4
%1 = call i32 (i8*, …)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %0) nounwind
%2 = load i32* %i, align 4
%3 = sub nsw i32 %2, 1
store i32 %3, i32* %i, align 4
br label %bb1

the first instruction " store i32 21, i32* %ij, align 4"
is clearly loop invariant (corresponds to j=10; in c-code)
but all i am getting is “bad luck”.

am i doing something wrong here? or is the function incomplete/wrong?

Hi,
I'm trying to write a simple pass to print out Loop invariant instructions, using the
Loop::isLoopInvariant(Instruction *I)
function. it is giving me false value on instructions which should be loop invariant.

the code i am using is:

The isLoopInvariant method just works for scalar operations like 'add' and 'multiply'. It doesn't apply to memory operations, because hoisting them requires more analysis (e.g. mod-ref analysis for the rest of the loop). Please see the LICM pass to see how to do this.

-Chris

Thanks Chris,

I was able to weed out loop invariant arithmetic instructions using isLoopInvariant function.
when i try to do an instruction->moveBefore(bb->getTerminator()) i’m getting a seg fault.
any obvious reasons that i’m missing out on?

Thanks in advance

No idea, sorry.

-Chris

The funny thing is that i am manually able to hoist the Loop invariant instruction to the basicBlock terminator, by editing the human readable form and then using llvm-as to convert it into bytecode.

i am getting seg fault on functions like I->eraseFromParent also.
I’m assuming that the problem comes when i change the loop structure.

my changed code.

namespace {
class MyLoopPass:public LoopPass {
bool changed;
public:
static char ID;
Loop* curLoop;
// AnalysisType* AA;
DominatorTree* DT;
LoopInfo* LI;
MyLoopPass() : LoopPass(ID){}
bool isLoopInvariantInst(Instruction &I) ;
bool runOnLoop(Loop * L, LPPassManager &lpm);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired();
AU.addRequired();
AU.addRequiredID(LoopSimplifyID);
AU.addPreserved();
AU.addPreservedID(LoopSimplifyID);
}
};
}

char MyLoopPass::ID=0;
INITIALIZE_PASS(MyLoopPass, “myLICM”, “simple LICM pass”, false, false);

bool MyLoopPass::runOnLoop(Loop * L, LPPassManager &lpm){
//find loop pre-header
BasicBlock* pre=L->getLoopPreheader();
curLoop=L;
changed=false;
BasicBlock* lat=L->getLoopLatch();
LI = &getAnalysis();
DT = &getAnalysis();

errs() <<“Loop Pre-Header:” << *pre;
errs() <<“Loop Latch:” << *lat;

for (BasicBlock::iterator i = lat->begin(), e = lat->end(); i != e; ++i){
Instruction* hijk= i;
// find out if the statement is a branch or whatever.
if(hijk->isSafeToSpeculativelyExecute()){
if(isLoopInvariantInst(*hijk)){
errs() << " " << *hijk << " is loop invariant\n";
errs() << " hoisting to " << pre->getName() << “\n”;
// This is where all the trouble happens.
hijk->moveBefore(pre->getTerminator());
changed=true;
}
}
}

return changed;
}

bool MyLoopPass::isLoopInvariantInst(Instruction &I) {
// The instruction is loop invariant if all of its operands are loop-invariant
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
if (!curLoop->isLoopInvariant(I.getOperand(i)))
return false;
// If we got this far, the instruction is loop invariant!
return true;
}

So you move this instruction, and then keep iterating in the basicblock.
I don't think the iterator is safe to use after a removal, try
incrementing 'i' earlier, and then perform the erase.

Best regards
--Edwin