diff options
author | Philip Reames <preames@rivosinc.com> | 2023-03-14 08:39:19 -0700 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2023-03-14 10:38:02 -0700 |
commit | 9227f286acd8f411b74908b4f1a42a0d748b5cac (patch) | |
tree | d9eed0afcf1818f053aaa2c1fc19dab302921ec9 /llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | |
parent | f52c9500b426d249d083b747a70865e2a7190763 (diff) | |
download | llvm-9227f286acd8f411b74908b4f1a42a0d748b5cac.zip llvm-9227f286acd8f411b74908b4f1a42a0d748b5cac.tar.gz llvm-9227f286acd8f411b74908b4f1a42a0d748b5cac.tar.bz2 |
Move utility for acting on each lane of ElementCount to common code [nfc]
This was first written for AddressSanitizer, but I'm about to reuse it for MemorySanitizer as well.
Diffstat (limited to 'llvm/lib/Transforms/Utils/BasicBlockUtils.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/BasicBlockUtils.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 0dd3857..2d1be2c 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -32,6 +32,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" @@ -1599,6 +1600,61 @@ void llvm::SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore, } } +/// Insert a for (int i = 0; i < End; i++) loop structure (with the exception +/// that \p End is assumed > 0, and thus not checked on entry) at \p +/// SplitBefore. Returns the first insert point in the loop body, and the +/// PHINode for the induction variable (i.e. "i" above). +static std::pair<Instruction*, Value*> +SplitBlockAndInsertSimpleForLoop(Value *End, Instruction *SplitBefore) { + BasicBlock *LoopPred = SplitBefore->getParent(); + BasicBlock *LoopBody = SplitBlock(SplitBefore->getParent(), SplitBefore); + BasicBlock *LoopExit = SplitBlock(SplitBefore->getParent(), SplitBefore); + + auto *Ty = End->getType(); + auto &DL = SplitBefore->getModule()->getDataLayout(); + const unsigned Bitwidth = DL.getTypeSizeInBits(Ty); + + IRBuilder<> Builder(LoopBody->getTerminator()); + auto *IV = Builder.CreatePHI(Ty, 2, "iv"); + auto *IVNext = + Builder.CreateAdd(IV, ConstantInt::get(Ty, 1), IV->getName() + ".next", + /*HasNUW=*/true, /*HasNSW=*/Bitwidth != 2); + auto *IVCheck = Builder.CreateICmpEQ(IVNext, End, + IV->getName() + ".check"); + Builder.CreateCondBr(IVCheck, LoopExit, LoopBody); + LoopBody->getTerminator()->eraseFromParent(); + + // Populate the IV PHI. + IV->addIncoming(ConstantInt::get(Ty, 0), LoopPred); + IV->addIncoming(IVNext, LoopBody); + + return std::make_pair(LoopBody->getFirstNonPHI(), IV); +} + +void llvm::SplitBlockAndInsertForEachLane(ElementCount EC, + Type *IndexTy, Instruction *InsertBefore, + std::function<void(IRBuilderBase&, Value*)> Func) { + + IRBuilder<> IRB(InsertBefore); + + if (EC.isScalable()) { + Value *NumElements = IRB.CreateElementCount(IndexTy, EC); + + auto [BodyIP, Index] = + SplitBlockAndInsertSimpleForLoop(NumElements, InsertBefore); + + IRB.SetInsertPoint(BodyIP); + Func(IRB, Index); + return; + } + + unsigned Num = EC.getFixedValue(); + for (unsigned Idx = 0; Idx < Num; ++Idx) { + IRB.SetInsertPoint(InsertBefore); + Func(IRB, ConstantInt::get(IndexTy, Idx)); + } +} + BranchInst *llvm::GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, BasicBlock *&IfFalse) { PHINode *SomePHI = dyn_cast<PHINode>(BB->begin()); |