16bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
26bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
36bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//                     The LLVM Compiler Infrastructure
46bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
56bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// This file is distributed under the University of Illinois Open Source
66bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// License. See LICENSE.TXT for details.
76bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//
86bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines//===----------------------------------------------------------------------===//
96bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "CGLoopInfo.h"
116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/BasicBlock.h"
126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/Constants.h"
136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/InstrTypes.h"
146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/Instructions.h"
156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "llvm/IR/Metadata.h"
166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesusing namespace clang;
176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesusing namespace CodeGen;
186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesusing namespace llvm;
196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!Attrs.IsParallel && Attrs.VectorizerWidth == 0 &&
236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Attrs.VectorizerUnroll == 0 &&
246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Attrs.VectorizerEnable == LoopAttributes::VecUnspecified)
256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SmallVector<Value *, 4> Args;
286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Reserve operand 0 for loop id self reference.
296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MDNode *TempNode = MDNode::getTemporary(Ctx, None);
306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Args.push_back(TempNode);
316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Setting vectorizer.width
336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Attrs.VectorizerWidth > 0) {
34ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.width"),
356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      ConstantInt::get(Type::getInt32Ty(Ctx),
366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       Attrs.VectorizerWidth) };
376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Args.push_back(MDNode::get(Ctx, Vals));
386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Setting vectorizer.unroll
416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Attrs.VectorizerUnroll > 0) {
42ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.unroll"),
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      ConstantInt::get(Type::getInt32Ty(Ctx),
446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       Attrs.VectorizerUnroll) };
456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Args.push_back(MDNode::get(Ctx, Vals));
466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Setting vectorizer.enable
496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Attrs.VectorizerEnable != LoopAttributes::VecUnspecified) {
50ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    Value *Vals[] = { MDString::get(Ctx, "llvm.loop.vectorize.enable"),
516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      ConstantInt::get(Type::getInt1Ty(Ctx),
526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                       (Attrs.VectorizerEnable ==
536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                        LoopAttributes::VecEnable)) };
546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Args.push_back(MDNode::get(Ctx, Vals));
556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MDNode *LoopID = MDNode::get(Ctx, Args);
586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(LoopID->use_empty() && "LoopID should not be used");
596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Set the first operand to itself.
616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  LoopID->replaceOperandWith(0, LoopID);
626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  MDNode::deleteTemporary(TempNode);
636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return LoopID;
646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesLoopAttributes::LoopAttributes(bool IsParallel)
676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : IsParallel(IsParallel), VectorizerEnable(LoopAttributes::VecUnspecified),
686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      VectorizerWidth(0), VectorizerUnroll(0) {}
696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid LoopAttributes::clear() {
716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  IsParallel = false;
726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  VectorizerWidth = 0;
736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  VectorizerUnroll = 0;
746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  VectorizerEnable = LoopAttributes::VecUnspecified;
756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesLoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    : LoopID(nullptr), Header(Header), Attrs(Attrs) {
796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  LoopID = createMetadata(Header->getContext(), Attrs);
806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid LoopInfoStack::push(BasicBlock *Header) {
836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Active.push_back(LoopInfo(Header, StagedAttrs));
846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Clear the attributes so nested loops do not inherit them.
856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  StagedAttrs.clear();
866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid LoopInfoStack::pop() {
896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(!Active.empty() && "No active loops to pop");
906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Active.pop_back();
916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid LoopInfoStack::InsertHelper(Instruction *I) const {
946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!hasInfo())
956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return;
966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const LoopInfo &L = getInfo();
986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!L.getLoopID())
996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return;
1006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
1026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
1036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (TI->getSuccessor(i) == L.getHeader()) {
1046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        TI->setMetadata("llvm.loop", L.getLoopID());
1056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        break;
1066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
1076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return;
1086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
1096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
1116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
1126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
113