mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-01 00:17:01 +00:00 
			
		
		
		
	R600/SI: Fix f64 inline immediates
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224458 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -70,9 +70,14 @@ void AMDGPUMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const { | ||||
|       llvm_unreachable("unknown operand type"); | ||||
|     case MachineOperand::MO_FPImmediate: { | ||||
|       const APFloat &FloatValue = MO.getFPImm()->getValueAPF(); | ||||
|       assert(&FloatValue.getSemantics() == &APFloat::IEEEsingle && | ||||
|              "Only floating point immediates are supported at the moment."); | ||||
|       MCOp = MCOperand::CreateFPImm(FloatValue.convertToFloat()); | ||||
|  | ||||
|       if (&FloatValue.getSemantics() == &APFloat::IEEEsingle) | ||||
|         MCOp = MCOperand::CreateFPImm(FloatValue.convertToFloat()); | ||||
|       else if (&FloatValue.getSemantics() == &APFloat::IEEEdouble) | ||||
|         MCOp = MCOperand::CreateFPImm(FloatValue.convertToDouble()); | ||||
|       else | ||||
|         llvm_unreachable("Unhandled floating point type"); | ||||
|  | ||||
|       break; | ||||
|     } | ||||
|     case MachineOperand::MO_Immediate: | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "MCTargetDesc/AMDGPUMCTargetDesc.h" | ||||
| #include "llvm/MC/MCExpr.h" | ||||
| #include "llvm/MC/MCInst.h" | ||||
| #include "llvm/MC/MCInstrInfo.h" | ||||
| #include "llvm/MC/MCRegisterInfo.h" | ||||
| #include "llvm/Support/MathExtras.h" | ||||
|  | ||||
| @@ -208,7 +209,7 @@ void AMDGPUInstPrinter::printRegOperand(unsigned reg, raw_ostream &O) { | ||||
|   O << Type << '[' << RegIdx << ':' << (RegIdx + NumRegs - 1) << ']'; | ||||
| } | ||||
|  | ||||
| void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) { | ||||
| void AMDGPUInstPrinter::printImmediate32(uint32_t Imm, raw_ostream &O) { | ||||
|   int32_t SImm = static_cast<int32_t>(Imm); | ||||
|   if (SImm >= -16 && SImm <= 64) { | ||||
|     O << SImm; | ||||
| @@ -233,9 +234,37 @@ void AMDGPUInstPrinter::printImmediate(uint32_t Imm, raw_ostream &O) { | ||||
|     O << "4.0"; | ||||
|   else if (Imm == FloatToBits(-4.0f)) | ||||
|     O << "-4.0"; | ||||
|   else { | ||||
|   else | ||||
|     O << formatHex(static_cast<uint64_t>(Imm)); | ||||
| } | ||||
|  | ||||
| void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) { | ||||
|   int64_t SImm = static_cast<int64_t>(Imm); | ||||
|   if (SImm >= -16 && SImm <= 64) { | ||||
|     O << SImm; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if (Imm == DoubleToBits(0.0)) | ||||
|     O << "0.0"; | ||||
|   else if (Imm == DoubleToBits(1.0)) | ||||
|     O << "1.0"; | ||||
|   else if (Imm == DoubleToBits(-1.0)) | ||||
|     O << "-1.0"; | ||||
|   else if (Imm == DoubleToBits(0.5)) | ||||
|     O << "0.5"; | ||||
|   else if (Imm == DoubleToBits(-0.5)) | ||||
|     O << "-0.5"; | ||||
|   else if (Imm == DoubleToBits(2.0)) | ||||
|     O << "2.0"; | ||||
|   else if (Imm == DoubleToBits(-2.0)) | ||||
|     O << "-2.0"; | ||||
|   else if (Imm == DoubleToBits(4.0)) | ||||
|     O << "4.0"; | ||||
|   else if (Imm == DoubleToBits(-4.0)) | ||||
|     O << "-4.0"; | ||||
|   else | ||||
|     llvm_unreachable("64-bit literal constants not supported"); | ||||
| } | ||||
|  | ||||
| void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, | ||||
| @@ -253,14 +282,37 @@ void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, | ||||
|       break; | ||||
|     } | ||||
|   } else if (Op.isImm()) { | ||||
|     printImmediate(Op.getImm(), O); | ||||
|     const MCInstrDesc &Desc = MII.get(MI->getOpcode()); | ||||
|     int RCID = Desc.OpInfo[OpNo].RegClass; | ||||
|     if (RCID != -1) { | ||||
|       const MCRegisterClass &ImmRC = MRI.getRegClass(RCID); | ||||
|       if (ImmRC.getSize() == 4) | ||||
|         printImmediate32(Op.getImm(), O); | ||||
|       else if (ImmRC.getSize() == 8) | ||||
|         printImmediate64(Op.getImm(), O); | ||||
|       else | ||||
|         llvm_unreachable("Invalid register class size"); | ||||
|     } else { | ||||
|       // We hit this for the immediate instruction bits that don't yet have a | ||||
|       // custom printer. | ||||
|       // TODO: Eventually this should be unnecessary. | ||||
|       O << formatDec(Op.getImm()); | ||||
|     } | ||||
|   } else if (Op.isFPImm()) { | ||||
|  | ||||
|     // We special case 0.0 because otherwise it will be printed as an integer. | ||||
|     if (Op.getFPImm() == 0.0) | ||||
|       O << "0.0"; | ||||
|     else | ||||
|       printImmediate(FloatToBits(Op.getFPImm()), O); | ||||
|     else { | ||||
|       const MCInstrDesc &Desc = MII.get(MI->getOpcode()); | ||||
|       const MCRegisterClass &ImmRC = MRI.getRegClass(Desc.OpInfo[OpNo].RegClass); | ||||
|  | ||||
|       if (ImmRC.getSize() == 4) | ||||
|         printImmediate32(FloatToBits(Op.getFPImm()), O); | ||||
|       else if (ImmRC.getSize() == 8) | ||||
|         printImmediate64(DoubleToBits(Op.getFPImm()), O); | ||||
|       else | ||||
|         llvm_unreachable("Invalid register class size"); | ||||
|     } | ||||
|   } else if (Op.isExpr()) { | ||||
|     const MCExpr *Exp = Op.getExpr(); | ||||
|     Exp->print(O); | ||||
|   | ||||
| @@ -48,7 +48,8 @@ private: | ||||
|   void printSLC(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||||
|   void printTFE(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||||
|   void printRegOperand(unsigned RegNo, raw_ostream &O); | ||||
|   void printImmediate(uint32_t Imm, raw_ostream &O); | ||||
|   void printImmediate32(uint32_t I, raw_ostream &O); | ||||
|   void printImmediate64(uint64_t I, raw_ostream &O); | ||||
|   void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||||
|   void printOperandAndMods(const MCInst *MI, unsigned OpNo, raw_ostream &O); | ||||
|   static void printInterpSlot(const MCInst *MI, unsigned OpNum, raw_ostream &O); | ||||
|   | ||||
| @@ -1578,31 +1578,30 @@ static bool isSSrc(unsigned RegClass) { | ||||
| /// and the immediate value if it's a literal immediate | ||||
| int32_t SITargetLowering::analyzeImmediate(const SDNode *N) const { | ||||
|  | ||||
|   union { | ||||
|     int32_t I; | ||||
|     float F; | ||||
|   } Imm; | ||||
|   const SIInstrInfo *TII = static_cast<const SIInstrInfo *>( | ||||
|     getTargetMachine().getSubtargetImpl()->getInstrInfo()); | ||||
|  | ||||
|   if (const ConstantSDNode *Node = dyn_cast<ConstantSDNode>(N)) { | ||||
|     if (Node->getZExtValue() >> 32) { | ||||
|         return -1; | ||||
|     } | ||||
|     Imm.I = Node->getSExtValue(); | ||||
|   } else if (const ConstantFPSDNode *Node = dyn_cast<ConstantFPSDNode>(N)) { | ||||
|     if (N->getValueType(0) != MVT::f32) | ||||
|     if (Node->getZExtValue() >> 32) | ||||
|       return -1; | ||||
|     Imm.F = Node->getValueAPF().convertToFloat(); | ||||
|   } else | ||||
|     return -1; // It isn't an immediate | ||||
|  | ||||
|   if ((Imm.I >= -16 && Imm.I <= 64) || | ||||
|       Imm.F == 0.5f || Imm.F == -0.5f || | ||||
|       Imm.F == 1.0f || Imm.F == -1.0f || | ||||
|       Imm.F == 2.0f || Imm.F == -2.0f || | ||||
|       Imm.F == 4.0f || Imm.F == -4.0f) | ||||
|     return 0; // It's an inline immediate | ||||
|     if (TII->isInlineConstant(Node->getAPIntValue())) | ||||
|       return 0; | ||||
|  | ||||
|   return Imm.I; // It's a literal immediate | ||||
|     return Node->getZExtValue(); | ||||
|   } | ||||
|  | ||||
|   if (const ConstantFPSDNode *Node = dyn_cast<ConstantFPSDNode>(N)) { | ||||
|     if (TII->isInlineConstant(Node->getValueAPF().bitcastToAPInt())) | ||||
|       return 0; | ||||
|  | ||||
|     if (Node->getValueType(0) == MVT::f32) | ||||
|       return FloatToBits(Node->getValueAPF().convertToFloat()); | ||||
|  | ||||
|     return -1; | ||||
|   } | ||||
|  | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| /// \brief Try to fold an immediate directly into an instruction | ||||
|   | ||||
| @@ -896,10 +896,23 @@ bool SIInstrInfo::areMemAccessesTriviallyDisjoint(MachineInstr *MIa, | ||||
| } | ||||
|  | ||||
| bool SIInstrInfo::isInlineConstant(const APInt &Imm) const { | ||||
|   int32_t Val = Imm.getSExtValue(); | ||||
|   if (Val >= -16 && Val <= 64) | ||||
|   int64_t SVal = Imm.getSExtValue(); | ||||
|   if (SVal >= -16 && SVal <= 64) | ||||
|     return true; | ||||
|  | ||||
|   if (Imm.getBitWidth() == 64) { | ||||
|     uint64_t Val = Imm.getZExtValue(); | ||||
|     return (DoubleToBits(0.0) == Val) || | ||||
|            (DoubleToBits(1.0) == Val) || | ||||
|            (DoubleToBits(-1.0) == Val) || | ||||
|            (DoubleToBits(0.5) == Val) || | ||||
|            (DoubleToBits(-0.5) == Val) || | ||||
|            (DoubleToBits(2.0) == Val) || | ||||
|            (DoubleToBits(-2.0) == Val) || | ||||
|            (DoubleToBits(4.0) == Val) || | ||||
|            (DoubleToBits(-4.0) == Val); | ||||
|   } | ||||
|  | ||||
|   // The actual type of the operand does not seem to matter as long | ||||
|   // as the bits match one of the inline immediate values.  For example: | ||||
|   // | ||||
| @@ -908,16 +921,17 @@ bool SIInstrInfo::isInlineConstant(const APInt &Imm) const { | ||||
|   // | ||||
|   // 1065353216 has the hexadecimal encoding 0x3f800000 which is 1.0f in | ||||
|   // floating-point, so it is a legal inline immediate. | ||||
|   uint32_t Val = Imm.getZExtValue(); | ||||
|  | ||||
|   return (APInt::floatToBits(0.0f) == Imm) || | ||||
|          (APInt::floatToBits(1.0f) == Imm) || | ||||
|          (APInt::floatToBits(-1.0f) == Imm) || | ||||
|          (APInt::floatToBits(0.5f) == Imm) || | ||||
|          (APInt::floatToBits(-0.5f) == Imm) || | ||||
|          (APInt::floatToBits(2.0f) == Imm) || | ||||
|          (APInt::floatToBits(-2.0f) == Imm) || | ||||
|          (APInt::floatToBits(4.0f) == Imm) || | ||||
|          (APInt::floatToBits(-4.0f) == Imm); | ||||
|   return (FloatToBits(0.0f) == Val) || | ||||
|          (FloatToBits(1.0f) == Val) || | ||||
|          (FloatToBits(-1.0f) == Val) || | ||||
|          (FloatToBits(0.5f) == Val) || | ||||
|          (FloatToBits(-0.5f) == Val) || | ||||
|          (FloatToBits(2.0f) == Val) || | ||||
|          (FloatToBits(-2.0f) == Val) || | ||||
|          (FloatToBits(4.0f) == Val) || | ||||
|          (FloatToBits(-4.0f) == Val); | ||||
| } | ||||
|  | ||||
| bool SIInstrInfo::isInlineConstant(const MachineOperand &MO) const { | ||||
|   | ||||
| @@ -188,6 +188,10 @@ class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{ | ||||
|   return isInlineImmediate(N); | ||||
| }]>; | ||||
|  | ||||
| class InlineFPImm <ValueType vt> : PatLeaf <(vt fpimm), [{ | ||||
|   return isInlineImmediate(N); | ||||
| }]>; | ||||
|  | ||||
| class SGPRImm <dag frag> : PatLeaf<frag, [{ | ||||
|   if (TM.getSubtarget<AMDGPUSubtarget>().getGeneration() < | ||||
|       AMDGPUSubtarget::SOUTHERN_ISLANDS) { | ||||
|   | ||||
| @@ -2572,6 +2572,11 @@ def : Pat < | ||||
|   (S_MOV_B64 (i64 (as_i64imm $imm))) | ||||
| >; | ||||
|  | ||||
| def : Pat < | ||||
|   (f64 InlineFPImm<f64>:$imm), | ||||
|   (S_MOV_B64 InlineFPImm<f64>:$imm) | ||||
| >; | ||||
|  | ||||
| /********** ===================== **********/ | ||||
| /********** Interpolation Paterns **********/ | ||||
| /********** ===================== **********/ | ||||
|   | ||||
| @@ -184,9 +184,9 @@ def SReg_32 : RegisterClass<"AMDGPU", [f32, i32], 32, | ||||
|   (add SGPR_32, M0Reg, VCC_LO, VCC_HI, EXEC_LO, EXEC_HI, FLAT_SCR_LO, FLAT_SCR_HI) | ||||
| >; | ||||
|  | ||||
| def SGPR_64 : RegisterClass<"AMDGPU", [v2i32, i64], 64, (add SGPR_64Regs)>; | ||||
| def SGPR_64 : RegisterClass<"AMDGPU", [v2i32, i64, f64], 64, (add SGPR_64Regs)>; | ||||
|  | ||||
| def SReg_64 : RegisterClass<"AMDGPU", [v2i32, i64, i1], 64, | ||||
| def SReg_64 : RegisterClass<"AMDGPU", [v2i32, i64, f64, i1], 64, | ||||
|   (add SGPR_64, VCCReg, EXECReg, FLAT_SCR) | ||||
| >; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user