[llvm] r283937 - GlobalISel: support selection of extend operations.

Quentin Colombet via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 11 21:16:10 PDT 2016


Hi Tim,

I was adding the support for copies and bit casts (we stepped a bit on each other toes, sorry about that x)) and that led me to refactor a bit the handling of G_ANYEXT. (r283972)
I wanted to point out that I was surprised that G_ANYEXT is handled differently than G_SEXT and G_ZEXT. I would have expected G_ANYEXT to be a shrunk version of the cheapest expansion of both for the related types.
What do you think?

Although, I notice that we unconditionally generate BFM-like instructions for G_SEXT and G_ZEXT. That is correct but it seems sub-optimal to me. Is the intent to use G_ANYEXT every time we know we don’t need to generate BFM or is this a limitation in the current handling?

Thanks,
-Quentin
 
> On Oct 11, 2016, at 1:50 PM, Tim Northover via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> Author: tnorthover
> Date: Tue Oct 11 15:50:21 2016
> New Revision: 283937
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=283937&view=rev
> Log:
> GlobalISel: support selection of extend operations.
> 
> Patch mostly by Ahmed Bougaca.
> 
> Modified:
>    llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
>    llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir
> 
> Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=283937&r1=283936&r2=283937&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Tue Oct 11 15:50:21 2016
> @@ -394,6 +394,105 @@ bool AArch64InstructionSelector::select(
>     // operands to use appropriate classes.
>     return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
>   }
> +
> +  case TargetOpcode::G_ANYEXT: {
> +    const unsigned DstReg = I.getOperand(0).getReg();
> +    const unsigned SrcReg = I.getOperand(1).getReg();
> +
> +    const RegisterBank &RB = *RBI.getRegBank(DstReg, MRI, TRI);
> +
> +    if (RB.getID() != AArch64::GPRRegBankID) {
> +      DEBUG(dbgs() << "G_ANYEXT on bank: " << RB << ", expected: GPR\n");
> +      return false;
> +    }
> +
> +    const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
> +
> +    if (DstSize == 0) {
> +      DEBUG(dbgs() << "G_ANYEXT operand has no size, not a gvreg?\n");
> +      return false;
> +    }
> +
> +    const TargetRegisterClass *RC = nullptr;
> +    if (DstSize <= 32) {
> +      RC = &AArch64::GPR32RegClass;
> +    } else if (DstSize == 64) {
> +      RC = &AArch64::GPR64RegClass;
> +    } else {
> +      DEBUG(dbgs() << "G_ANYEXT to size: " << DstSize
> +                   << ", expected: 32 or 64\n");
> +      return false;
> +    }
> +
> +    if (!RBI.constrainGenericRegister(SrcReg, *RC, MRI) ||
> +        !RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
> +      DEBUG(dbgs() << "Failed to constrain G_ANYEXT\n");
> +      return false;
> +    }
> +
> +    BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::COPY))
> +        .addDef(DstReg)
> +        .addUse(SrcReg);
> +
> +    I.eraseFromParent();
> +    return true;
> +  }
> +
> +  case TargetOpcode::G_ZEXT:
> +  case TargetOpcode::G_SEXT: {
> +    unsigned Opcode = I.getOpcode();
> +    const LLT DstTy = MRI.getType(I.getOperand(0).getReg()),
> +              SrcTy = MRI.getType(I.getOperand(1).getReg());
> +    const bool isSigned = Opcode == TargetOpcode::G_SEXT;
> +    const unsigned DefReg = I.getOperand(0).getReg();
> +    const unsigned SrcReg = I.getOperand(1).getReg();
> +    const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
> +
> +    if (RB.getID() != AArch64::GPRRegBankID) {
> +      DEBUG(dbgs() << TII.getName(I.getOpcode()) << " on bank: " << RB
> +                   << ", expected: GPR\n");
> +      return false;
> +    }
> +
> +    MachineInstr *ExtI;
> +    if (DstTy == LLT::scalar(64)) {
> +      // FIXME: Can we avoid manually doing this?
> +      if (!RBI.constrainGenericRegister(SrcReg, AArch64::GPR32RegClass, MRI)) {
> +        DEBUG(dbgs() << "Failed to constrain " << TII.getName(Opcode)
> +                     << " operand\n");
> +        return false;
> +      }
> +
> +      const unsigned SrcXReg =
> +          MRI.createVirtualRegister(&AArch64::GPR64RegClass);
> +      BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::SUBREG_TO_REG))
> +          .addDef(SrcXReg)
> +          .addImm(0)
> +          .addUse(SrcReg)
> +          .addImm(AArch64::sub_32);
> +
> +      const unsigned NewOpc = isSigned ? AArch64::SBFMXri : AArch64::UBFMXri;
> +      ExtI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
> +                 .addDef(DefReg)
> +                 .addUse(SrcXReg)
> +                 .addImm(0)
> +                 .addImm(SrcTy.getSizeInBits() - 1);
> +    } else if (DstTy == LLT::scalar(32)) {
> +      const unsigned NewOpc = isSigned ? AArch64::SBFMWri : AArch64::UBFMWri;
> +      ExtI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc))
> +                 .addDef(DefReg)
> +                 .addUse(SrcReg)
> +                 .addImm(0)
> +                 .addImm(SrcTy.getSizeInBits() - 1);
> +    } else {
> +      return false;
> +    }
> +
> +    constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
> +
> +    I.eraseFromParent();
> +    return true;
> +  }
>   }
> 
>   return false;
> 
> Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir?rev=283937&r1=283936&r2=283937&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir (original)
> +++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir Tue Oct 11 15:50:21 2016
> @@ -82,6 +82,10 @@
> 
>   @var_got = external global i8
>   define i8* @global_got() { ret i8* undef }
> +
> +  define void @anyext_gpr() { ret void }
> +  define void @zext_gpr() { ret void }
> +  define void @sext_gpr() { ret void }
> ...
> 
> ---
> @@ -1319,3 +1323,103 @@ body:             |
>   bb.0:
>     %0(p0) = G_GLOBAL_VALUE @var_got
> ...
> +
> +---
> +# CHECK-LABEL: name: anyext_gpr
> +name:            anyext_gpr
> +legalized:       true
> +regBankSelected: true
> +
> +# CHECK:      registers:
> +# CHECK-NEXT:  - { id: 0, class: gpr64 }
> +# CHECK-NEXT:  - { id: 1, class: gpr64 }
> +# CHECK-NEXT:  - { id: 2, class: gpr32 }
> +# CHECK-NEXT:  - { id: 3, class: gpr32 }
> +registers:
> +  - { id: 0, class: gpr }
> +  - { id: 1, class: gpr }
> +  - { id: 2, class: gpr }
> +  - { id: 3, class: gpr }
> +
> +# CHECK:  body:
> +# CHECK:    %0 = COPY %w0
> +# CHECK:    %1 = COPY %0
> +# CHECK:    %2 = COPY %w0
> +# CHECK:    %3 = COPY %2
> +body:             |
> +  bb.0:
> +    liveins: %x0
> +
> +    %0(s32) = COPY %w0
> +    %1(s64) = G_ANYEXT %0
> +    %2(s8) = COPY %w0
> +    %3(s32) = G_ANYEXT %2
> +...
> +
> +---
> +# CHECK-LABEL: name: zext_gpr
> +name:            zext_gpr
> +legalized:       true
> +regBankSelected: true
> +
> +# CHECK:      registers:
> +# CHECK-NEXT:  - { id: 0, class: gpr32 }
> +# CHECK-NEXT:  - { id: 1, class: gpr64 }
> +# CHECK-NEXT:  - { id: 2, class: gpr32 }
> +# CHECK-NEXT:  - { id: 3, class: gpr32 }
> +# CHECK-NEXT:  - { id: 4, class: gpr64 }
> +registers:
> +  - { id: 0, class: gpr }
> +  - { id: 1, class: gpr }
> +  - { id: 2, class: gpr }
> +  - { id: 3, class: gpr }
> +
> +# CHECK:  body:
> +# CHECK:    %0 = COPY %w0
> +# CHECK:    %4 = SUBREG_TO_REG 0, %0, 15
> +# CHECK:    %1 = UBFMXri %4, 0, 31
> +# CHECK:    %2 = COPY %w0
> +# CHECK:    %3 = UBFMWri %2, 0, 7
> +body:             |
> +  bb.0:
> +    liveins: %x0
> +
> +    %0(s32) = COPY %w0
> +    %1(s64) = G_ZEXT %0
> +    %2(s8) = COPY %w0
> +    %3(s32) = G_ZEXT %2
> +...
> +
> +---
> +# CHECK-LABEL: name: sext_gpr
> +name:            sext_gpr
> +legalized:       true
> +regBankSelected: true
> +
> +# CHECK:      registers:
> +# CHECK-NEXT:  - { id: 0, class: gpr32 }
> +# CHECK-NEXT:  - { id: 1, class: gpr64 }
> +# CHECK-NEXT:  - { id: 2, class: gpr32 }
> +# CHECK-NEXT:  - { id: 3, class: gpr32 }
> +# CHECK-NEXT:  - { id: 4, class: gpr64 }
> +registers:
> +  - { id: 0, class: gpr }
> +  - { id: 1, class: gpr }
> +  - { id: 2, class: gpr }
> +  - { id: 3, class: gpr }
> +
> +# CHECK:  body:
> +# CHECK:    %0 = COPY %w0
> +# CHECK:    %4 = SUBREG_TO_REG 0, %0, 15
> +# CHECK:    %1 = SBFMXri %4, 0, 31
> +# CHECK:    %2 = COPY %w0
> +# CHECK:    %3 = SBFMWri %2, 0, 7
> +body:             |
> +  bb.0:
> +    liveins: %x0
> +
> +    %0(s32) = COPY %w0
> +    %1(s64) = G_SEXT %0
> +    %2(s8) = COPY %w0
> +    %3(s32) = G_SEXT %2
> +...
> 
> 
> _______________________________________________
> 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