Skip to content

Commit

Permalink
GlobalISel: support selection of extend operations.
Browse files Browse the repository at this point in the history
Patch mostly by Ahmed Bougaca.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283937 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
TNorthover committed Oct 11, 2016
1 parent 4c7a4f4 commit 6a493c6
Show file tree
Hide file tree
Showing 2 changed files with 203 additions and 0 deletions.
99 changes: 99 additions & 0 deletions lib/Target/AArch64/AArch64InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,105 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
// 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;
Expand Down
104 changes: 104 additions & 0 deletions test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
...

---
Expand Down Expand Up @@ -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
...

0 comments on commit 6a493c6

Please sign in to comment.