summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h8
-rw-r--r--llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h9
-rw-r--r--llvm/include/llvm/Target/GenericOpcodes.td19
-rw-r--r--llvm/include/llvm/Target/TargetOpcodes.def10
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp25
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp12
-rw-r--r--llvm/lib/CodeGen/MIRPrinter.cpp2
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll60
8 files changed, 135 insertions, 10 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index b61f5bbcdd0..656e327fedc 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -93,6 +93,14 @@ private:
/// \return true if the translation succeeded.
bool translate(const Instruction &Inst);
+ /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is
+ /// emitted.
+ bool translateBitCast(const CastInst &CI);
+
+ /// Translate one of LLVM's cast instructions into MachineInstrs, with the
+ /// given generic Opcode.
+ bool translateCast(unsigned Opcode, const CastInst &CI);
+
/// Translate alloca instruction (i.e. one of constant size and in the first
/// basic block).
bool translateStaticAlloca(const AllocaInst &Inst);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 55eafb372f9..c835be06e2d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -116,6 +116,15 @@ public:
MachineInstr *buildInstr(unsigned Opcode, LLT Ty, unsigned Res,
unsigned Op0, unsigned Op1);
+ /// Build and insert \p Res<def> = \p Opcode {[\p Tys]} \p Op0, \p Op1.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre Tys empty or isPreISelGenericOpcode(Opcode)
+ ///
+ /// \return The newly created instruction.
+ MachineInstr *buildInstr(unsigned Opcode, ArrayRef<LLT> Tys, unsigned Res,
+ unsigned Op0);
+
/// Build and insert \p Res<def> = \p Opcode \p Op0, \p Op1.
/// I.e., instruction with a non-generic opcode.
///
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 4c297322aa7..0f846e743c3 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -22,6 +22,25 @@ def G_FRAME_INDEX : Instruction {
let hasSideEffects = 0;
}
+def G_INTTOPTR : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins unknown:$src);
+ let hasSideEffects = 0;
+}
+
+def G_PTRTOINT : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins unknown:$src);
+ let hasSideEffects = 0;
+}
+
+def G_BITCAST : Instruction {
+ let OutOperandList = (outs unknown:$dst);
+ let InOperandList = (ins unknown:$src);
+ let hasSideEffects = 0;
+}
+
+
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------
diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def
index 297ff82ccfd..61668770329 100644
--- a/llvm/include/llvm/Target/TargetOpcodes.def
+++ b/llvm/include/llvm/Target/TargetOpcodes.def
@@ -180,6 +180,16 @@ HANDLE_TARGET_OPCODE(G_EXTRACT)
/// larger register.
HANDLE_TARGET_OPCODE(G_SEQUENCE)
+/// Generic pointer to int conversion.
+HANDLE_TARGET_OPCODE(G_PTRTOINT)
+
+/// Generic int to pointer conversion.
+HANDLE_TARGET_OPCODE(G_INTTOPTR)
+
+/// Generic bitcast. The source and destination types must be different, or a
+/// COPY is the relevant instruction.
+HANDLE_TARGET_OPCODE(G_BITCAST)
+
/// Generic BRANCH instruction. This is an unconditional branch.
HANDLE_TARGET_OPCODE(G_BR)
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 82cec258fa6..f7db60f59b5 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -100,6 +100,23 @@ bool IRTranslator::translateBr(const Instruction &Inst) {
return true;
}
+bool IRTranslator::translateBitCast(const CastInst &CI) {
+ if (LLT{*CI.getDestTy()} == LLT{*CI.getSrcTy()}) {
+ MIRBuilder.buildInstr(TargetOpcode::COPY, getOrCreateVReg(CI),
+ getOrCreateVReg(*CI.getOperand(0)));
+ return true;
+ }
+ return translateCast(TargetOpcode::G_BITCAST, CI);
+}
+
+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()}},
+ Res, Op);
+ return true;
+}
+
bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) {
assert(AI.isStaticAlloca() && "only handle static allocas now");
MachineFunction &MF = MIRBuilder.getMF();
@@ -138,6 +155,14 @@ bool IRTranslator::translate(const Instruction &Inst) {
case Instruction::Ret:
return translateReturn(Inst);
+ // Casts
+ 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::Alloca:
return translateStaticAlloca(cast<AllocaInst>(Inst));
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 2b91584c75d..f18467c4bb4 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -85,6 +85,18 @@ MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, LLT Ty,
return NewMI;
}
+MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, ArrayRef<LLT> Tys,
+ unsigned Res, unsigned Op0) {
+ MachineInstr *NewMI = buildInstr(Opcode, Tys[0]);
+ for (unsigned i = 1; i < Tys.size(); ++i)
+ NewMI->setType(Tys[i], i);
+
+ MachineInstrBuilder(getMF(), NewMI)
+ .addReg(Res, RegState::Define)
+ .addReg(Op0);
+ return NewMI;
+}
+
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, unsigned Res,
unsigned Op0) {
MachineInstr *NewMI = buildInstr(Opcode, LLT{});
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index f738385adcc..7946fc2676f 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -568,7 +568,7 @@ void MIPrinter::print(const MachineInstr &MI) {
assert(MI.getType().isValid() && "Generic instructions must have a type");
OS << " { ";
for (unsigned i = 0; i < MI.getNumTypes(); ++i) {
- MI.getType().print(OS);
+ MI.getType(i).print(OS);
if (i + 1 != MI.getNumTypes())
OS << ", ";
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
index 032a527e3e7..2bcfc6c4a25 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
@@ -6,7 +6,7 @@ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-apple-ios"
; Tests for add.
-; CHECK: name: addi64
+; CHECK-LABEL: name: addi64
; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1
; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_ADD { s64 } [[ARG1]], [[ARG2]]
@@ -18,7 +18,7 @@ define i64 @addi64(i64 %arg1, i64 %arg2) {
}
; Tests for alloca
-; CHECK: name: allocai64
+; CHECK-LABEL: name: allocai64
; CHECK: stack:
; CHECK-NEXT: - { id: 0, name: ptr1, offset: 0, size: 8, alignment: 8 }
; CHECK-NEXT: - { id: 1, name: ptr2, offset: 0, size: 8, alignment: 1 }
@@ -34,7 +34,7 @@ define void @allocai64() {
}
; Tests for br.
-; CHECK: name: uncondbr
+; CHECK-LABEL: name: uncondbr
; CHECK: body:
;
; Entry basic block.
@@ -56,7 +56,7 @@ end:
}
; Tests for or.
-; CHECK: name: ori64
+; CHECK-LABEL: name: ori64
; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1
; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_OR { s64 } [[ARG1]], [[ARG2]]
@@ -67,7 +67,7 @@ define i64 @ori64(i64 %arg1, i64 %arg2) {
ret i64 %res
}
-; CHECK: name: ori32
+; CHECK-LABEL: name: ori32
; CHECK: [[ARG1:%[0-9]+]](32) = COPY %w0
; CHECK-NEXT: [[ARG2:%[0-9]+]](32) = COPY %w1
; CHECK-NEXT: [[RES:%[0-9]+]](32) = G_OR { s32 } [[ARG1]], [[ARG2]]
@@ -79,7 +79,7 @@ define i32 @ori32(i32 %arg1, i32 %arg2) {
}
; Tests for and.
-; CHECK: name: andi64
+; CHECK-LABEL: name: andi64
; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1
; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_AND { s64 } [[ARG1]], [[ARG2]]
@@ -90,7 +90,7 @@ define i64 @andi64(i64 %arg1, i64 %arg2) {
ret i64 %res
}
-; CHECK: name: andi32
+; CHECK-LABEL: name: andi32
; CHECK: [[ARG1:%[0-9]+]](32) = COPY %w0
; CHECK-NEXT: [[ARG2:%[0-9]+]](32) = COPY %w1
; CHECK-NEXT: [[RES:%[0-9]+]](32) = G_AND { s32 } [[ARG1]], [[ARG2]]
@@ -102,7 +102,7 @@ define i32 @andi32(i32 %arg1, i32 %arg2) {
}
; Tests for sub.
-; CHECK: name: subi64
+; CHECK-LABEL: name: subi64
; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1
; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_SUB { s64 } [[ARG1]], [[ARG2]]
@@ -113,7 +113,7 @@ define i64 @subi64(i64 %arg1, i64 %arg2) {
ret i64 %res
}
-; CHECK: name: subi32
+; CHECK-LABEL: name: subi32
; CHECK: [[ARG1:%[0-9]+]](32) = COPY %w0
; CHECK-NEXT: [[ARG2:%[0-9]+]](32) = COPY %w1
; CHECK-NEXT: [[RES:%[0-9]+]](32) = G_SUB { s32 } [[ARG1]], [[ARG2]]
@@ -123,3 +123,45 @@ define i32 @subi32(i32 %arg1, i32 %arg2) {
%res = sub i32 %arg1, %arg2
ret i32 %res
}
+
+; CHECK-LABEL: name: ptrtoint
+; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
+; CHECK: [[RES:%[0-9]+]](64) = G_PTRTOINT { s64, p0 } [[ARG1]]
+; CHECK: %x0 = COPY [[RES]]
+; CHECK: RET_ReallyLR implicit %x0
+define i64 @ptrtoint(i64* %a) {
+ %val = ptrtoint i64* %a to i64
+ ret i64 %val
+}
+
+; CHECK-LABEL: name: inttoptr
+; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
+; CHECK: [[RES:%[0-9]+]](64) = G_INTTOPTR { p0, s64 } [[ARG1]]
+; CHECK: %x0 = COPY [[RES]]
+; CHECK: RET_ReallyLR implicit %x0
+define i64* @inttoptr(i64 %a) {
+ %val = inttoptr i64 %a to i64*
+ ret i64* %val
+}
+
+; CHECK-LABEL: name: trivial_bitcast
+; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
+; CHECK: [[RES:%[0-9]+]](64) = COPY [[ARG1]]
+; CHECK: %x0 = COPY [[RES]]
+; CHECK: RET_ReallyLR implicit %x0
+define i64* @trivial_bitcast(i8* %a) {
+ %val = bitcast i8* %a to i64*
+ ret i64* %val
+}
+
+; CHECK-LABEL: name: bitcast
+; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0
+; CHECK: [[RES1:%[0-9]+]](64) = G_BITCAST { <2 x s32>, s64 } [[ARG1]]
+; CHECK: [[RES2:%[0-9]+]](64) = G_BITCAST { s64, <2 x s32> } [[RES1]]
+; CHECK: %x0 = COPY [[RES2]]
+; CHECK: RET_ReallyLR implicit %x0
+define i64 @bitcast(i64 %a) {
+ %res1 = bitcast i64 %a to <2 x i32>
+ %res2 = bitcast <2 x i32> %res1 to i64
+ ret i64 %res2
+}
OpenPOWER on IntegriCloud