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: {
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
...
---
+# 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
legalized: true