[llvm] r276690 - GlobalISel: add generic casts to IRTranslator
Quentin Colombet via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 9 18:10:32 PDT 2016
> On Jul 25, 2016, at 2:01 PM, Tim Northover via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
> Author: tnorthover
> Date: Mon Jul 25 16:01:29 2016
> New Revision: 276690
>
> URL: http://llvm.org/viewvc/llvm-project?rev=276690&view=rev
> Log:
> GlobalISel: add generic casts to IRTranslator
>
> This adds LLVM's 3 main cast instructions (inttoptr, ptrtoint, bitcast) to the
> IRTranslator. The first two are direct translations (with 2 MachineInstr types
> each). Since LLT discards information, a bitcast might become trivial and we
> emit a COPY in those cases instead.
>
> Modified:
> llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
> llvm/trunk/include/llvm/Target/GenericOpcodes.td
> llvm/trunk/include/llvm/Target/TargetOpcodes.def
> llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
> llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
> llvm/trunk/lib/CodeGen/MIRPrinter.cpp
> llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h Mon Jul 25 16:01:29 2016
> @@ -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);
>
> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Mon Jul 25 16:01:29 2016
> @@ -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.
> ///
>
> Modified: llvm/trunk/include/llvm/Target/GenericOpcodes.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GenericOpcodes.td?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/GenericOpcodes.td (original)
> +++ llvm/trunk/include/llvm/Target/GenericOpcodes.td Mon Jul 25 16:01:29 2016
> @@ -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.
> //------------------------------------------------------------------------------
>
> Modified: llvm/trunk/include/llvm/Target/TargetOpcodes.def
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOpcodes.def?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetOpcodes.def (original)
> +++ llvm/trunk/include/llvm/Target/TargetOpcodes.def Mon Jul 25 16:01:29 2016
> @@ -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)
>
>
> Modified: llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp (original)
> +++ llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp Mon Jul 25 16:01:29 2016
> @@ -100,6 +100,23 @@ bool IRTranslator::translateBr(const Ins
> return true;
> }
>
> +bool IRTranslator::translateBitCast(const CastInst &CI) {
> + if (LLT{*CI.getDestTy()} == LLT{*CI.getSrcTy()}) {
Shouldn’t we test isNoOpCast or something like that instead?
I.e., having v2i32 becoming v8i8 should also produce a copy.
> + MIRBuilder.buildInstr(TargetOpcode::COPY, getOrCreateVReg(CI),
> + getOrCreateVReg(*CI.getOperand(0)));
Although this is correct, I’d like to be a little smarter here. Basically, I would like that we directly use CI.getOperand(0)’s vreg if CI hasn’t been created yet. I.e., I’d like we avoid creating copies if we don’t have to.
> + 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 Instr
> 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));
>
>
> Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Mon Jul 25 16:01:29 2016
> @@ -85,6 +85,18 @@ MachineInstr *MachineIRBuilder::buildIns
> 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{});
>
> Modified: llvm/trunk/lib/CodeGen/MIRPrinter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRPrinter.cpp?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/MIRPrinter.cpp (original)
> +++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp Mon Jul 25 16:01:29 2016
> @@ -568,7 +568,7 @@ void MIPrinter::print(const MachineInstr
> 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 << ", ";
> }
>
> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll?rev=276690&r1=276689&r2=276690&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll (original)
> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll Mon Jul 25 16:01:29 2016
> @@ -6,7 +6,7 @@ target datalayout = "e-m:o-i64:64-i128:1
> 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
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list