2017-06-27 06:44:03 +08:00
|
|
|
|
//===- llvm/CodeGen/GlobalISel/IRTranslator.cpp - IRTranslator ---*- C++ -*-==//
|
2016-01-21 04:58:56 +08:00
|
|
|
|
//
|
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
|
//
|
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
/// \file
|
|
|
|
|
/// This file implements the IRTranslator class.
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2017-02-24 07:57:28 +08:00
|
|
|
|
#include "llvm/ADT/ScopeExit.h"
|
2017-01-18 06:13:50 +08:00
|
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2016-02-12 03:59:41 +08:00
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-10-10 07:19:02 +08:00
|
|
|
|
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
|
2016-11-10 06:39:54 +08:00
|
|
|
|
#include "llvm/CodeGen/Analysis.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
|
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/CodeGen/LowLevelType.h"
|
|
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2016-07-23 00:59:52 +08:00
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
|
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
2016-02-12 01:51:31 +08:00
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
|
#include "llvm/CodeGen/TargetFrameLowering.h"
|
|
|
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
2016-08-27 07:49:05 +08:00
|
|
|
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
2016-02-12 01:51:31 +08:00
|
|
|
|
#include "llvm/IR/Constant.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
2017-01-27 07:39:14 +08:00
|
|
|
|
#include "llvm/IR/DebugInfo.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
2016-02-11 06:59:27 +08:00
|
|
|
|
#include "llvm/IR/Function.h"
|
2016-09-12 19:20:22 +08:00
|
|
|
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/InlineAsm.h"
|
|
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
|
#include "llvm/IR/Instructions.h"
|
2016-07-30 06:32:36 +08:00
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
|
#include "llvm/IR/Metadata.h"
|
2016-02-12 01:51:31 +08:00
|
|
|
|
#include "llvm/IR/Type.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/IR/User.h"
|
2016-02-12 01:51:31 +08:00
|
|
|
|
#include "llvm/IR/Value.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
|
#include "llvm/Pass.h"
|
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
|
#include "llvm/Support/CodeGen.h"
|
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
|
#include "llvm/Support/LowLevelTypeImpl.h"
|
|
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2016-07-30 06:32:36 +08:00
|
|
|
|
#include "llvm/Target/TargetIntrinsicInfo.h"
|
2017-06-27 06:44:03 +08:00
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <iterator>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
2016-02-11 06:59:27 +08:00
|
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "irtranslator"
|
|
|
|
|
|
2016-01-21 04:58:56 +08:00
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
|
|
char IRTranslator::ID = 0;
|
2017-06-27 06:44:03 +08:00
|
|
|
|
|
2016-08-27 07:49:05 +08:00
|
|
|
|
INITIALIZE_PASS_BEGIN(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI",
|
|
|
|
|
false, false)
|
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
|
|
|
|
|
INITIALIZE_PASS_END(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI",
|
2016-07-26 11:29:18 +08:00
|
|
|
|
false, false)
|
2016-01-21 04:58:56 +08:00
|
|
|
|
|
2017-02-24 05:05:42 +08:00
|
|
|
|
static void reportTranslationError(MachineFunction &MF,
|
|
|
|
|
const TargetPassConfig &TPC,
|
|
|
|
|
OptimizationRemarkEmitter &ORE,
|
|
|
|
|
OptimizationRemarkMissed &R) {
|
|
|
|
|
MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
|
|
|
|
|
|
|
|
|
|
// Print the function name explicitly if we don't have a debug location (which
|
|
|
|
|
// makes the diagnostic less useful) or if we're going to emit a raw error.
|
|
|
|
|
if (!R.getLocation().isValid() || TPC.isGlobalISelAbortEnabled())
|
|
|
|
|
R << (" (in function: " + MF.getName() + ")").str();
|
|
|
|
|
|
|
|
|
|
if (TPC.isGlobalISelAbortEnabled())
|
|
|
|
|
report_fatal_error(R.getMsg());
|
|
|
|
|
else
|
|
|
|
|
ORE.emit(R);
|
2016-11-08 09:12:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-27 06:44:03 +08:00
|
|
|
|
IRTranslator::IRTranslator() : MachineFunctionPass(ID) {
|
2016-03-08 09:38:55 +08:00
|
|
|
|
initializeIRTranslatorPass(*PassRegistry::getPassRegistry());
|
2016-02-12 01:53:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-27 07:49:05 +08:00
|
|
|
|
void IRTranslator::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
|
AU.addRequired<TargetPassConfig>();
|
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-12 01:27:54 +08:00
|
|
|
|
unsigned IRTranslator::getOrCreateVReg(const Value &Val) {
|
|
|
|
|
unsigned &ValReg = ValToVReg[&Val];
|
2017-01-26 04:58:22 +08:00
|
|
|
|
|
|
|
|
|
if (ValReg)
|
|
|
|
|
return ValReg;
|
|
|
|
|
|
|
|
|
|
// Fill ValRegsSequence with the sequence of registers
|
|
|
|
|
// we need to concat together to produce the value.
|
|
|
|
|
assert(Val.getType()->isSized() &&
|
|
|
|
|
"Don't know how to create an empty vreg");
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
unsigned VReg =
|
|
|
|
|
MRI->createGenericVirtualRegister(getLLTForType(*Val.getType(), *DL));
|
2017-01-26 04:58:22 +08:00
|
|
|
|
ValReg = VReg;
|
|
|
|
|
|
|
|
|
|
if (auto CV = dyn_cast<Constant>(&Val)) {
|
|
|
|
|
bool Success = translate(*CV, VReg);
|
|
|
|
|
if (!Success) {
|
2017-02-24 05:05:42 +08:00
|
|
|
|
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
|
2017-12-16 06:22:58 +08:00
|
|
|
|
MF->getFunction().getSubprogram(),
|
|
|
|
|
&MF->getFunction().getEntryBlock());
|
2017-02-24 05:05:42 +08:00
|
|
|
|
R << "unable to translate constant: " << ore::NV("Type", Val.getType());
|
|
|
|
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
|
|
|
|
return VReg;
|
2016-08-10 05:28:04 +08:00
|
|
|
|
}
|
2016-02-12 01:51:31 +08:00
|
|
|
|
}
|
2017-01-21 07:25:17 +08:00
|
|
|
|
|
2017-01-26 04:58:22 +08:00
|
|
|
|
return VReg;
|
2016-02-12 01:51:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-01 02:30:59 +08:00
|
|
|
|
int IRTranslator::getOrCreateFrameIndex(const AllocaInst &AI) {
|
|
|
|
|
if (FrameIndices.find(&AI) != FrameIndices.end())
|
|
|
|
|
return FrameIndices[&AI];
|
|
|
|
|
|
|
|
|
|
unsigned ElementSize = DL->getTypeStoreSize(AI.getAllocatedType());
|
|
|
|
|
unsigned Size =
|
|
|
|
|
ElementSize * cast<ConstantInt>(AI.getArraySize())->getZExtValue();
|
|
|
|
|
|
|
|
|
|
// Always allocate at least one byte.
|
|
|
|
|
Size = std::max(Size, 1u);
|
|
|
|
|
|
|
|
|
|
unsigned Alignment = AI.getAlignment();
|
|
|
|
|
if (!Alignment)
|
|
|
|
|
Alignment = DL->getABITypeAlignment(AI.getAllocatedType());
|
|
|
|
|
|
|
|
|
|
int &FI = FrameIndices[&AI];
|
2016-12-08 05:17:47 +08:00
|
|
|
|
FI = MF->getFrameInfo().CreateStackObject(Size, Alignment, false, &AI);
|
2016-11-01 02:30:59 +08:00
|
|
|
|
return FI;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
|
unsigned IRTranslator::getMemOpAlignment(const Instruction &I) {
|
|
|
|
|
unsigned Alignment = 0;
|
|
|
|
|
Type *ValTy = nullptr;
|
|
|
|
|
if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
|
|
|
|
|
Alignment = SI->getAlignment();
|
|
|
|
|
ValTy = SI->getValueOperand()->getType();
|
|
|
|
|
} else if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
|
|
|
|
|
Alignment = LI->getAlignment();
|
|
|
|
|
ValTy = LI->getType();
|
2017-02-24 05:05:42 +08:00
|
|
|
|
} else {
|
|
|
|
|
OptimizationRemarkMissed R("gisel-irtranslator", "", &I);
|
|
|
|
|
R << "unable to translate memop: " << ore::NV("Opcode", &I);
|
|
|
|
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
2016-08-27 07:49:05 +08:00
|
|
|
|
return 1;
|
2017-02-24 05:05:42 +08:00
|
|
|
|
}
|
2016-07-27 04:23:26 +08:00
|
|
|
|
|
|
|
|
|
return Alignment ? Alignment : DL->getABITypeAlignment(ValTy);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &IRTranslator::getMBB(const BasicBlock &BB) {
|
2016-03-12 01:27:43 +08:00
|
|
|
|
MachineBasicBlock *&MBB = BBToMBB[&BB];
|
2017-03-16 02:22:33 +08:00
|
|
|
|
assert(MBB && "BasicBlock was not encountered before");
|
2016-02-12 01:51:31 +08:00
|
|
|
|
return *MBB;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 06:13:50 +08:00
|
|
|
|
void IRTranslator::addMachineCFGPred(CFGEdge Edge, MachineBasicBlock *NewPred) {
|
|
|
|
|
assert(NewPred && "new predecessor must be a real MachineBasicBlock");
|
|
|
|
|
MachinePreds[Edge].push_back(NewPred);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-07-30 02:11:21 +08:00
|
|
|
|
// FIXME: handle signed/unsigned wrapping flags.
|
|
|
|
|
|
2016-02-11 06:59:27 +08:00
|
|
|
|
// Get or create a virtual register for each value.
|
|
|
|
|
// Unless the value is a Constant => loadimm cst?
|
|
|
|
|
// or inline constant each time?
|
|
|
|
|
// Creation of a virtual register needs to have a size.
|
2016-08-11 07:02:41 +08:00
|
|
|
|
unsigned Op0 = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Op1 = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildInstr(Opcode).addDef(Res).addUse(Op0).addUse(Op1);
|
2016-02-12 01:51:31 +08:00
|
|
|
|
return true;
|
2016-01-21 04:58:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-08 02:03:28 +08:00
|
|
|
|
bool IRTranslator::translateFSub(const User &U, MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
// -0.0 - X --> G_FNEG
|
|
|
|
|
if (isa<Constant>(U.getOperand(0)) &&
|
|
|
|
|
U.getOperand(0) == ConstantFP::getZeroValueForNegation(U.getType())) {
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FNEG)
|
|
|
|
|
.addDef(getOrCreateVReg(U))
|
|
|
|
|
.addUse(getOrCreateVReg(*U.getOperand(1)));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateCompare(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-08-20 04:48:16 +08:00
|
|
|
|
const CmpInst *CI = dyn_cast<CmpInst>(&U);
|
|
|
|
|
unsigned Op0 = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Op1 = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
|
|
|
|
CmpInst::Predicate Pred =
|
|
|
|
|
CI ? CI->getPredicate() : static_cast<CmpInst::Predicate>(
|
|
|
|
|
cast<ConstantExpr>(U).getPredicate());
|
|
|
|
|
if (CmpInst::isIntPredicate(Pred))
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildICmp(Pred, Res, Op0, Op1);
|
2017-03-09 02:49:54 +08:00
|
|
|
|
else if (Pred == CmpInst::FCMP_FALSE)
|
2017-03-16 03:21:11 +08:00
|
|
|
|
MIRBuilder.buildCopy(
|
|
|
|
|
Res, getOrCreateVReg(*Constant::getNullValue(CI->getType())));
|
|
|
|
|
else if (Pred == CmpInst::FCMP_TRUE)
|
|
|
|
|
MIRBuilder.buildCopy(
|
|
|
|
|
Res, getOrCreateVReg(*Constant::getAllOnesValue(CI->getType())));
|
2016-08-20 04:48:16 +08:00
|
|
|
|
else
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildFCmp(Pred, Res, Op0, Op1);
|
2016-08-20 04:48:16 +08:00
|
|
|
|
|
2016-08-18 04:25:25 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateRet(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const ReturnInst &RI = cast<ReturnInst>(U);
|
2016-07-30 02:11:21 +08:00
|
|
|
|
const Value *Ret = RI.getReturnValue();
|
2017-12-01 04:06:02 +08:00
|
|
|
|
if (Ret && DL->getTypeStoreSize(Ret->getType()) == 0)
|
|
|
|
|
Ret = nullptr;
|
2016-02-12 02:53:28 +08:00
|
|
|
|
// The target may mess up with the insertion point, but
|
|
|
|
|
// this is not important as a return is the last instruction
|
|
|
|
|
// of the block anyway.
|
2016-04-15 01:23:33 +08:00
|
|
|
|
return CLI->lowerReturn(MIRBuilder, Ret, !Ret ? 0 : getOrCreateVReg(*Ret));
|
2016-02-12 02:53:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateBr(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const BranchInst &BrInst = cast<BranchInst>(U);
|
2016-07-30 01:58:00 +08:00
|
|
|
|
unsigned Succ = 0;
|
|
|
|
|
if (!BrInst.isUnconditional()) {
|
|
|
|
|
// We want a G_BRCOND to the true BB followed by an unconditional branch.
|
|
|
|
|
unsigned Tst = getOrCreateVReg(*BrInst.getCondition());
|
|
|
|
|
const BasicBlock &TrueTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ++));
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &TrueBB = getMBB(TrueTgt);
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildBrCond(Tst, TrueBB);
|
2016-03-12 01:28:03 +08:00
|
|
|
|
}
|
2016-07-30 01:58:00 +08:00
|
|
|
|
|
|
|
|
|
const BasicBlock &BrTgt = *cast<BasicBlock>(BrInst.getSuccessor(Succ));
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &TgtBB = getMBB(BrTgt);
|
2017-03-22 07:42:50 +08:00
|
|
|
|
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
|
|
|
|
|
|
|
|
|
|
// If the unconditional target is the layout successor, fallthrough.
|
|
|
|
|
if (!CurBB.isLayoutSuccessor(&TgtBB))
|
|
|
|
|
MIRBuilder.buildBr(TgtBB);
|
2016-07-30 01:58:00 +08:00
|
|
|
|
|
2016-03-12 01:28:03 +08:00
|
|
|
|
// Link successors.
|
|
|
|
|
for (const BasicBlock *Succ : BrInst.successors())
|
2017-03-16 02:22:33 +08:00
|
|
|
|
CurBB.addSuccessor(&getMBB(*Succ));
|
2016-03-12 01:28:03 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 19:28:51 +08:00
|
|
|
|
bool IRTranslator::translateSwitch(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
// For now, just translate as a chain of conditional branches.
|
|
|
|
|
// FIXME: could we share most of the logic/code in
|
|
|
|
|
// SelectionDAGBuilder::visitSwitch between SelectionDAG and GlobalISel?
|
|
|
|
|
// At first sight, it seems most of the logic in there is independent of
|
|
|
|
|
// SelectionDAG-specifics and a lot of work went in to optimize switch
|
|
|
|
|
// lowering in there.
|
|
|
|
|
|
|
|
|
|
const SwitchInst &SwInst = cast<SwitchInst>(U);
|
|
|
|
|
const unsigned SwCondValue = getOrCreateVReg(*SwInst.getCondition());
|
2017-01-18 06:13:50 +08:00
|
|
|
|
const BasicBlock *OrigBB = SwInst.getParent();
|
2017-01-05 19:28:51 +08:00
|
|
|
|
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
LLT LLTi1 = getLLTForType(*Type::getInt1Ty(U.getContext()), *DL);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
for (auto &CaseIt : SwInst.cases()) {
|
|
|
|
|
const unsigned CaseValueReg = getOrCreateVReg(*CaseIt.getCaseValue());
|
|
|
|
|
const unsigned Tst = MRI->createGenericVirtualRegister(LLTi1);
|
|
|
|
|
MIRBuilder.buildICmp(CmpInst::ICMP_EQ, Tst, CaseValueReg, SwCondValue);
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MachineBasicBlock &CurMBB = MIRBuilder.getMBB();
|
|
|
|
|
const BasicBlock *TrueBB = CaseIt.getCaseSuccessor();
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &TrueMBB = getMBB(*TrueBB);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MIRBuilder.buildBrCond(Tst, TrueMBB);
|
|
|
|
|
CurMBB.addSuccessor(&TrueMBB);
|
|
|
|
|
addMachineCFGPred({OrigBB, TrueBB}, &CurMBB);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MachineBasicBlock *FalseMBB =
|
2017-01-05 19:28:51 +08:00
|
|
|
|
MF->CreateMachineBasicBlock(SwInst.getParent());
|
2017-03-16 02:22:37 +08:00
|
|
|
|
// Insert the comparison blocks one after the other.
|
|
|
|
|
MF->insert(std::next(CurMBB.getIterator()), FalseMBB);
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MIRBuilder.buildBr(*FalseMBB);
|
|
|
|
|
CurMBB.addSuccessor(FalseMBB);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MIRBuilder.setMBB(*FalseMBB);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
}
|
|
|
|
|
// handle default case
|
2017-01-18 06:13:50 +08:00
|
|
|
|
const BasicBlock *DefaultBB = SwInst.getDefaultDest();
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &DefaultMBB = getMBB(*DefaultBB);
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MIRBuilder.buildBr(DefaultMBB);
|
|
|
|
|
MachineBasicBlock &CurMBB = MIRBuilder.getMBB();
|
|
|
|
|
CurMBB.addSuccessor(&DefaultMBB);
|
|
|
|
|
addMachineCFGPred({OrigBB, DefaultBB}, &CurMBB);
|
2017-01-05 19:28:51 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-30 17:13:18 +08:00
|
|
|
|
bool IRTranslator::translateIndirectBr(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
const IndirectBrInst &BrInst = cast<IndirectBrInst>(U);
|
|
|
|
|
|
|
|
|
|
const unsigned Tgt = getOrCreateVReg(*BrInst.getAddress());
|
|
|
|
|
MIRBuilder.buildBrIndirect(Tgt);
|
|
|
|
|
|
|
|
|
|
// Link successors.
|
|
|
|
|
MachineBasicBlock &CurBB = MIRBuilder.getMBB();
|
|
|
|
|
for (const BasicBlock *Succ : BrInst.successors())
|
2017-03-16 02:22:33 +08:00
|
|
|
|
CurBB.addSuccessor(&getMBB(*Succ));
|
2017-01-30 17:13:18 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const LoadInst &LI = cast<LoadInst>(U);
|
2016-08-27 07:49:05 +08:00
|
|
|
|
|
2016-10-19 23:55:06 +08:00
|
|
|
|
auto Flags = LI.isVolatile() ? MachineMemOperand::MOVolatile
|
|
|
|
|
: MachineMemOperand::MONone;
|
|
|
|
|
Flags |= MachineMemOperand::MOLoad;
|
2016-07-27 04:23:26 +08:00
|
|
|
|
|
2017-12-01 04:06:02 +08:00
|
|
|
|
if (DL->getTypeStoreSize(LI.getType()) == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(LI);
|
|
|
|
|
unsigned Addr = getOrCreateVReg(*LI.getPointerOperand());
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
|
MIRBuilder.buildLoad(
|
2016-09-09 19:46:34 +08:00
|
|
|
|
Res, Addr,
|
2016-12-08 05:17:47 +08:00
|
|
|
|
*MF->getMachineMemOperand(MachinePointerInfo(LI.getPointerOperand()),
|
|
|
|
|
Flags, DL->getTypeStoreSize(LI.getType()),
|
2017-02-14 06:14:16 +08:00
|
|
|
|
getMemOpAlignment(LI), AAMDNodes(), nullptr,
|
2017-07-12 06:23:00 +08:00
|
|
|
|
LI.getSyncScopeID(), LI.getOrdering()));
|
2016-07-27 04:23:26 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const StoreInst &SI = cast<StoreInst>(U);
|
2016-10-19 23:55:06 +08:00
|
|
|
|
auto Flags = SI.isVolatile() ? MachineMemOperand::MOVolatile
|
|
|
|
|
: MachineMemOperand::MONone;
|
|
|
|
|
Flags |= MachineMemOperand::MOStore;
|
2016-07-27 04:23:26 +08:00
|
|
|
|
|
2017-12-01 04:06:02 +08:00
|
|
|
|
if (DL->getTypeStoreSize(SI.getValueOperand()->getType()) == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
2016-07-27 04:23:26 +08:00
|
|
|
|
unsigned Val = getOrCreateVReg(*SI.getValueOperand());
|
|
|
|
|
unsigned Addr = getOrCreateVReg(*SI.getPointerOperand());
|
|
|
|
|
|
|
|
|
|
MIRBuilder.buildStore(
|
2016-12-08 05:17:47 +08:00
|
|
|
|
Val, Addr,
|
|
|
|
|
*MF->getMachineMemOperand(
|
|
|
|
|
MachinePointerInfo(SI.getPointerOperand()), Flags,
|
|
|
|
|
DL->getTypeStoreSize(SI.getValueOperand()->getType()),
|
2017-07-12 06:23:00 +08:00
|
|
|
|
getMemOpAlignment(SI), AAMDNodes(), nullptr, SI.getSyncScopeID(),
|
2017-02-14 06:14:16 +08:00
|
|
|
|
SI.getOrdering()));
|
2016-07-27 04:23:26 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateExtractValue(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-08-20 04:09:03 +08:00
|
|
|
|
const Value *Src = U.getOperand(0);
|
|
|
|
|
Type *Int32Ty = Type::getInt32Ty(U.getContext());
|
2016-08-20 01:47:05 +08:00
|
|
|
|
SmallVector<Value *, 1> Indices;
|
|
|
|
|
|
2017-05-19 17:47:02 +08:00
|
|
|
|
// If Src is a single element ConstantStruct, translate extractvalue
|
|
|
|
|
// to that element to avoid inserting a cast instruction.
|
|
|
|
|
if (auto CS = dyn_cast<ConstantStruct>(Src))
|
|
|
|
|
if (CS->getNumOperands() == 1) {
|
|
|
|
|
unsigned Res = getOrCreateVReg(*CS->getOperand(0));
|
|
|
|
|
ValToVReg[&U] = Res;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-20 01:47:05 +08:00
|
|
|
|
// getIndexedOffsetInType is designed for GEPs, so the first index is the
|
|
|
|
|
// usual array element rather than looking into the actual aggregate.
|
|
|
|
|
Indices.push_back(ConstantInt::get(Int32Ty, 0));
|
2016-08-20 04:09:03 +08:00
|
|
|
|
|
|
|
|
|
if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&U)) {
|
|
|
|
|
for (auto Idx : EVI->indices())
|
|
|
|
|
Indices.push_back(ConstantInt::get(Int32Ty, Idx));
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned i = 1; i < U.getNumOperands(); ++i)
|
|
|
|
|
Indices.push_back(U.getOperand(i));
|
|
|
|
|
}
|
2016-08-20 01:47:05 +08:00
|
|
|
|
|
|
|
|
|
uint64_t Offset = 8 * DL->getIndexedOffsetInType(Src->getType(), Indices);
|
|
|
|
|
|
2016-08-20 04:09:03 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
2017-03-07 07:50:28 +08:00
|
|
|
|
MIRBuilder.buildExtract(Res, getOrCreateVReg(*Src), Offset);
|
2016-08-20 01:47:05 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateInsertValue(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-08-20 04:09:03 +08:00
|
|
|
|
const Value *Src = U.getOperand(0);
|
|
|
|
|
Type *Int32Ty = Type::getInt32Ty(U.getContext());
|
2016-08-20 04:08:55 +08:00
|
|
|
|
SmallVector<Value *, 1> Indices;
|
|
|
|
|
|
|
|
|
|
// getIndexedOffsetInType is designed for GEPs, so the first index is the
|
|
|
|
|
// usual array element rather than looking into the actual aggregate.
|
|
|
|
|
Indices.push_back(ConstantInt::get(Int32Ty, 0));
|
2016-08-20 04:09:03 +08:00
|
|
|
|
|
|
|
|
|
if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(&U)) {
|
|
|
|
|
for (auto Idx : IVI->indices())
|
|
|
|
|
Indices.push_back(ConstantInt::get(Int32Ty, Idx));
|
|
|
|
|
} else {
|
|
|
|
|
for (unsigned i = 2; i < U.getNumOperands(); ++i)
|
|
|
|
|
Indices.push_back(U.getOperand(i));
|
|
|
|
|
}
|
2016-08-20 04:08:55 +08:00
|
|
|
|
|
|
|
|
|
uint64_t Offset = 8 * DL->getIndexedOffsetInType(Src->getType(), Indices);
|
|
|
|
|
|
2016-08-20 04:09:03 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
2017-04-19 14:38:37 +08:00
|
|
|
|
unsigned Inserted = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
MIRBuilder.buildInsert(Res, getOrCreateVReg(*Src), Inserted, Offset);
|
2016-08-20 04:08:55 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateSelect(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2017-04-19 14:38:37 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
|
|
|
|
unsigned Tst = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Op0 = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
unsigned Op1 = getOrCreateVReg(*U.getOperand(2));
|
|
|
|
|
MIRBuilder.buildSelect(Res, Tst, Op0, Op1);
|
2016-08-20 04:09:07 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateBitCast(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2017-03-08 04:53:06 +08:00
|
|
|
|
// If we're bitcasting to the source type, we can reuse the source vreg.
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
if (getLLTForType(*U.getOperand(0)->getType(), *DL) ==
|
|
|
|
|
getLLTForType(*U.getType(), *DL)) {
|
2017-03-08 04:53:06 +08:00
|
|
|
|
// Get the source vreg now, to avoid invalidating ValToVReg.
|
|
|
|
|
unsigned SrcReg = getOrCreateVReg(*U.getOperand(0));
|
2016-08-11 07:02:41 +08:00
|
|
|
|
unsigned &Reg = ValToVReg[&U];
|
2017-03-08 04:53:06 +08:00
|
|
|
|
// If we already assigned a vreg for this bitcast, we can't change that.
|
|
|
|
|
// Emit a copy to satisfy the users we already emitted.
|
2016-08-11 00:51:14 +08:00
|
|
|
|
if (Reg)
|
2017-03-08 04:53:06 +08:00
|
|
|
|
MIRBuilder.buildCopy(Reg, SrcReg);
|
2016-08-11 00:51:14 +08:00
|
|
|
|
else
|
2017-03-08 04:53:06 +08:00
|
|
|
|
Reg = SrcReg;
|
2016-07-26 05:01:29 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-12-08 05:29:15 +08:00
|
|
|
|
return translateCast(TargetOpcode::G_BITCAST, U, MIRBuilder);
|
2016-07-26 05:01:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateCast(unsigned Opcode, const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
unsigned Op = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildInstr(Opcode).addDef(Res).addUse(Op);
|
2016-07-26 05:01:29 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateGetElementPtr(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-09-12 19:20:22 +08:00
|
|
|
|
// FIXME: support vector GEPs.
|
|
|
|
|
if (U.getType()->isVectorTy())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
Value &Op0 = *U.getOperand(0);
|
|
|
|
|
unsigned BaseReg = getOrCreateVReg(Op0);
|
2017-03-16 03:21:11 +08:00
|
|
|
|
Type *PtrIRTy = Op0.getType();
|
|
|
|
|
LLT PtrTy = getLLTForType(*PtrIRTy, *DL);
|
|
|
|
|
Type *OffsetIRTy = DL->getIntPtrType(PtrIRTy);
|
|
|
|
|
LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL);
|
2016-09-12 19:20:22 +08:00
|
|
|
|
|
|
|
|
|
int64_t Offset = 0;
|
|
|
|
|
for (gep_type_iterator GTI = gep_type_begin(&U), E = gep_type_end(&U);
|
|
|
|
|
GTI != E; ++GTI) {
|
|
|
|
|
const Value *Idx = GTI.getOperand();
|
2016-12-02 10:55:30 +08:00
|
|
|
|
if (StructType *StTy = GTI.getStructTypeOrNull()) {
|
2016-09-12 19:20:22 +08:00
|
|
|
|
unsigned Field = cast<Constant>(Idx)->getUniqueInteger().getZExtValue();
|
|
|
|
|
Offset += DL->getStructLayout(StTy)->getElementOffset(Field);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
uint64_t ElementSize = DL->getTypeAllocSize(GTI.getIndexedType());
|
|
|
|
|
|
|
|
|
|
// If this is a scalar constant or a splat vector of constants,
|
|
|
|
|
// handle it quickly.
|
|
|
|
|
if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
|
|
|
|
|
Offset += ElementSize * CI->getSExtValue();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Offset != 0) {
|
|
|
|
|
unsigned NewBaseReg = MRI->createGenericVirtualRegister(PtrTy);
|
2017-03-16 03:21:11 +08:00
|
|
|
|
unsigned OffsetReg =
|
|
|
|
|
getOrCreateVReg(*ConstantInt::get(OffsetIRTy, Offset));
|
2016-09-12 19:20:22 +08:00
|
|
|
|
MIRBuilder.buildGEP(NewBaseReg, BaseReg, OffsetReg);
|
|
|
|
|
|
|
|
|
|
BaseReg = NewBaseReg;
|
|
|
|
|
Offset = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned IdxReg = getOrCreateVReg(*Idx);
|
|
|
|
|
if (MRI->getType(IdxReg) != OffsetTy) {
|
|
|
|
|
unsigned NewIdxReg = MRI->createGenericVirtualRegister(OffsetTy);
|
|
|
|
|
MIRBuilder.buildSExtOrTrunc(NewIdxReg, IdxReg);
|
|
|
|
|
IdxReg = NewIdxReg;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-05 10:56:28 +08:00
|
|
|
|
// N = N + Idx * ElementSize;
|
|
|
|
|
// Avoid doing it for ElementSize of 1.
|
|
|
|
|
unsigned GepOffsetReg;
|
|
|
|
|
if (ElementSize != 1) {
|
|
|
|
|
unsigned ElementSizeReg =
|
|
|
|
|
getOrCreateVReg(*ConstantInt::get(OffsetIRTy, ElementSize));
|
|
|
|
|
|
|
|
|
|
GepOffsetReg = MRI->createGenericVirtualRegister(OffsetTy);
|
|
|
|
|
MIRBuilder.buildMul(GepOffsetReg, ElementSizeReg, IdxReg);
|
|
|
|
|
} else
|
|
|
|
|
GepOffsetReg = IdxReg;
|
2016-09-12 19:20:22 +08:00
|
|
|
|
|
|
|
|
|
unsigned NewBaseReg = MRI->createGenericVirtualRegister(PtrTy);
|
2018-01-05 10:56:28 +08:00
|
|
|
|
MIRBuilder.buildGEP(NewBaseReg, BaseReg, GepOffsetReg);
|
2016-09-12 19:20:22 +08:00
|
|
|
|
BaseReg = NewBaseReg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Offset != 0) {
|
2017-03-16 03:21:11 +08:00
|
|
|
|
unsigned OffsetReg = getOrCreateVReg(*ConstantInt::get(OffsetIRTy, Offset));
|
2016-09-12 19:20:22 +08:00
|
|
|
|
MIRBuilder.buildGEP(getOrCreateVReg(U), BaseReg, OffsetReg);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MIRBuilder.buildCopy(getOrCreateVReg(U), BaseReg);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 03:33:07 +08:00
|
|
|
|
bool IRTranslator::translateMemfunc(const CallInst &CI,
|
|
|
|
|
MachineIRBuilder &MIRBuilder,
|
|
|
|
|
unsigned ID) {
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
LLT SizeTy = getLLTForType(*CI.getArgOperand(2)->getType(), *DL);
|
2017-01-31 03:33:07 +08:00
|
|
|
|
Type *DstTy = CI.getArgOperand(0)->getType();
|
|
|
|
|
if (cast<PointerType>(DstTy)->getAddressSpace() != 0 ||
|
2016-10-19 04:03:45 +08:00
|
|
|
|
SizeTy.getSizeInBits() != DL->getPointerSizeInBits(0))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
SmallVector<CallLowering::ArgInfo, 8> Args;
|
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
|
const auto &Arg = CI.getArgOperand(i);
|
|
|
|
|
Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType());
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-31 03:33:07 +08:00
|
|
|
|
const char *Callee;
|
|
|
|
|
switch (ID) {
|
|
|
|
|
case Intrinsic::memmove:
|
|
|
|
|
case Intrinsic::memcpy: {
|
|
|
|
|
Type *SrcTy = CI.getArgOperand(1)->getType();
|
|
|
|
|
if(cast<PointerType>(SrcTy)->getAddressSpace() != 0)
|
|
|
|
|
return false;
|
|
|
|
|
Callee = ID == Intrinsic::memcpy ? "memcpy" : "memmove";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Intrinsic::memset:
|
|
|
|
|
Callee = "memset";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-10-19 04:03:45 +08:00
|
|
|
|
|
2017-03-20 22:40:18 +08:00
|
|
|
|
return CLI->lowerCall(MIRBuilder, CI.getCallingConv(),
|
|
|
|
|
MachineOperand::CreateES(Callee),
|
2016-10-19 04:03:45 +08:00
|
|
|
|
CallLowering::ArgInfo(0, CI.getType()), Args);
|
|
|
|
|
}
|
2016-09-12 19:20:22 +08:00
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
void IRTranslator::getStackGuard(unsigned DstReg,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2017-01-28 05:31:24 +08:00
|
|
|
|
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
|
|
|
|
|
MRI->setRegClass(DstReg, TRI->getPointerRegClass(*MF));
|
2016-11-01 02:30:59 +08:00
|
|
|
|
auto MIB = MIRBuilder.buildInstr(TargetOpcode::LOAD_STACK_GUARD);
|
|
|
|
|
MIB.addDef(DstReg);
|
|
|
|
|
|
2016-12-08 05:17:47 +08:00
|
|
|
|
auto &TLI = *MF->getSubtarget().getTargetLowering();
|
2017-12-16 06:22:58 +08:00
|
|
|
|
Value *Global = TLI.getSDagStackGuard(*MF->getFunction().getParent());
|
2016-11-01 02:30:59 +08:00
|
|
|
|
if (!Global)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MachinePointerInfo MPInfo(Global);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
MachineInstr::mmo_iterator MemRefs = MF->allocateMemRefsArray(1);
|
2016-11-01 02:30:59 +08:00
|
|
|
|
auto Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant |
|
|
|
|
|
MachineMemOperand::MODereferenceable;
|
|
|
|
|
*MemRefs =
|
2016-12-08 05:17:47 +08:00
|
|
|
|
MF->getMachineMemOperand(MPInfo, Flags, DL->getPointerSizeInBits() / 8,
|
2017-11-15 14:17:32 +08:00
|
|
|
|
DL->getPointerABIAlignment(0));
|
2016-11-01 02:30:59 +08:00
|
|
|
|
MIB.setMemRefs(MemRefs, MemRefs + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-09 06:44:00 +08:00
|
|
|
|
bool IRTranslator::translateOverflowIntrinsic(const CallInst &CI, unsigned Op,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
LLT Ty = getLLTForType(*CI.getOperand(0)->getType(), *DL);
|
2016-12-09 06:44:00 +08:00
|
|
|
|
LLT s1 = LLT::scalar(1);
|
|
|
|
|
unsigned Width = Ty.getSizeInBits();
|
|
|
|
|
unsigned Res = MRI->createGenericVirtualRegister(Ty);
|
|
|
|
|
unsigned Overflow = MRI->createGenericVirtualRegister(s1);
|
|
|
|
|
auto MIB = MIRBuilder.buildInstr(Op)
|
|
|
|
|
.addDef(Res)
|
|
|
|
|
.addDef(Overflow)
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getOperand(0)))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getOperand(1)));
|
|
|
|
|
|
|
|
|
|
if (Op == TargetOpcode::G_UADDE || Op == TargetOpcode::G_USUBE) {
|
2017-03-16 03:21:11 +08:00
|
|
|
|
unsigned Zero = getOrCreateVReg(
|
|
|
|
|
*Constant::getNullValue(Type::getInt1Ty(CI.getContext())));
|
2016-12-09 06:44:00 +08:00
|
|
|
|
MIB.addUse(Zero);
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-24 00:15:37 +08:00
|
|
|
|
MIRBuilder.buildSequence(getOrCreateVReg(CI), {Res, Overflow}, {0, Width});
|
2016-12-09 06:44:00 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-08-20 01:17:06 +08:00
|
|
|
|
switch (ID) {
|
2016-12-09 06:44:00 +08:00
|
|
|
|
default:
|
|
|
|
|
break;
|
2017-02-11 03:10:38 +08:00
|
|
|
|
case Intrinsic::lifetime_start:
|
|
|
|
|
case Intrinsic::lifetime_end:
|
|
|
|
|
// Stack coloring is not enabled in O0 (which we care about now) so we can
|
|
|
|
|
// drop these. Make sure someone notices when we start compiling at higher
|
|
|
|
|
// opts though.
|
|
|
|
|
if (MF->getTarget().getOptLevel() != CodeGenOpt::None)
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
2017-01-27 07:39:14 +08:00
|
|
|
|
case Intrinsic::dbg_declare: {
|
|
|
|
|
const DbgDeclareInst &DI = cast<DbgDeclareInst>(CI);
|
|
|
|
|
assert(DI.getVariable() && "Missing variable");
|
|
|
|
|
|
|
|
|
|
const Value *Address = DI.getAddress();
|
|
|
|
|
if (!Address || isa<UndefValue>(Address)) {
|
|
|
|
|
DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(DI.getVariable()->isValidLocationForIntrinsic(
|
|
|
|
|
MIRBuilder.getDebugLoc()) &&
|
|
|
|
|
"Expected inlined-at fields to agree");
|
2017-03-10 05:12:06 +08:00
|
|
|
|
auto AI = dyn_cast<AllocaInst>(Address);
|
|
|
|
|
if (AI && AI->isStaticAlloca()) {
|
|
|
|
|
// Static allocas are tracked at the MF level, no need for DBG_VALUE
|
|
|
|
|
// instructions (in fact, they get ignored if they *do* exist).
|
|
|
|
|
MF->setVariableDbgInfo(DI.getVariable(), DI.getExpression(),
|
|
|
|
|
getOrCreateFrameIndex(*AI), DI.getDebugLoc());
|
2017-01-27 07:39:14 +08:00
|
|
|
|
} else
|
2017-03-10 05:12:06 +08:00
|
|
|
|
MIRBuilder.buildDirectDbgValue(getOrCreateVReg(*Address),
|
|
|
|
|
DI.getVariable(), DI.getExpression());
|
2016-12-09 06:44:13 +08:00
|
|
|
|
return true;
|
2017-01-27 07:39:14 +08:00
|
|
|
|
}
|
2017-02-08 04:08:59 +08:00
|
|
|
|
case Intrinsic::vaend:
|
|
|
|
|
// No target I know of cares about va_end. Certainly no in-tree target
|
|
|
|
|
// does. Simplest intrinsic ever!
|
|
|
|
|
return true;
|
2017-02-09 01:57:20 +08:00
|
|
|
|
case Intrinsic::vastart: {
|
|
|
|
|
auto &TLI = *MF->getSubtarget().getTargetLowering();
|
|
|
|
|
Value *Ptr = CI.getArgOperand(0);
|
|
|
|
|
unsigned ListSize = TLI.getVaListSizeInBits(*DL) / 8;
|
|
|
|
|
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_VASTART)
|
|
|
|
|
.addUse(getOrCreateVReg(*Ptr))
|
|
|
|
|
.addMemOperand(MF->getMachineMemOperand(
|
|
|
|
|
MachinePointerInfo(Ptr), MachineMemOperand::MOStore, ListSize, 0));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-01-27 07:39:14 +08:00
|
|
|
|
case Intrinsic::dbg_value: {
|
|
|
|
|
// This form of DBG_VALUE is target-independent.
|
|
|
|
|
const DbgValueInst &DI = cast<DbgValueInst>(CI);
|
|
|
|
|
const Value *V = DI.getValue();
|
|
|
|
|
assert(DI.getVariable()->isValidLocationForIntrinsic(
|
|
|
|
|
MIRBuilder.getDebugLoc()) &&
|
|
|
|
|
"Expected inlined-at fields to agree");
|
|
|
|
|
if (!V) {
|
|
|
|
|
// Currently the optimizer can produce this; insert an undef to
|
|
|
|
|
// help debugging. Probably the optimizer should not do this.
|
2017-07-29 06:46:20 +08:00
|
|
|
|
MIRBuilder.buildIndirectDbgValue(0, DI.getVariable(), DI.getExpression());
|
2017-01-27 07:39:14 +08:00
|
|
|
|
} else if (const auto *CI = dyn_cast<Constant>(V)) {
|
2017-07-29 06:46:20 +08:00
|
|
|
|
MIRBuilder.buildConstDbgValue(*CI, DI.getVariable(), DI.getExpression());
|
2017-01-27 07:39:14 +08:00
|
|
|
|
} else {
|
|
|
|
|
unsigned Reg = getOrCreateVReg(*V);
|
|
|
|
|
// FIXME: This does not handle register-indirect values at offset 0. The
|
|
|
|
|
// direct/indirect thing shouldn't really be handled by something as
|
|
|
|
|
// implicit as reg+noreg vs reg+imm in the first palce, but it seems
|
|
|
|
|
// pretty baked in right now.
|
2017-07-29 04:21:02 +08:00
|
|
|
|
MIRBuilder.buildDirectDbgValue(Reg, DI.getVariable(), DI.getExpression());
|
2017-01-27 07:39:14 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-12-09 06:44:00 +08:00
|
|
|
|
case Intrinsic::uadd_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDE, MIRBuilder);
|
|
|
|
|
case Intrinsic::sadd_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_SADDO, MIRBuilder);
|
|
|
|
|
case Intrinsic::usub_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_USUBE, MIRBuilder);
|
|
|
|
|
case Intrinsic::ssub_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_SSUBO, MIRBuilder);
|
|
|
|
|
case Intrinsic::umul_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_UMULO, MIRBuilder);
|
|
|
|
|
case Intrinsic::smul_with_overflow:
|
|
|
|
|
return translateOverflowIntrinsic(CI, TargetOpcode::G_SMULO, MIRBuilder);
|
2017-02-09 07:23:32 +08:00
|
|
|
|
case Intrinsic::pow:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FPOW)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(1)));
|
|
|
|
|
return true;
|
2017-06-28 06:19:32 +08:00
|
|
|
|
case Intrinsic::exp:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FEXP)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
|
|
|
|
return true;
|
|
|
|
|
case Intrinsic::exp2:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FEXP2)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
|
|
|
|
return true;
|
2017-06-30 07:43:44 +08:00
|
|
|
|
case Intrinsic::log:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FLOG)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
|
|
|
|
return true;
|
|
|
|
|
case Intrinsic::log2:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FLOG2)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)));
|
|
|
|
|
return true;
|
2017-06-21 03:25:23 +08:00
|
|
|
|
case Intrinsic::fma:
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FMA)
|
|
|
|
|
.addDef(getOrCreateVReg(CI))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(0)))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(1)))
|
|
|
|
|
.addUse(getOrCreateVReg(*CI.getArgOperand(2)));
|
|
|
|
|
return true;
|
2018-02-13 08:47:46 +08:00
|
|
|
|
case Intrinsic::fmuladd: {
|
|
|
|
|
const TargetMachine &TM = MF->getTarget();
|
|
|
|
|
const TargetLowering &TLI = *MF->getSubtarget().getTargetLowering();
|
|
|
|
|
unsigned Dst = getOrCreateVReg(CI);
|
|
|
|
|
unsigned Op0 = getOrCreateVReg(*CI.getArgOperand(0));
|
|
|
|
|
unsigned Op1 = getOrCreateVReg(*CI.getArgOperand(1));
|
|
|
|
|
unsigned Op2 = getOrCreateVReg(*CI.getArgOperand(2));
|
|
|
|
|
if (TM.Options.AllowFPOpFusion != FPOpFusion::Strict &&
|
|
|
|
|
TLI.isFMAFasterThanFMulAndFAdd(TLI.getValueType(*DL, CI.getType()))) {
|
|
|
|
|
// TODO: Revisit this to see if we should move this part of the
|
|
|
|
|
// lowering to the combiner.
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FMA, Dst, Op0, Op1, Op2);
|
|
|
|
|
} else {
|
|
|
|
|
LLT Ty = getLLTForType(*CI.getType(), *DL);
|
|
|
|
|
auto FMul = MIRBuilder.buildInstr(TargetOpcode::G_FMUL, Ty, Op0, Op1);
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_FADD, Dst, FMul, Op2);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-10-19 04:03:45 +08:00
|
|
|
|
case Intrinsic::memcpy:
|
2017-01-31 03:33:07 +08:00
|
|
|
|
case Intrinsic::memmove:
|
|
|
|
|
case Intrinsic::memset:
|
|
|
|
|
return translateMemfunc(CI, MIRBuilder, ID);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
case Intrinsic::eh_typeid_for: {
|
|
|
|
|
GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0));
|
|
|
|
|
unsigned Reg = getOrCreateVReg(CI);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
unsigned TypeID = MF->getTypeIDFor(GV);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
MIRBuilder.buildConstant(Reg, TypeID);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-10-19 04:03:51 +08:00
|
|
|
|
case Intrinsic::objectsize: {
|
|
|
|
|
// If we don't know by now, we're never going to know.
|
|
|
|
|
const ConstantInt *Min = cast<ConstantInt>(CI.getArgOperand(1));
|
|
|
|
|
|
|
|
|
|
MIRBuilder.buildConstant(getOrCreateVReg(CI), Min->isZero() ? -1ULL : 0);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-11-01 02:30:59 +08:00
|
|
|
|
case Intrinsic::stackguard:
|
2016-12-08 05:29:15 +08:00
|
|
|
|
getStackGuard(getOrCreateVReg(CI), MIRBuilder);
|
2016-11-01 02:30:59 +08:00
|
|
|
|
return true;
|
|
|
|
|
case Intrinsic::stackprotector: {
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
LLT PtrTy = getLLTForType(*CI.getArgOperand(0)->getType(), *DL);
|
2016-11-01 02:30:59 +08:00
|
|
|
|
unsigned GuardVal = MRI->createGenericVirtualRegister(PtrTy);
|
2016-12-08 05:29:15 +08:00
|
|
|
|
getStackGuard(GuardVal, MIRBuilder);
|
2016-11-01 02:30:59 +08:00
|
|
|
|
|
|
|
|
|
AllocaInst *Slot = cast<AllocaInst>(CI.getArgOperand(1));
|
|
|
|
|
MIRBuilder.buildStore(
|
|
|
|
|
GuardVal, getOrCreateVReg(*Slot),
|
2016-12-08 05:17:47 +08:00
|
|
|
|
*MF->getMachineMemOperand(
|
|
|
|
|
MachinePointerInfo::getFixedStack(*MF,
|
|
|
|
|
getOrCreateFrameIndex(*Slot)),
|
2016-11-01 02:30:59 +08:00
|
|
|
|
MachineMemOperand::MOStore | MachineMemOperand::MOVolatile,
|
|
|
|
|
PtrTy.getSizeInBits() / 8, 8));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2016-08-20 01:17:06 +08:00
|
|
|
|
}
|
2016-12-09 06:44:00 +08:00
|
|
|
|
return false;
|
2016-08-20 01:17:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-10 07:36:26 +08:00
|
|
|
|
bool IRTranslator::translateInlineAsm(const CallInst &CI,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
const InlineAsm &IA = cast<InlineAsm>(*CI.getCalledValue());
|
|
|
|
|
if (!IA.getConstraintString().empty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
unsigned ExtraInfo = 0;
|
|
|
|
|
if (IA.hasSideEffects())
|
|
|
|
|
ExtraInfo |= InlineAsm::Extra_HasSideEffects;
|
|
|
|
|
if (IA.getDialect() == InlineAsm::AD_Intel)
|
|
|
|
|
ExtraInfo |= InlineAsm::Extra_AsmDialect;
|
|
|
|
|
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::INLINEASM)
|
|
|
|
|
.addExternalSymbol(IA.getAsmString().c_str())
|
|
|
|
|
.addImm(ExtraInfo);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const CallInst &CI = cast<CallInst>(U);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
auto TII = MF->getTarget().getIntrinsicInfo();
|
2016-08-11 05:44:01 +08:00
|
|
|
|
const Function *F = CI.getCalledFunction();
|
|
|
|
|
|
2018-01-31 03:50:58 +08:00
|
|
|
|
// FIXME: support Windows dllimport function calls.
|
|
|
|
|
if (F && F->hasDLLImportStorageClass())
|
|
|
|
|
return false;
|
|
|
|
|
|
2017-01-20 07:59:35 +08:00
|
|
|
|
if (CI.isInlineAsm())
|
2017-03-10 07:36:26 +08:00
|
|
|
|
return translateInlineAsm(CI, MIRBuilder);
|
2017-01-20 07:59:35 +08:00
|
|
|
|
|
2018-01-03 02:56:39 +08:00
|
|
|
|
Intrinsic::ID ID = Intrinsic::not_intrinsic;
|
|
|
|
|
if (F && F->isIntrinsic()) {
|
|
|
|
|
ID = F->getIntrinsicID();
|
|
|
|
|
if (TII && ID == Intrinsic::not_intrinsic)
|
|
|
|
|
ID = static_cast<Intrinsic::ID>(TII->getIntrinsicID(F));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!F || !F->isIntrinsic() || ID == Intrinsic::not_intrinsic) {
|
2016-08-11 05:44:01 +08:00
|
|
|
|
unsigned Res = CI.getType()->isVoidTy() ? 0 : getOrCreateVReg(CI);
|
|
|
|
|
SmallVector<unsigned, 8> Args;
|
|
|
|
|
for (auto &Arg: CI.arg_operands())
|
|
|
|
|
Args.push_back(getOrCreateVReg(*Arg));
|
|
|
|
|
|
2017-03-10 06:00:39 +08:00
|
|
|
|
MF->getFrameInfo().setHasCalls(true);
|
2017-03-10 08:25:44 +08:00
|
|
|
|
return CLI->lowerCall(MIRBuilder, &CI, Res, Args, [&]() {
|
2016-08-30 03:07:08 +08:00
|
|
|
|
return getOrCreateVReg(*CI.getCalledValue());
|
|
|
|
|
});
|
2016-08-11 05:44:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(ID != Intrinsic::not_intrinsic && "unknown intrinsic");
|
2016-07-30 06:32:36 +08:00
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
if (translateKnownIntrinsic(CI, ID, MIRBuilder))
|
2016-08-20 01:17:06 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
2016-07-30 06:32:36 +08:00
|
|
|
|
unsigned Res = CI.getType()->isVoidTy() ? 0 : getOrCreateVReg(CI);
|
|
|
|
|
MachineInstrBuilder MIB =
|
2016-09-09 19:46:34 +08:00
|
|
|
|
MIRBuilder.buildIntrinsic(ID, Res, !CI.doesNotAccessMemory());
|
2016-07-30 06:32:36 +08:00
|
|
|
|
|
|
|
|
|
for (auto &Arg : CI.arg_operands()) {
|
2017-03-08 04:53:09 +08:00
|
|
|
|
// Some intrinsics take metadata parameters. Reject them.
|
|
|
|
|
if (isa<MetadataAsValue>(Arg))
|
|
|
|
|
return false;
|
2017-03-22 09:16:39 +08:00
|
|
|
|
MIB.addUse(getOrCreateVReg(*Arg));
|
2016-07-30 06:32:36 +08:00
|
|
|
|
}
|
2017-06-06 06:17:17 +08:00
|
|
|
|
|
|
|
|
|
// Add a MachineMemOperand if it is a target mem intrinsic.
|
|
|
|
|
const TargetLowering &TLI = *MF->getSubtarget().getTargetLowering();
|
|
|
|
|
TargetLowering::IntrinsicInfo Info;
|
|
|
|
|
// TODO: Add a GlobalISel version of getTgtMemIntrinsic.
|
2017-12-15 06:34:10 +08:00
|
|
|
|
if (TLI.getTgtMemIntrinsic(Info, CI, *MF, ID)) {
|
2017-11-28 22:44:32 +08:00
|
|
|
|
uint64_t Size = Info.memVT.getStoreSize();
|
2017-06-06 06:17:17 +08:00
|
|
|
|
MIB.addMemOperand(MF->getMachineMemOperand(MachinePointerInfo(Info.ptrVal),
|
2017-12-15 05:39:51 +08:00
|
|
|
|
Info.flags, Size, Info.align));
|
2017-06-06 06:17:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-07-30 06:32:36 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateInvoke(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-11-10 06:39:54 +08:00
|
|
|
|
const InvokeInst &I = cast<InvokeInst>(U);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
MCContext &Context = MF->getContext();
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
|
|
|
|
const BasicBlock *ReturnBB = I.getSuccessor(0);
|
|
|
|
|
const BasicBlock *EHPadBB = I.getSuccessor(1);
|
|
|
|
|
|
2017-03-10 08:25:35 +08:00
|
|
|
|
const Value *Callee = I.getCalledValue();
|
2016-11-10 06:39:54 +08:00
|
|
|
|
const Function *Fn = dyn_cast<Function>(Callee);
|
|
|
|
|
if (isa<InlineAsm>(Callee))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// FIXME: support invoking patchpoint and statepoint intrinsics.
|
|
|
|
|
if (Fn && Fn->isIntrinsic())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// FIXME: support whatever these are.
|
|
|
|
|
if (I.countOperandBundlesOfType(LLVMContext::OB_deopt))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// FIXME: support Windows exception handling.
|
|
|
|
|
if (!isa<LandingPadInst>(EHPadBB->front()))
|
|
|
|
|
return false;
|
|
|
|
|
|
2016-12-02 03:32:15 +08:00
|
|
|
|
// Emit the actual call, bracketed by EH_LABELs so that the MF knows about
|
2016-11-10 06:39:54 +08:00
|
|
|
|
// the region covered by the try.
|
2016-12-02 03:32:15 +08:00
|
|
|
|
MCSymbol *BeginSymbol = Context.createTempSymbol();
|
2016-11-10 06:39:54 +08:00
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol);
|
|
|
|
|
|
|
|
|
|
unsigned Res = I.getType()->isVoidTy() ? 0 : getOrCreateVReg(I);
|
2017-02-01 02:36:11 +08:00
|
|
|
|
SmallVector<unsigned, 8> Args;
|
2016-11-10 06:39:54 +08:00
|
|
|
|
for (auto &Arg: I.arg_operands())
|
2017-02-01 02:36:11 +08:00
|
|
|
|
Args.push_back(getOrCreateVReg(*Arg));
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2017-03-10 08:25:44 +08:00
|
|
|
|
if (!CLI->lowerCall(MIRBuilder, &I, Res, Args,
|
2017-03-10 08:25:35 +08:00
|
|
|
|
[&]() { return getOrCreateVReg(*I.getCalledValue()); }))
|
|
|
|
|
return false;
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2016-12-02 03:32:15 +08:00
|
|
|
|
MCSymbol *EndSymbol = Context.createTempSymbol();
|
2016-11-10 06:39:54 +08:00
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol);
|
|
|
|
|
|
|
|
|
|
// FIXME: track probabilities.
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &EHPadMBB = getMBB(*EHPadBB),
|
|
|
|
|
&ReturnMBB = getMBB(*ReturnBB);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
MF->addInvoke(&EHPadMBB, BeginSymbol, EndSymbol);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
MIRBuilder.getMBB().addSuccessor(&ReturnMBB);
|
|
|
|
|
MIRBuilder.getMBB().addSuccessor(&EHPadMBB);
|
2017-02-01 04:12:18 +08:00
|
|
|
|
MIRBuilder.buildBr(ReturnMBB);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translateLandingPad(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
2016-11-10 06:39:54 +08:00
|
|
|
|
const LandingPadInst &LP = cast<LandingPadInst>(U);
|
|
|
|
|
|
|
|
|
|
MachineBasicBlock &MBB = MIRBuilder.getMBB();
|
2016-12-02 03:32:15 +08:00
|
|
|
|
addLandingPadInfo(LP, MBB);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
|
|
|
|
MBB.setIsEHPad();
|
|
|
|
|
|
|
|
|
|
// If there aren't registers to copy the values into (e.g., during SjLj
|
|
|
|
|
// exceptions), then don't bother.
|
2016-12-08 05:17:47 +08:00
|
|
|
|
auto &TLI = *MF->getSubtarget().getTargetLowering();
|
2017-12-16 06:22:58 +08:00
|
|
|
|
const Constant *PersonalityFn = MF->getFunction().getPersonalityFn();
|
2016-11-10 06:39:54 +08:00
|
|
|
|
if (TLI.getExceptionPointerRegister(PersonalityFn) == 0 &&
|
|
|
|
|
TLI.getExceptionSelectorRegister(PersonalityFn) == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// If landingpad's return type is token type, we don't create DAG nodes
|
|
|
|
|
// for its exception pointer and selector value. The extraction of exception
|
|
|
|
|
// pointer or selector value from token type landingpads is not currently
|
|
|
|
|
// supported.
|
|
|
|
|
if (LP.getType()->isTokenTy())
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// Add a label to mark the beginning of the landing pad. Deletion of the
|
|
|
|
|
// landing pad can thus be detected via the MachineModuleInfo.
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL)
|
2016-12-08 05:17:47 +08:00
|
|
|
|
.addSym(MF->addLandingPad(&MBB));
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2017-03-08 07:32:10 +08:00
|
|
|
|
LLT Ty = getLLTForType(*LP.getType(), *DL);
|
2017-03-08 07:04:06 +08:00
|
|
|
|
unsigned Undef = MRI->createGenericVirtualRegister(Ty);
|
|
|
|
|
MIRBuilder.buildUndef(Undef);
|
|
|
|
|
|
2017-01-25 08:16:53 +08:00
|
|
|
|
SmallVector<LLT, 2> Tys;
|
|
|
|
|
for (Type *Ty : cast<StructType>(LP.getType())->elements())
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
Tys.push_back(getLLTForType(*Ty, *DL));
|
2017-01-25 08:16:53 +08:00
|
|
|
|
assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
|
|
|
|
|
|
2016-11-10 06:39:54 +08:00
|
|
|
|
// Mark exception register as live in.
|
2017-03-08 07:04:06 +08:00
|
|
|
|
unsigned ExceptionReg = TLI.getExceptionPointerRegister(PersonalityFn);
|
|
|
|
|
if (!ExceptionReg)
|
|
|
|
|
return false;
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2017-03-08 07:04:06 +08:00
|
|
|
|
MBB.addLiveIn(ExceptionReg);
|
|
|
|
|
unsigned VReg = MRI->createGenericVirtualRegister(Tys[0]),
|
|
|
|
|
Tmp = MRI->createGenericVirtualRegister(Ty);
|
|
|
|
|
MIRBuilder.buildCopy(VReg, ExceptionReg);
|
|
|
|
|
MIRBuilder.buildInsert(Tmp, Undef, VReg, 0);
|
|
|
|
|
|
|
|
|
|
unsigned SelectorReg = TLI.getExceptionSelectorRegister(PersonalityFn);
|
|
|
|
|
if (!SelectorReg)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
MBB.addLiveIn(SelectorReg);
|
|
|
|
|
|
|
|
|
|
// N.b. the exception selector register always has pointer type and may not
|
|
|
|
|
// match the actual IR-level type in the landingpad so an extra cast is
|
|
|
|
|
// needed.
|
|
|
|
|
unsigned PtrVReg = MRI->createGenericVirtualRegister(Tys[0]);
|
|
|
|
|
MIRBuilder.buildCopy(PtrVReg, SelectorReg);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2017-03-08 07:04:06 +08:00
|
|
|
|
VReg = MRI->createGenericVirtualRegister(Tys[1]);
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT).addDef(VReg).addUse(PtrVReg);
|
|
|
|
|
MIRBuilder.buildInsert(getOrCreateVReg(LP), Tmp, VReg,
|
|
|
|
|
Tys[0].getSizeInBits());
|
2016-11-10 06:39:54 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-04 02:22:45 +08:00
|
|
|
|
bool IRTranslator::translateAlloca(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
auto &AI = cast<AllocaInst>(U);
|
|
|
|
|
|
|
|
|
|
if (AI.isStaticAlloca()) {
|
|
|
|
|
unsigned Res = getOrCreateVReg(AI);
|
|
|
|
|
int FI = getOrCreateFrameIndex(AI);
|
|
|
|
|
MIRBuilder.buildFrameIndex(Res, FI);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now we're in the harder dynamic case.
|
|
|
|
|
Type *Ty = AI.getAllocatedType();
|
|
|
|
|
unsigned Align =
|
|
|
|
|
std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI.getAlignment());
|
|
|
|
|
|
|
|
|
|
unsigned NumElts = getOrCreateVReg(*AI.getArraySize());
|
|
|
|
|
|
2017-03-16 03:21:11 +08:00
|
|
|
|
Type *IntPtrIRTy = DL->getIntPtrType(AI.getType());
|
|
|
|
|
LLT IntPtrTy = getLLTForType(*IntPtrIRTy, *DL);
|
2017-02-04 02:22:45 +08:00
|
|
|
|
if (MRI->getType(NumElts) != IntPtrTy) {
|
|
|
|
|
unsigned ExtElts = MRI->createGenericVirtualRegister(IntPtrTy);
|
|
|
|
|
MIRBuilder.buildZExtOrTrunc(ExtElts, NumElts);
|
|
|
|
|
NumElts = ExtElts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned AllocSize = MRI->createGenericVirtualRegister(IntPtrTy);
|
2017-03-16 03:21:11 +08:00
|
|
|
|
unsigned TySize =
|
|
|
|
|
getOrCreateVReg(*ConstantInt::get(IntPtrIRTy, -DL->getTypeAllocSize(Ty)));
|
2017-02-04 02:22:45 +08:00
|
|
|
|
MIRBuilder.buildMul(AllocSize, NumElts, TySize);
|
|
|
|
|
|
Recommit: [globalisel] Change LLT constructor string into an LLT-based object that knows how to generate it.
Summary:
This will allow future patches to inspect the details of the LLT. The implementation is now split between
the Support and CodeGen libraries to allow TableGen to use this class without introducing layering concerns.
Thanks to Ahmed Bougacha for finding a reasonable way to avoid the layering issue and providing the version of this patch without that problem.
The problem with the previous commit appears to have been that TableGen was including CodeGen/LowLevelType.h instead of Support/LowLevelTypeImpl.h.
Reviewers: t.p.northover, qcolombet, rovka, aditya_nandakumar, ab, javed.absar
Subscribers: arsenm, nhaehnle, mgorny, dberris, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30046
llvm-svn: 297241
2017-03-08 07:20:35 +08:00
|
|
|
|
LLT PtrTy = getLLTForType(*AI.getType(), *DL);
|
2017-02-04 02:22:45 +08:00
|
|
|
|
auto &TLI = *MF->getSubtarget().getTargetLowering();
|
|
|
|
|
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
|
|
|
|
|
|
|
|
|
|
unsigned SPTmp = MRI->createGenericVirtualRegister(PtrTy);
|
|
|
|
|
MIRBuilder.buildCopy(SPTmp, SPReg);
|
|
|
|
|
|
2017-02-15 04:56:18 +08:00
|
|
|
|
unsigned AllocTmp = MRI->createGenericVirtualRegister(PtrTy);
|
|
|
|
|
MIRBuilder.buildGEP(AllocTmp, SPTmp, AllocSize);
|
2017-02-04 02:22:45 +08:00
|
|
|
|
|
|
|
|
|
// Handle alignment. We have to realign if the allocation granule was smaller
|
|
|
|
|
// than stack alignment, or the specific alloca requires more than stack
|
|
|
|
|
// alignment.
|
|
|
|
|
unsigned StackAlign =
|
|
|
|
|
MF->getSubtarget().getFrameLowering()->getStackAlignment();
|
|
|
|
|
Align = std::max(Align, StackAlign);
|
|
|
|
|
if (Align > StackAlign || DL->getTypeAllocSize(Ty) % StackAlign != 0) {
|
|
|
|
|
// Round the size of the allocation up to the stack alignment size
|
|
|
|
|
// by add SA-1 to the size. This doesn't overflow because we're computing
|
|
|
|
|
// an address inside an alloca.
|
2017-02-15 04:56:18 +08:00
|
|
|
|
unsigned AlignedAlloc = MRI->createGenericVirtualRegister(PtrTy);
|
|
|
|
|
MIRBuilder.buildPtrMask(AlignedAlloc, AllocTmp, Log2_32(Align));
|
|
|
|
|
AllocTmp = AlignedAlloc;
|
2017-02-04 02:22:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-15 04:56:18 +08:00
|
|
|
|
MIRBuilder.buildCopy(SPReg, AllocTmp);
|
|
|
|
|
MIRBuilder.buildCopy(getOrCreateVReg(AI), AllocTmp);
|
2016-08-27 07:49:05 +08:00
|
|
|
|
|
2017-02-04 02:22:45 +08:00
|
|
|
|
MF->getFrameInfo().CreateVariableSizedObject(Align ? Align : 1, &AI);
|
|
|
|
|
assert(MF->getFrameInfo().hasVarSizedObjects());
|
2016-07-23 00:59:52 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-16 07:22:33 +08:00
|
|
|
|
bool IRTranslator::translateVAArg(const User &U, MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
// FIXME: We may need more info about the type. Because of how LLT works,
|
|
|
|
|
// we're completely discarding the i64/double distinction here (amongst
|
|
|
|
|
// others). Fortunately the ABIs I know of where that matters don't use va_arg
|
|
|
|
|
// anyway but that's not guaranteed.
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_VAARG)
|
|
|
|
|
.addDef(getOrCreateVReg(U))
|
|
|
|
|
.addUse(getOrCreateVReg(*U.getOperand(0)))
|
|
|
|
|
.addImm(DL->getABITypeAlignment(U.getType()));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-11 03:08:28 +08:00
|
|
|
|
bool IRTranslator::translateInsertElement(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
// If it is a <1 x Ty> vector, use the scalar as it is
|
|
|
|
|
// not a legal vector type in LLT.
|
|
|
|
|
if (U.getType()->getVectorNumElements() == 1) {
|
|
|
|
|
unsigned Elt = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
ValToVReg[&U] = Elt;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-04-19 14:38:37 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
|
|
|
|
unsigned Val = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Elt = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
unsigned Idx = getOrCreateVReg(*U.getOperand(2));
|
|
|
|
|
MIRBuilder.buildInsertVectorElement(Res, Val, Elt, Idx);
|
2017-03-11 03:08:28 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IRTranslator::translateExtractElement(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
// If it is a <1 x Ty> vector, use the scalar as it is
|
|
|
|
|
// not a legal vector type in LLT.
|
|
|
|
|
if (U.getOperand(0)->getType()->getVectorNumElements() == 1) {
|
|
|
|
|
unsigned Elt = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
ValToVReg[&U] = Elt;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-04-19 14:38:37 +08:00
|
|
|
|
unsigned Res = getOrCreateVReg(U);
|
|
|
|
|
unsigned Val = getOrCreateVReg(*U.getOperand(0));
|
|
|
|
|
unsigned Idx = getOrCreateVReg(*U.getOperand(1));
|
|
|
|
|
MIRBuilder.buildExtractVectorElement(Res, Val, Idx);
|
2017-03-11 03:08:28 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 16:44:13 +08:00
|
|
|
|
bool IRTranslator::translateShuffleVector(const User &U,
|
|
|
|
|
MachineIRBuilder &MIRBuilder) {
|
|
|
|
|
MIRBuilder.buildInstr(TargetOpcode::G_SHUFFLE_VECTOR)
|
|
|
|
|
.addDef(getOrCreateVReg(U))
|
|
|
|
|
.addUse(getOrCreateVReg(*U.getOperand(0)))
|
|
|
|
|
.addUse(getOrCreateVReg(*U.getOperand(1)))
|
|
|
|
|
.addUse(getOrCreateVReg(*U.getOperand(2)));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:29:15 +08:00
|
|
|
|
bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
const PHINode &PI = cast<PHINode>(U);
|
2017-08-24 04:45:48 +08:00
|
|
|
|
auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI);
|
2016-08-06 01:16:40 +08:00
|
|
|
|
MIB.addDef(getOrCreateVReg(PI));
|
|
|
|
|
|
|
|
|
|
PendingPHIs.emplace_back(&PI, MIB.getInstr());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRTranslator::finishPendingPhis() {
|
|
|
|
|
for (std::pair<const PHINode *, MachineInstr *> &Phi : PendingPHIs) {
|
|
|
|
|
const PHINode *PI = Phi.first;
|
2016-12-08 05:29:15 +08:00
|
|
|
|
MachineInstrBuilder MIB(*MF, Phi.second);
|
2016-08-06 01:16:40 +08:00
|
|
|
|
|
|
|
|
|
// All MachineBasicBlocks exist, add them to the PHI. We assume IRTranslator
|
|
|
|
|
// won't create extra control flow here, otherwise we need to find the
|
|
|
|
|
// dominating predecessor here (or perhaps force the weirder IRTranslators
|
|
|
|
|
// to provide a simple boundary).
|
2017-01-18 06:13:50 +08:00
|
|
|
|
SmallSet<const BasicBlock *, 4> HandledPreds;
|
|
|
|
|
|
2016-08-06 01:16:40 +08:00
|
|
|
|
for (unsigned i = 0; i < PI->getNumIncomingValues(); ++i) {
|
2017-01-18 06:13:50 +08:00
|
|
|
|
auto IRPred = PI->getIncomingBlock(i);
|
|
|
|
|
if (HandledPreds.count(IRPred))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
HandledPreds.insert(IRPred);
|
|
|
|
|
unsigned ValReg = getOrCreateVReg(*PI->getIncomingValue(i));
|
|
|
|
|
for (auto Pred : getMachinePredBBs({IRPred, PI->getParent()})) {
|
|
|
|
|
assert(Pred->isSuccessor(MIB->getParent()) &&
|
|
|
|
|
"incorrect CFG at MachineBasicBlock level");
|
|
|
|
|
MIB.addUse(ValReg);
|
|
|
|
|
MIB.addMBB(Pred);
|
|
|
|
|
}
|
2016-08-06 01:16:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 06:59:27 +08:00
|
|
|
|
bool IRTranslator::translate(const Instruction &Inst) {
|
2016-12-08 05:29:15 +08:00
|
|
|
|
CurBuilder.setDebugLoc(Inst.getDebugLoc());
|
2016-02-11 06:59:27 +08:00
|
|
|
|
switch(Inst.getOpcode()) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
#define HANDLE_INST(NUM, OPCODE, CLASS) \
|
2016-12-08 05:29:15 +08:00
|
|
|
|
case Instruction::OPCODE: return translate##OPCODE(Inst, CurBuilder);
|
2016-08-11 07:02:41 +08:00
|
|
|
|
#include "llvm/IR/Instruction.def"
|
2016-02-12 02:53:28 +08:00
|
|
|
|
default:
|
2017-03-11 08:28:33 +08:00
|
|
|
|
return false;
|
2016-02-11 06:59:27 +08:00
|
|
|
|
}
|
2016-01-21 04:58:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-10 05:28:04 +08:00
|
|
|
|
bool IRTranslator::translate(const Constant &C, unsigned Reg) {
|
2016-08-10 07:01:30 +08:00
|
|
|
|
if (auto CI = dyn_cast<ConstantInt>(&C))
|
2016-12-06 05:54:17 +08:00
|
|
|
|
EntryBuilder.buildConstant(Reg, *CI);
|
2016-08-20 04:09:15 +08:00
|
|
|
|
else if (auto CF = dyn_cast<ConstantFP>(&C))
|
2016-09-09 19:46:34 +08:00
|
|
|
|
EntryBuilder.buildFConstant(Reg, *CF);
|
2016-08-10 07:01:30 +08:00
|
|
|
|
else if (isa<UndefValue>(C))
|
2017-03-07 02:36:40 +08:00
|
|
|
|
EntryBuilder.buildUndef(Reg);
|
2016-08-12 05:40:55 +08:00
|
|
|
|
else if (isa<ConstantPointerNull>(C))
|
2016-12-06 05:47:07 +08:00
|
|
|
|
EntryBuilder.buildConstant(Reg, 0);
|
2016-09-12 20:10:41 +08:00
|
|
|
|
else if (auto GV = dyn_cast<GlobalValue>(&C))
|
|
|
|
|
EntryBuilder.buildGlobalValue(Reg, GV);
|
2017-03-11 05:23:13 +08:00
|
|
|
|
else if (auto CAZ = dyn_cast<ConstantAggregateZero>(&C)) {
|
|
|
|
|
if (!CAZ->getType()->isVectorTy())
|
|
|
|
|
return false;
|
2017-03-15 07:45:06 +08:00
|
|
|
|
// Return the scalar if it is a <1 x Ty> vector.
|
|
|
|
|
if (CAZ->getNumElements() == 1)
|
|
|
|
|
return translate(*CAZ->getElementValue(0u), Reg);
|
2017-03-11 05:23:13 +08:00
|
|
|
|
std::vector<unsigned> Ops;
|
|
|
|
|
for (unsigned i = 0; i < CAZ->getNumElements(); ++i) {
|
|
|
|
|
Constant &Elt = *CAZ->getElementValue(i);
|
|
|
|
|
Ops.push_back(getOrCreateVReg(Elt));
|
|
|
|
|
}
|
|
|
|
|
EntryBuilder.buildMerge(Reg, Ops);
|
GlobalISel: Translate ConstantDataVector
Reviewers: qcolombet, aditya_nandakumar, dsanders, t.p.northover, javed.absar, ab
Reviewed By: qcolombet, dsanders, ab
Subscribers: dberris, rovka, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30216
llvm-svn: 297670
2017-03-14 05:36:19 +08:00
|
|
|
|
} else if (auto CV = dyn_cast<ConstantDataVector>(&C)) {
|
2017-03-15 07:45:06 +08:00
|
|
|
|
// Return the scalar if it is a <1 x Ty> vector.
|
|
|
|
|
if (CV->getNumElements() == 1)
|
|
|
|
|
return translate(*CV->getElementAsConstant(0), Reg);
|
GlobalISel: Translate ConstantDataVector
Reviewers: qcolombet, aditya_nandakumar, dsanders, t.p.northover, javed.absar, ab
Reviewed By: qcolombet, dsanders, ab
Subscribers: dberris, rovka, llvm-commits, kristof.beyls
Differential Revision: https://reviews.llvm.org/D30216
llvm-svn: 297670
2017-03-14 05:36:19 +08:00
|
|
|
|
std::vector<unsigned> Ops;
|
|
|
|
|
for (unsigned i = 0; i < CV->getNumElements(); ++i) {
|
|
|
|
|
Constant &Elt = *CV->getElementAsConstant(i);
|
|
|
|
|
Ops.push_back(getOrCreateVReg(Elt));
|
|
|
|
|
}
|
|
|
|
|
EntryBuilder.buildMerge(Reg, Ops);
|
2017-03-11 05:23:13 +08:00
|
|
|
|
} else if (auto CE = dyn_cast<ConstantExpr>(&C)) {
|
2016-08-11 07:02:41 +08:00
|
|
|
|
switch(CE->getOpcode()) {
|
|
|
|
|
#define HANDLE_INST(NUM, OPCODE, CLASS) \
|
2016-12-08 05:29:15 +08:00
|
|
|
|
case Instruction::OPCODE: return translate##OPCODE(*CE, EntryBuilder);
|
2016-08-11 07:02:41 +08:00
|
|
|
|
#include "llvm/IR/Instruction.def"
|
|
|
|
|
default:
|
2017-03-11 08:28:33 +08:00
|
|
|
|
return false;
|
2016-08-11 07:02:41 +08:00
|
|
|
|
}
|
2017-05-19 17:47:02 +08:00
|
|
|
|
} else if (auto CS = dyn_cast<ConstantStruct>(&C)) {
|
|
|
|
|
// Return the element if it is a single element ConstantStruct.
|
|
|
|
|
if (CS->getNumOperands() == 1) {
|
|
|
|
|
unsigned EltReg = getOrCreateVReg(*CS->getOperand(0));
|
|
|
|
|
EntryBuilder.buildCast(Reg, EltReg);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
SmallVector<unsigned, 4> Ops;
|
|
|
|
|
SmallVector<uint64_t, 4> Indices;
|
|
|
|
|
uint64_t Offset = 0;
|
|
|
|
|
for (unsigned i = 0; i < CS->getNumOperands(); ++i) {
|
|
|
|
|
unsigned OpReg = getOrCreateVReg(*CS->getOperand(i));
|
|
|
|
|
Ops.push_back(OpReg);
|
|
|
|
|
Indices.push_back(Offset);
|
|
|
|
|
Offset += MRI->getType(OpReg).getSizeInBits();
|
|
|
|
|
}
|
|
|
|
|
EntryBuilder.buildSequence(Reg, Ops, Indices);
|
2017-05-05 05:43:12 +08:00
|
|
|
|
} else if (auto CV = dyn_cast<ConstantVector>(&C)) {
|
|
|
|
|
if (CV->getNumOperands() == 1)
|
|
|
|
|
return translate(*CV->getOperand(0), Reg);
|
|
|
|
|
SmallVector<unsigned, 4> Ops;
|
|
|
|
|
for (unsigned i = 0; i < CV->getNumOperands(); ++i) {
|
|
|
|
|
Ops.push_back(getOrCreateVReg(*CV->getOperand(i)));
|
|
|
|
|
}
|
|
|
|
|
EntryBuilder.buildMerge(Reg, Ops);
|
2017-03-11 08:28:33 +08:00
|
|
|
|
} else
|
2016-08-27 07:49:05 +08:00
|
|
|
|
return false;
|
2016-08-10 05:28:04 +08:00
|
|
|
|
|
2016-08-10 07:01:30 +08:00
|
|
|
|
return true;
|
2016-08-10 05:28:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-12 00:21:29 +08:00
|
|
|
|
void IRTranslator::finalizeFunction() {
|
2016-02-11 06:59:27 +08:00
|
|
|
|
// Release the memory used by the different maps we
|
|
|
|
|
// needed during the translation.
|
2016-12-06 07:10:19 +08:00
|
|
|
|
PendingPHIs.clear();
|
2016-02-12 05:48:32 +08:00
|
|
|
|
ValToVReg.clear();
|
2016-11-01 02:30:59 +08:00
|
|
|
|
FrameIndices.clear();
|
2017-01-18 06:13:50 +08:00
|
|
|
|
MachinePreds.clear();
|
2017-05-18 01:41:55 +08:00
|
|
|
|
// MachineIRBuilder::DebugLoc can outlive the DILocation it holds. Clear it
|
|
|
|
|
// to avoid accessing free’d memory (in runOnMachineFunction) and to avoid
|
|
|
|
|
// destroying it twice (in ~IRTranslator() and ~LLVMContext())
|
|
|
|
|
EntryBuilder = MachineIRBuilder();
|
|
|
|
|
CurBuilder = MachineIRBuilder();
|
2016-01-21 04:58:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 05:17:47 +08:00
|
|
|
|
bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
|
|
|
|
|
MF = &CurMF;
|
2017-12-16 06:22:58 +08:00
|
|
|
|
const Function &F = MF->getFunction();
|
2016-02-12 03:59:41 +08:00
|
|
|
|
if (F.empty())
|
|
|
|
|
return false;
|
2016-12-08 05:17:47 +08:00
|
|
|
|
CLI = MF->getSubtarget().getCallLowering();
|
2016-12-08 05:29:15 +08:00
|
|
|
|
CurBuilder.setMF(*MF);
|
2016-12-08 05:17:47 +08:00
|
|
|
|
EntryBuilder.setMF(*MF);
|
|
|
|
|
MRI = &MF->getRegInfo();
|
2016-07-23 00:59:52 +08:00
|
|
|
|
DL = &F.getParent()->getDataLayout();
|
2016-08-27 07:49:05 +08:00
|
|
|
|
TPC = &getAnalysis<TargetPassConfig>();
|
2017-06-27 06:44:03 +08:00
|
|
|
|
ORE = llvm::make_unique<OptimizationRemarkEmitter>(&F);
|
2016-07-23 00:59:52 +08:00
|
|
|
|
|
2016-08-06 01:50:36 +08:00
|
|
|
|
assert(PendingPHIs.empty() && "stale PHIs");
|
|
|
|
|
|
2017-12-12 00:58:29 +08:00
|
|
|
|
if (!DL->isLittleEndian()) {
|
|
|
|
|
// Currently we don't properly handle big endian code.
|
|
|
|
|
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
|
2017-12-16 06:22:58 +08:00
|
|
|
|
F.getSubprogram(), &F.getEntryBlock());
|
2017-12-12 00:58:29 +08:00
|
|
|
|
R << "unable to translate in big endian mode";
|
|
|
|
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-24 07:57:28 +08:00
|
|
|
|
// Release the per-function state when we return, whether we succeeded or not.
|
|
|
|
|
auto FinalizeOnReturn = make_scope_exit([this]() { finalizeFunction(); });
|
|
|
|
|
|
2017-03-16 02:22:33 +08:00
|
|
|
|
// Setup a separate basic-block for the arguments and constants
|
2016-12-08 05:17:47 +08:00
|
|
|
|
MachineBasicBlock *EntryBB = MF->CreateMachineBasicBlock();
|
|
|
|
|
MF->push_back(EntryBB);
|
2016-12-08 05:05:38 +08:00
|
|
|
|
EntryBuilder.setMBB(*EntryBB);
|
|
|
|
|
|
2017-03-16 02:22:33 +08:00
|
|
|
|
// Create all blocks, in IR order, to preserve the layout.
|
|
|
|
|
for (const BasicBlock &BB: F) {
|
|
|
|
|
auto *&MBB = BBToMBB[&BB];
|
|
|
|
|
|
|
|
|
|
MBB = MF->CreateMachineBasicBlock(&BB);
|
|
|
|
|
MF->push_back(MBB);
|
|
|
|
|
|
|
|
|
|
if (BB.hasAddressTaken())
|
|
|
|
|
MBB->setHasAddressTaken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make our arguments/constants entry block fallthrough to the IR entry block.
|
|
|
|
|
EntryBB->addSuccessor(&getMBB(F.front()));
|
|
|
|
|
|
2016-12-08 05:05:38 +08:00
|
|
|
|
// Lower the actual args into this basic block.
|
2016-02-12 03:59:41 +08:00
|
|
|
|
SmallVector<unsigned, 8> VRegArgs;
|
2017-12-01 04:06:02 +08:00
|
|
|
|
for (const Argument &Arg: F.args()) {
|
|
|
|
|
if (DL->getTypeStoreSize(Arg.getType()) == 0)
|
|
|
|
|
continue; // Don't handle zero sized types.
|
2016-03-12 01:27:54 +08:00
|
|
|
|
VRegArgs.push_back(getOrCreateVReg(Arg));
|
2017-12-01 04:06:02 +08:00
|
|
|
|
}
|
2017-02-24 08:34:41 +08:00
|
|
|
|
if (!CLI->lowerFormalArguments(EntryBuilder, F, VRegArgs)) {
|
2017-02-24 08:34:44 +08:00
|
|
|
|
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
|
2017-12-16 06:22:58 +08:00
|
|
|
|
F.getSubprogram(), &F.getEntryBlock());
|
2017-02-24 05:05:42 +08:00
|
|
|
|
R << "unable to lower arguments: " << ore::NV("Prototype", F.getType());
|
|
|
|
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
|
|
|
|
return false;
|
2016-08-27 07:49:05 +08:00
|
|
|
|
}
|
2016-02-12 03:59:41 +08:00
|
|
|
|
|
2016-12-08 05:05:38 +08:00
|
|
|
|
// And translate the function!
|
2016-02-11 06:59:27 +08:00
|
|
|
|
for (const BasicBlock &BB: F) {
|
2017-03-16 02:22:33 +08:00
|
|
|
|
MachineBasicBlock &MBB = getMBB(BB);
|
2016-03-12 01:27:47 +08:00
|
|
|
|
// Set the insertion point of all the following translations to
|
|
|
|
|
// the end of this basic block.
|
2016-12-08 05:29:15 +08:00
|
|
|
|
CurBuilder.setMBB(MBB);
|
2016-11-10 06:39:54 +08:00
|
|
|
|
|
2016-02-11 06:59:27 +08:00
|
|
|
|
for (const Instruction &Inst: BB) {
|
2017-02-24 08:34:41 +08:00
|
|
|
|
if (translate(Inst))
|
|
|
|
|
continue;
|
|
|
|
|
|
2017-02-24 08:34:47 +08:00
|
|
|
|
OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure",
|
|
|
|
|
Inst.getDebugLoc(), &BB);
|
2017-09-19 02:50:09 +08:00
|
|
|
|
R << "unable to translate instruction: " << ore::NV("Opcode", &Inst);
|
|
|
|
|
|
|
|
|
|
if (ORE->allowExtraAnalysis("gisel-irtranslator")) {
|
|
|
|
|
std::string InstStrStorage;
|
|
|
|
|
raw_string_ostream InstStr(InstStrStorage);
|
|
|
|
|
InstStr << Inst;
|
|
|
|
|
|
|
|
|
|
R << ": '" << InstStr.str() << "'";
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-24 08:34:41 +08:00
|
|
|
|
reportTranslationError(*MF, *TPC, *ORE, R);
|
|
|
|
|
return false;
|
2016-02-11 06:59:27 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-07-13 06:23:42 +08:00
|
|
|
|
|
2017-02-24 07:57:36 +08:00
|
|
|
|
finishPendingPhis();
|
|
|
|
|
|
|
|
|
|
// Merge the argument lowering and constants block with its single
|
|
|
|
|
// successor, the LLVM-IR entry block. We want the basic block to
|
|
|
|
|
// be maximal.
|
|
|
|
|
assert(EntryBB->succ_size() == 1 &&
|
|
|
|
|
"Custom BB used for lowering should have only one successor");
|
|
|
|
|
// Get the successor of the current entry block.
|
|
|
|
|
MachineBasicBlock &NewEntryBB = **EntryBB->succ_begin();
|
|
|
|
|
assert(NewEntryBB.pred_size() == 1 &&
|
|
|
|
|
"LLVM-IR entry block has a predecessor!?");
|
|
|
|
|
// Move all the instruction from the current entry block to the
|
|
|
|
|
// new entry block.
|
|
|
|
|
NewEntryBB.splice(NewEntryBB.begin(), EntryBB, EntryBB->begin(),
|
|
|
|
|
EntryBB->end());
|
|
|
|
|
|
|
|
|
|
// Update the live-in information for the new entry block.
|
|
|
|
|
for (const MachineBasicBlock::RegisterMaskPair &LiveIn : EntryBB->liveins())
|
|
|
|
|
NewEntryBB.addLiveIn(LiveIn);
|
|
|
|
|
NewEntryBB.sortUniqueLiveIns();
|
|
|
|
|
|
|
|
|
|
// Get rid of the now empty basic block.
|
|
|
|
|
EntryBB->removeSuccessor(&NewEntryBB);
|
|
|
|
|
MF->remove(EntryBB);
|
|
|
|
|
MF->DeleteMachineBasicBlock(EntryBB);
|
|
|
|
|
|
|
|
|
|
assert(&MF->front() == &NewEntryBB &&
|
|
|
|
|
"New entry wasn't next in the list of basic block!");
|
2016-08-06 01:16:40 +08:00
|
|
|
|
|
2016-01-21 04:58:56 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|