1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

GlobalISel: support floating-point constants on AArch64.

Patch from Ahmed Bougacha.

llvm-svn: 284523
This commit is contained in:
Tim Northover 2016-10-18 19:47:57 +00:00
parent 7adf6be710
commit 189324351a
2 changed files with 109 additions and 7 deletions

View File

@ -513,14 +513,81 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
return constrainSelectedInstRegOperands(*MIB.getInstr(), TII, TRI, RBI);
}
case TargetOpcode::G_FCONSTANT:
case TargetOpcode::G_CONSTANT: {
if (Ty.getSizeInBits() <= 32)
I.setDesc(TII.get(AArch64::MOVi32imm));
else if (Ty.getSizeInBits() <= 64)
I.setDesc(TII.get(AArch64::MOVi64imm));
else
return false;
return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
const bool isFP = Opcode == TargetOpcode::G_FCONSTANT;
const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
const LLT p0 = LLT::pointer(0, 64);
const unsigned DefReg = I.getOperand(0).getReg();
const LLT DefTy = MRI.getType(DefReg);
const unsigned DefSize = DefTy.getSizeInBits();
const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
// FIXME: Redundant check, but even less readable when factored out.
if (isFP) {
if (Ty != s32 && Ty != s64) {
DEBUG(dbgs() << "Unable to materialize FP " << Ty
<< " constant, expected: " << s32 << " or " << s64
<< '\n');
return false;
}
if (RB.getID() != AArch64::FPRRegBankID) {
DEBUG(dbgs() << "Unable to materialize FP " << Ty
<< " constant on bank: " << RB << ", expected: FPR\n");
return false;
}
} else {
if (Ty != s32 && Ty != s64 && Ty != p0) {
DEBUG(dbgs() << "Unable to materialize integer " << Ty
<< " constant, expected: " << s32 << ", " << s64 << ", or "
<< p0 << '\n');
return false;
}
if (RB.getID() != AArch64::GPRRegBankID) {
DEBUG(dbgs() << "Unable to materialize integer " << Ty
<< " constant on bank: " << RB << ", expected: GPR\n");
return false;
}
}
const unsigned MovOpc =
DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
I.setDesc(TII.get(MovOpc));
if (isFP) {
const TargetRegisterClass &GPRRC =
DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
const TargetRegisterClass &FPRRC =
DefSize == 32 ? AArch64::FPR32RegClass : AArch64::FPR64RegClass;
const unsigned DefGPRReg = MRI.createVirtualRegister(&GPRRC);
MachineOperand &RegOp = I.getOperand(0);
RegOp.setReg(DefGPRReg);
BuildMI(MBB, std::next(I.getIterator()), I.getDebugLoc(),
TII.get(AArch64::COPY))
.addDef(DefReg)
.addUse(DefGPRReg);
if (!RBI.constrainGenericRegister(DefReg, FPRRC, MRI)) {
DEBUG(dbgs() << "Failed to constrain G_FCONSTANT def operand\n");
return false;
}
MachineOperand &ImmOp = I.getOperand(1);
// FIXME: Is going through int64_t always correct?
ImmOp.ChangeToImmediate(
ImmOp.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
}
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
return true;
}
case TargetOpcode::G_FRAME_INDEX: {

View File

@ -103,6 +103,9 @@
define i32 @const_s32() { ret i32 42 }
define i64 @const_s64() { ret i64 1234567890123 }
define i32 @fconst_s32() { ret i32 42 }
define i64 @fconst_s64() { ret i64 1234567890123 }
define i8* @gep(i8* %in) { ret i8* undef }
@var_local = global i8 0
@ -1878,6 +1881,38 @@ body: |
%0(s64) = G_CONSTANT 1234567890123
...
---
# CHECK-LABEL: name: fconst_s32
name: fconst_s32
legalized: true
regBankSelected: true
registers:
- { id: 0, class: fpr }
# CHECK: body:
# CHECK: [[TMP:%[0-9]+]] = MOVi32imm 1080033280
# CHECK: %0 = COPY [[TMP]]
body: |
bb.0:
%0(s32) = G_FCONSTANT float 3.5
...
---
# CHECK-LABEL: name: fconst_s64
name: fconst_s64
legalized: true
regBankSelected: true
registers:
- { id: 0, class: fpr }
# CHECK: body:
# CHECK: [[TMP:%[0-9]+]] = MOVi64imm 4607182418800017408
# CHECK: %0 = COPY [[TMP]]
body: |
bb.0:
%0(s64) = G_FCONSTANT double 1.0
...
---
# CHECK-LABEL: name: gep
name: gep