forked from OSchip/llvm-project
GlobalISel: support selection of extend operations.
Patch mostly by Ahmed Bougaca. llvm-svn: 283937
This commit is contained in:
parent
60cf6fc58f
commit
3d38b3a4d1
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
...
|
||||
|
|
Loading…
Reference in New Issue