summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h107
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp116
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll8
3 files changed, 143 insertions, 88 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 74aa09b6351..73f4317566b 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -109,47 +109,128 @@ private:
/// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is
/// emitted.
- bool translateBitCast(const CastInst &CI);
+ bool translateBitCast(const User &U);
/// Translate an LLVM load instruction into generic IR.
- bool translateLoad(const LoadInst &LI);
+ bool translateLoad(const User &U);
/// Translate an LLVM store instruction into generic IR.
- bool translateStore(const StoreInst &SI);
+ bool translateStore(const User &U);
/// Translate call instruction.
- /// \pre \p Inst is a call instruction.
- bool translateCall(const CallInst &Inst);
+ /// \pre \p U is a call instruction.
+ bool translateCall(const User &U);
/// Translate one of LLVM's cast instructions into MachineInstrs, with the
/// given generic Opcode.
- bool translateCast(unsigned Opcode, const CastInst &CI);
+ bool translateCast(unsigned Opcode, const User &U);
/// Translate static alloca instruction (i.e. one of constant size and in the
/// first basic block).
bool translateStaticAlloca(const AllocaInst &Inst);
/// Translate a phi instruction.
- bool translatePhi(const PHINode &PI);
+ bool translatePHI(const User &U);
/// Add remaining operands onto phis we've translated. Executed after all
/// MachineBasicBlocks for the function have been created.
void finishPendingPhis();
/// Translate \p Inst into a binary operation \p Opcode.
- /// \pre \p Inst is a binary operation.
- bool translateBinaryOp(unsigned Opcode, const BinaryOperator &Inst);
+ /// \pre \p U is a binary operation.
+ bool translateBinaryOp(unsigned Opcode, const User &U);
/// Translate branch (br) instruction.
- /// \pre \p Inst is a branch instruction.
- bool translateBr(const BranchInst &Inst);
+ /// \pre \p U is a branch instruction.
+ bool translateBr(const User &U);
+ bool translateAdd(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_ADD, U);
+ }
+ bool translateSub(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_SUB, U);
+ }
+ bool translateAnd(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_AND, U);
+ }
+ bool translateMul(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_MUL, U);
+ }
+ bool translateOr(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_OR, U);
+ }
+ bool translateXor(const User &U) {
+ return translateBinaryOp(TargetOpcode::G_XOR, U);
+ }
+ bool translateAlloca(const User &U) {
+ return translateStaticAlloca(cast<AllocaInst>(U));
+ }
+ bool translateIntToPtr(const User &U) {
+ return translateCast(TargetOpcode::G_INTTOPTR, U);
+ }
+ bool translatePtrToInt(const User &U) {
+ return translateCast(TargetOpcode::G_PTRTOINT, U);
+ }
+ bool translateTrunc(const User &U) {
+ return translateCast(TargetOpcode::G_TRUNC, U);
+ }
+ bool translateUnreachable(const User &U) { return true; }
/// Translate return (ret) instruction.
/// The target needs to implement CallLowering::lowerReturn for
/// this to succeed.
- /// \pre \p Inst is a return instruction.
- bool translateReturn(const ReturnInst &Inst);
+ /// \pre \p U is a return instruction.
+ bool translateRet(const User &U);
+
+ // Stubs to keep the compiler happy while we implement the rest of the
+ // translation.
+ bool translateSwitch(const User &U) { return false; }
+ bool translateIndirectBr(const User &U) { return false; }
+ bool translateInvoke(const User &U) { return false; }
+ bool translateResume(const User &U) { return false; }
+ bool translateCleanupRet(const User &U) { return false; }
+ bool translateCatchRet(const User &U) { return false; }
+ bool translateCatchSwitch(const User &U) { return false; }
+ bool translateFAdd(const User &U) { return false; }
+ bool translateFSub(const User &U) { return false; }
+ bool translateFMul(const User &U) { return false; }
+ bool translateUDiv(const User &U) { return false; }
+ bool translateSDiv(const User &U) { return false; }
+ bool translateFDiv(const User &U) { return false; }
+ bool translateURem(const User &U) { return false; }
+ bool translateSRem(const User &U) { return false; }
+ bool translateFRem(const User &U) { return false; }
+ bool translateShl(const User &U) { return false; }
+ bool translateLShr(const User &U) { return false; }
+ bool translateAShr(const User &U) { return false; }
+ bool translateGetElementPtr(const User &U) { return false; }
+ bool translateFence(const User &U) { return false; }
+ bool translateAtomicCmpXchg(const User &U) { return false; }
+ bool translateAtomicRMW(const User &U) { return false; }
+ bool translateSExt(const User &U) { return false; }
+ bool translateZExt(const User &U) { return false; }
+ bool translateFPToUI(const User &U) { return false; }
+ bool translateFPToSI(const User &U) { return false; }
+ bool translateUIToFP(const User &U) { return false; }
+ bool translateSIToFP(const User &U) { return false; }
+ bool translateFPTrunc(const User &U) { return false; }
+ bool translateFPExt(const User &U) { return false; }
+ bool translateAddrSpaceCast(const User &U) { return false; }
+ bool translateCleanupPad(const User &U) { return false; }
+ bool translateCatchPad(const User &U) { return false; }
+ bool translateICmp(const User &U) { return false; }
+ bool translateFCmp(const User &U) { return false; }
+ bool translateSelect(const User &U) { return false; }
+ bool translateUserOp1(const User &U) { return false; }
+ bool translateUserOp2(const User &U) { return false; }
+ bool translateVAArg(const User &U) { return false; }
+ bool translateExtractElement(const User &U) { return false; }
+ bool translateInsertElement(const User &U) { return false; }
+ bool translateShuffleVector(const User &U) { return false; }
+ bool translateExtractValue(const User &U) { return false; }
+ bool translateInsertValue(const User &U) { return false; }
+ bool translateLandingPad(const User &U) { return false; }
+
/// @}
// Builder for machine instruction a la IRBuilder.
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 788823d18d1..0f06b54e976 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -84,25 +84,25 @@ MachineBasicBlock &IRTranslator::getOrCreateBB(const BasicBlock &BB) {
return *MBB;
}
-bool IRTranslator::translateBinaryOp(unsigned Opcode,
- const BinaryOperator &Inst) {
+bool IRTranslator::translateBinaryOp(unsigned Opcode, const User &U) {
// FIXME: handle signed/unsigned wrapping flags.
// 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.
- unsigned Op0 = getOrCreateVReg(*Inst.getOperand(0));
- unsigned Op1 = getOrCreateVReg(*Inst.getOperand(1));
- unsigned Res = getOrCreateVReg(Inst);
- MIRBuilder.buildInstr(Opcode, LLT{*Inst.getType()})
+ unsigned Op0 = getOrCreateVReg(*U.getOperand(0));
+ unsigned Op1 = getOrCreateVReg(*U.getOperand(1));
+ unsigned Res = getOrCreateVReg(U);
+ MIRBuilder.buildInstr(Opcode, LLT{*U.getType()})
.addDef(Res)
.addUse(Op0)
.addUse(Op1);
return true;
}
-bool IRTranslator::translateReturn(const ReturnInst &RI) {
+bool IRTranslator::translateRet(const User &U) {
+ const ReturnInst &RI = cast<ReturnInst>(U);
const Value *Ret = RI.getReturnValue();
// The target may mess up with the insertion point, but
// this is not important as a return is the last instruction
@@ -110,7 +110,8 @@ bool IRTranslator::translateReturn(const ReturnInst &RI) {
return CLI->lowerReturn(MIRBuilder, Ret, !Ret ? 0 : getOrCreateVReg(*Ret));
}
-bool IRTranslator::translateBr(const BranchInst &BrInst) {
+bool IRTranslator::translateBr(const User &U) {
+ const BranchInst &BrInst = cast<BranchInst>(U);
unsigned Succ = 0;
if (!BrInst.isUnconditional()) {
// We want a G_BRCOND to the true BB followed by an unconditional branch.
@@ -131,7 +132,8 @@ bool IRTranslator::translateBr(const BranchInst &BrInst) {
return true;
}
-bool IRTranslator::translateLoad(const LoadInst &LI) {
+bool IRTranslator::translateLoad(const User &U) {
+ const LoadInst &LI = cast<LoadInst>(U);
assert(LI.isSimple() && "only simple loads are supported at the moment");
MachineFunction &MF = MIRBuilder.getMF();
@@ -147,7 +149,8 @@ bool IRTranslator::translateLoad(const LoadInst &LI) {
return true;
}
-bool IRTranslator::translateStore(const StoreInst &SI) {
+bool IRTranslator::translateStore(const User &U) {
+ const StoreInst &SI = cast<StoreInst>(U);
assert(SI.isSimple() && "only simple loads are supported at the moment");
MachineFunction &MF = MIRBuilder.getMF();
@@ -164,28 +167,30 @@ bool IRTranslator::translateStore(const StoreInst &SI) {
return true;
}
-bool IRTranslator::translateBitCast(const CastInst &CI) {
- if (LLT{*CI.getDestTy()} == LLT{*CI.getSrcTy()}) {
- unsigned &Reg = ValToVReg[&CI];
+bool IRTranslator::translateBitCast(const User &U) {
+ if (LLT{*U.getOperand(0)->getType()} == LLT{*U.getType()}) {
+ unsigned &Reg = ValToVReg[&U];
if (Reg)
- MIRBuilder.buildCopy(Reg, getOrCreateVReg(*CI.getOperand(0)));
+ MIRBuilder.buildCopy(Reg, getOrCreateVReg(*U.getOperand(0)));
else
- Reg = getOrCreateVReg(*CI.getOperand(0));
+ Reg = getOrCreateVReg(*U.getOperand(0));
return true;
}
- return translateCast(TargetOpcode::G_BITCAST, CI);
+ return translateCast(TargetOpcode::G_BITCAST, U);
}
-bool IRTranslator::translateCast(unsigned Opcode, const CastInst &CI) {
- unsigned Op = getOrCreateVReg(*CI.getOperand(0));
- unsigned Res = getOrCreateVReg(CI);
- MIRBuilder.buildInstr(Opcode, {LLT{*CI.getDestTy()}, LLT{*CI.getSrcTy()}})
+bool IRTranslator::translateCast(unsigned Opcode, const User &U) {
+ unsigned Op = getOrCreateVReg(*U.getOperand(0));
+ unsigned Res = getOrCreateVReg(U);
+ MIRBuilder
+ .buildInstr(Opcode, {LLT{*U.getType()}, LLT{*U.getOperand(0)->getType()}})
.addDef(Res)
.addUse(Op);
return true;
}
-bool IRTranslator::translateCall(const CallInst &CI) {
+bool IRTranslator::translateCall(const User &U) {
+ const CallInst &CI = cast<CallInst>(U);
auto TII = MIRBuilder.getMF().getTarget().getIntrinsicInfo();
const Function *F = CI.getCalledFunction();
@@ -246,7 +251,8 @@ bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) {
return true;
}
-bool IRTranslator::translatePhi(const PHINode &PI) {
+bool IRTranslator::translatePHI(const User &U) {
+ const PHINode &PI = cast<PHINode>(U);
MachineInstrBuilder MIB = MIRBuilder.buildInstr(TargetOpcode::PHI);
MIB.addDef(getOrCreateVReg(PI));
@@ -277,59 +283,11 @@ void IRTranslator::finishPendingPhis() {
bool IRTranslator::translate(const Instruction &Inst) {
MIRBuilder.setDebugLoc(Inst.getDebugLoc());
switch(Inst.getOpcode()) {
- // Arithmetic operations.
- case Instruction::Add:
- return translateBinaryOp(TargetOpcode::G_ADD, cast<BinaryOperator>(Inst));
- case Instruction::Sub:
- return translateBinaryOp(TargetOpcode::G_SUB, cast<BinaryOperator>(Inst));
-
- // Bitwise operations.
- case Instruction::And:
- return translateBinaryOp(TargetOpcode::G_AND, cast<BinaryOperator>(Inst));
- case Instruction::Mul:
- return translateBinaryOp(TargetOpcode::G_MUL, cast<BinaryOperator>(Inst));
- case Instruction::Or:
- return translateBinaryOp(TargetOpcode::G_OR, cast<BinaryOperator>(Inst));
- case Instruction::Xor:
- return translateBinaryOp(TargetOpcode::G_XOR, cast<BinaryOperator>(Inst));
-
- // Branch operations.
- case Instruction::Br:
- return translateBr(cast<BranchInst>(Inst));
- case Instruction::Ret:
- return translateReturn(cast<ReturnInst>(Inst));
-
- // Calls
- case Instruction::Call:
- return translateCall(cast<CallInst>(Inst));
-
- // Casts and allied operations
- case Instruction::BitCast:
- return translateBitCast(cast<CastInst>(Inst));
- case Instruction::IntToPtr:
- return translateCast(TargetOpcode::G_INTTOPTR, cast<CastInst>(Inst));
- case Instruction::PtrToInt:
- return translateCast(TargetOpcode::G_PTRTOINT, cast<CastInst>(Inst));
- case Instruction::Trunc:
- return translateCast(TargetOpcode::G_TRUNC, cast<CastInst>(Inst));
-
- // Memory ops.
- case Instruction::Load:
- return translateLoad(cast<LoadInst>(Inst));
- case Instruction::Store:
- return translateStore(cast<StoreInst>(Inst));
-
- case Instruction::Alloca:
- return translateStaticAlloca(cast<AllocaInst>(Inst));
-
- case Instruction::PHI:
- return translatePhi(cast<PHINode>(Inst));
-
- case Instruction::Unreachable:
- return true;
-
+#define HANDLE_INST(NUM, OPCODE, CLASS) \
+ case Instruction::OPCODE: return translate##OPCODE(Inst);
+#include "llvm/IR/Instruction.def"
default:
- llvm_unreachable("Opcode not supported");
+ llvm_unreachable("unknown opcode");
}
}
@@ -338,7 +296,15 @@ bool IRTranslator::translate(const Constant &C, unsigned Reg) {
EntryBuilder.buildConstant(LLT{*CI->getType()}, Reg, CI->getZExtValue());
else if (isa<UndefValue>(C))
EntryBuilder.buildInstr(TargetOpcode::IMPLICIT_DEF).addDef(Reg);
- else
+ else if (auto CE = dyn_cast<ConstantExpr>(&C)) {
+ switch(CE->getOpcode()) {
+#define HANDLE_INST(NUM, OPCODE, CLASS) \
+ case Instruction::OPCODE: return translate##OPCODE(*CE);
+#include "llvm/IR/Instruction.def"
+ default:
+ llvm_unreachable("unknown opcode");
+ }
+ } else
llvm_unreachable("unhandled constant kind");
return true;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
index f036d121dfd..a164c7a4c47 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
@@ -389,3 +389,11 @@ define i32 @constant_int_start() {
define i32 @test_undef() {
ret i32 undef
}
+
+; CHECK-LABEL: name: test_constant_inttoptr
+; CHECK: [[ONE:%[0-9]+]](64) = G_CONSTANT s64 1
+; CHECK: [[PTR:%[0-9]+]](64) = G_INTTOPTR { p0, s64 } [[ONE]]
+; CHECK: %x0 = COPY [[PTR]]
+define i8* @test_constant_inttoptr() {
+ ret i8* inttoptr(i64 1 to i8*)
+}
OpenPOWER on IntegriCloud