From 44478fede52a42a662a7e259ff1c3a4067817018 Mon Sep 17 00:00:00 2001 From: Renato Golin Date: Thu, 12 May 2016 21:22:31 +0000 Subject: [PATCH] [ARM] Delay ARM constant pool creation. NFC. This change adds a new constant pool kind to ARMOperand. When parsing the operand for =immediate we create an instance of this operand rather than creating a constant pool entry and rewriting the operand. As the new operand kind is only created for ldr rt,= we can make ldr rt,= an explicit pseudo instruction in ARM, Thumb and Thumb2 The pseudo instruction is expanded in processInstruction(). This creates the constant pool and transforms the pseudo instruction into a pc-relative ldr to the constant pool. There are no functional changes and no modifications needed to existing tests. Required by the patch that fixes PR25722. Patch by Peter Smith. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269352 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrFormats.td | 9 ++++ lib/Target/ARM/ARMInstrInfo.td | 6 +++ lib/Target/ARM/ARMInstrThumb.td | 5 +++ lib/Target/ARM/ARMInstrThumb2.td | 5 +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 73 ++++++++++++++++++++++++++++--- 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index c56a2c7c8d1..0ef5e9f0ebd 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -246,6 +246,15 @@ def shr_imm64 : Operand, ImmLeaf 0 && Imm <= 64; }]> { let ParserMatchClass = shr_imm64_asm_operand; } + +// ARM Assembler operand for ldr Rd, =expression which generates an offset +// to a constant pool entry or a MOV depending on the value of expression +def const_pool_asm_operand : AsmOperandClass { let Name = "ConstPoolAsmImm"; } +def const_pool_asm_imm : Operand { + let ParserMatchClass = const_pool_asm_operand; +} + + //===----------------------------------------------------------------------===// // ARM Assembler alias templates. // diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 25472b5e1db..870f7fc5709 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2792,6 +2792,12 @@ def LDRBT_POST : ARMAsmPseudo<"ldrbt${q} $Rt, $addr", (ins addr_offset_none:$addr, pred:$q), (outs GPR:$Rt)>; +// Pseudo instruction ldr Rt, =immediate +def LDRConstPool + : ARMAsmPseudo<"ldr${q} $Rt, $immediate", + (ins const_pool_asm_imm:$immediate, pred:$q), + (outs GPR:$Rt)>; + // Store // Stores with truncate diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index b879707c0fd..8903d99128c 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -1543,3 +1543,8 @@ def : tInstAlias<"lsr${s}${p} $Rdm, $imm", (tLSRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; def : tInstAlias<"asr${s}${p} $Rdm, $imm", (tASRri tGPR:$Rdm, cc_out:$s, tGPR:$Rdm, imm_sr:$imm, pred:$p)>; + +// Pseudo instruction ldr Rt, =immediate +def tLDRConstPool + : tAsmPseudo<"ldr${p} $Rt, $immediate", + (ins tGPR:$Rt, const_pool_asm_imm:$immediate, pred:$p)>; diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index aff43f0dcfc..63ddcd9a889 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -4802,6 +4802,11 @@ def : t2InstAlias<"ldrsh${p}.w $Rt, $addr", def : t2InstAlias<"add${p} $Rd, pc, $imm", (t2ADR rGPR:$Rd, imm0_4095:$imm, pred:$p)>; +// Pseudo instruction ldr Rt, =immediate +def t2LDRConstPool + : t2AsmPseudo<"ldr${p} $Rt, $immediate", + (ins GPRnopc:$Rt, const_pool_asm_imm:$immediate, pred:$p)>; + // PLD/PLDW/PLI with alternate literal form. def : t2InstAlias<"pld${p} $addr", (t2PLDpci t2ldr_pcrel_imm12:$addr, pred:$p)>; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 1af898cf7e5..bb2628ef724 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -427,8 +427,9 @@ class ARMOperand : public MCParsedAsmOperand { k_ShifterImmediate, k_RotateImmediate, k_ModifiedImmediate, + k_ConstantPoolImmediate, k_BitfieldDescriptor, - k_Token + k_Token, } Kind; SMLoc StartLoc, EndLoc, AlignmentLoc; @@ -621,6 +622,11 @@ public: return Imm.Val; } + const MCExpr *getConstantPoolImm() const { + assert(isConstantPoolImm() && "Invalid access!"); + return Imm.Val; + } + unsigned getVectorIndex() const { assert(Kind == k_VectorIndex && "Invalid access!"); return VectorIndex.Val; @@ -658,7 +664,9 @@ public: bool isCCOut() const { return Kind == k_CCOut; } bool isITMask() const { return Kind == k_ITCondMask; } bool isITCondCode() const { return Kind == k_CondCode; } - bool isImm() const override { return Kind == k_Immediate; } + bool isImm() const override { + return Kind == k_Immediate; + } // checks whether this operand is an unsigned offset which fits is a field // of specified width and scaled by a specific number of bits template @@ -1046,6 +1054,7 @@ public: return ARM_AM::getSOImmVal(Value) == -1 && ARM_AM::getSOImmVal(-Value) != -1; } + bool isConstantPoolImm() const { return Kind == k_ConstantPoolImmediate; } bool isBitfield() const { return Kind == k_BitfieldDescriptor; } bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; } bool isPostIdxReg() const { @@ -1343,6 +1352,7 @@ public: // If we have an immediate that's not a constant, treat it as a label // reference needing a fixup. If it is a constant, it's something else // and we reject it. + if (isImm() && !isa(getImm())) return true; @@ -1353,6 +1363,11 @@ public: int64_t Val = Memory.OffsetImm->getValue(); return (Val > -4096 && Val < 4096) || (Val == INT32_MIN); } + bool isConstPoolAsmImm() const { + // Delay processing of Constant Pool Immediate, this will turn into + // a constant. Match no other operand + return (isConstantPoolImm()); + } bool isPostIdxImm8() const { if (!isImm()) return false; const MCConstantExpr *CE = dyn_cast(getImm()); @@ -1965,6 +1980,7 @@ public: } const MCSymbolRefExpr *SR = dyn_cast(Imm.Val); + assert(SR && "Unknown value type!"); Inst.addOperand(MCOperand::createExpr(SR)); return; @@ -2260,6 +2276,14 @@ public: Inst.addOperand(MCOperand::createImm(Val)); } + void addConstPoolAsmImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // This is container for the immediate that we will create the constant + // pool from + addExpr(Inst, getConstantPoolImm()); + return; + } + void addMemTBBOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum)); @@ -2640,6 +2664,15 @@ public: } static std::unique_ptr + CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) { + auto Op = make_unique(k_ConstantPoolImmediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static std::unique_ptr CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { auto Op = make_unique(k_BitfieldDescriptor); Op->Bitfield.LSB = LSB; @@ -2896,6 +2929,9 @@ void ARMOperand::print(raw_ostream &OS) const { OS << ""; break; + case k_ConstantPoolImmediate: + OS << ""; @@ -5217,10 +5253,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (getParser().parseExpression(SubExprVal)) return true; E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - - const MCExpr *CPLoc = - getTargetStreamer().addConstantPoolEntry(SubExprVal, S); - Operands.push_back(ARMOperand::CreateImm(CPLoc, S, E)); + Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); return false; } } @@ -6835,6 +6868,34 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, case ARM::t2LDRSHpcrel: Inst.setOpcode(ARM::t2LDRSHpci); return true; + case ARM::LDRConstPool: + case ARM::tLDRConstPool: + case ARM::t2LDRConstPool: { + // Handle the pseudo instruction for ldr rn,= + // For now we always create the constant pool entry and load from it + // FIXME: Use a MOV or MVN when the immediate will fit + MCInst TmpInst; + if (Inst.getOpcode() == ARM::LDRConstPool) + TmpInst.setOpcode(ARM::LDRi12); + else if (Inst.getOpcode() == ARM::tLDRConstPool) + TmpInst.setOpcode(ARM::tLDRpci); + else if (Inst.getOpcode() == ARM::t2LDRConstPool) + TmpInst.setOpcode(ARM::t2LDRpci); + const ARMOperand &PoolOperand = + static_cast(*Operands[3]); + const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm(); + const MCExpr *CPLoc = + getTargetStreamer().addConstantPoolEntry(SubExprVal, + PoolOperand.getStartLoc()); + TmpInst.addOperand(Inst.getOperand(0)); // Rt + TmpInst.addOperand(MCOperand::createExpr(CPLoc)); // offset to constpool + if (TmpInst.getOpcode() == ARM::LDRi12) + TmpInst.addOperand(MCOperand::createImm(0)); // unused offset + TmpInst.addOperand(Inst.getOperand(2)); // CondCode + TmpInst.addOperand(Inst.getOperand(3)); // CondCode + Inst = TmpInst; + return true; + } // Handle NEON VST complex aliases. case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_16: -- 2.11.0