[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