Использование llvm do разворачивает цикл, ошибка при разбиении блока

Я делаю llvm для некоторой базовой практики преобразования цикла. Целевой цикл, который я хочу преобразовать, выглядит следующим образом:

int main ()
{
    int j=0,i=0;
    int x[100][5000] = {0};  

    for (i = 0; i < 100; i = i+1){
        for (j = 0; j < 5000; j = j+1){
            x[i][j] = 2 * x[i][j];
        }       
    }
   return 0;
}

IR этого кода имеет структуру вложенного цикла:

entry:
 ....
for.cond:
 ....
for.body:
 ....
for.cond1:
 ....
for.body3: 
 ....
for.inc:
 ....
for.end:

Когда я хочу развернуть внутренний цикл for.cond1, for.body3 и for.inc, эти три части. Сначала я разделяю for.body3 в ветке команд, а затем хочу вставить новый развернутый блок между ними:

  %3 = load i32* %j, align 4
  %idxprom = sext i32 %3 to i64
  %4 = load i32* %i, align 4
  %idxprom4 = sext i32 %4 to i64
  %arrayidx = getelementptr inbounds [5000 x [100 x i32]]* %x, i32 0, i64 %idxprom4
  %arrayidx5 = getelementptr inbounds [100 x i32]* %arrayidx, i32 0, i64 %idxprom
  %5 = load i32* %arrayidx5, align 4
  %mul = mul nsw i32 2, %5
  %6 = load i32* %j, align 4
  %idxprom6 = sext i32 %6 to i64
  %7 = load i32* %i, align 4
  %idxprom7 = sext i32 %7 to i64
  %arrayidx8 = getelementptr inbounds [5000 x [100 x i32]]* %x, i32 0, i64 %idxprom7
  %arrayidx9 = getelementptr inbounds [100 x i32]* %arrayidx8, i32 0, i64 %idxprom6
  store i32 %mul, i32* %arrayidx9, align 4

  // insert new blocks here

  br label %for.inc

Но когда я даю инструкции в моем проходе, я получаю ошибку.

моя инструкция:

BasicBlock *bb_new = bb->splitBasicBlock(inst_br);

Ошибка:

Assertion (`HasInsideLoopSuccs && "Loop block has no in-loop successors!)

Может кто-нибудь знакомый с llvm подскажет в чем проблема? Или у меня есть другие способы разделить блок и вставить развернутые?

HasInsideLoopSuccs устанавливается в следующем LoopInfoImpl.h

// Check the individual blocks.
for ( ; BI != BE; ++BI) {
BlockT *BB = *BI;
bool HasInsideLoopSuccs = false;
bool HasInsideLoopPreds = false;
SmallVector<BlockT *, 2> OutsideLoopPreds;

typedef GraphTraits<BlockT*> BlockTraits;
for (typename BlockTraits::ChildIteratorType SI =
       BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
     SI != SE; ++SI)
  if (contains(*SI)) {
    HasInsideLoopSuccs = true;
    break;
  }

26.11 добавить: это мой пропуск.

class IndependentUnroll : public llvm::LoopPass
{
    public:

    virtual void unroll(llvm::Loop *L){

        for (Loop::block_iterator block = L->block_begin(); block !=
        L->block_end(); block++) {
            BasicBlock *bb = *block;
            /* Handle loop body.  */
            if (string(bb->getName()).find("for.body3") !=string::npos) {
                Instruction *inst = &bb->back();
                    BasicBlock *new_bb = bb->splitBasicBlock(inst);
                    /*Then the code get crashed!*/
            }
        }
    }

IndependentUnroll() : llvm::LoopPass(IndependentUnroll::ID) { }

virtual bool runOnLoop(llvm::Loop *L, llvm::LPPassManager &LPM) {

    if (L->getLoopDepth() == 1){
        unroll(L);
    }
}
static char ID;

};

1 ответ

Ваш внутренний цикл for:

for (j = 0; j < 5000; j = i+1) {

Вы имеете в виду, что приращение будет:

j = j + 1

Чтобы избежать бесконечного цикла?

Другие вопросы по тегам