[llvm] r283353 - [mips][ias] fix li macro when values are negated with ~

Simon Dardis via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 5 11:26:19 PDT 2016


Author: sdardis
Date: Wed Oct  5 13:26:19 2016
New Revision: 283353

URL: http://llvm.org/viewvc/llvm-project?rev=283353&view=rev
Log:
[mips][ias] fix li macro when values are negated with ~

The integrated assembler evaluates the expressions such as ~0x80000000 to
0xffffffff7fffffff early in the parsing process. This patch adds compatibility
with gas so that li loads the expected value (0x7fffffff) in those cases. This
only occurs iff all the upper 32bits are set and maintains existing checks by
not truncating the result down to 32 bits if any of the the upper bits are not
set.

Reviewers: dsanders, zoran.jovanovic

Differential Review: https://reviews.llvm.org/D23399

Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
    llvm/trunk/test/MC/Mips/macro-li-bad.s
    llvm/trunk/test/MC/Mips/macro-li.s

Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=283353&r1=283352&r2=283353&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Wed Oct  5 13:26:19 2016
@@ -995,7 +995,7 @@ public:
   void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     uint64_t Imm = getConstantImm() - Offset;
-    Imm &= (1 << Bits) - 1;
+    Imm &= (1ULL << Bits) - 1;
     Imm += Offset;
     Imm += AdjustOffset;
     Inst.addOperand(MCOperand::createImm(Imm));
@@ -1093,7 +1093,8 @@ public:
   bool isRegIdx() const { return Kind == k_RegisterIndex; }
   bool isImm() const override { return Kind == k_Immediate; }
   bool isConstantImm() const {
-    return isImm() && isa<MCConstantExpr>(getImm());
+    int64_t Res;
+    return isImm() && getImm()->evaluateAsAbsolute(Res);
   }
   bool isConstantImmz() const {
     return isConstantImm() && getConstantImm() == 0;
@@ -1264,7 +1265,9 @@ public:
 
   int64_t getConstantImm() const {
     const MCExpr *Val = getImm();
-    return static_cast<const MCConstantExpr *>(Val)->getValue();
+    int64_t Value = 0;
+    (void)Val->evaluateAsAbsolute(Value);
+    return Value;
   }
 
   MipsOperand *getMemBase() const {
@@ -4051,6 +4054,9 @@ bool MipsAsmParser::MatchAndEmitInstruct
   case Match_SImm32_Relaxed:
     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
                  "expected 32-bit signed immediate");
+  case Match_UImm32_Coerced:
+    return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+                 "expected 32-bit immediate");
   case Match_MemSImm9:
     return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
                  "expected memory with 9-bit signed offset");

Modified: llvm/trunk/lib/Target/Mips/MipsInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsInstrInfo.td?rev=283353&r1=283352&r2=283353&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsInstrInfo.td (original)
+++ llvm/trunk/lib/Target/Mips/MipsInstrInfo.td Wed Oct  5 13:26:19 2016
@@ -467,6 +467,16 @@ class UImmAsmOperandClass<int Bits, list
   let DiagnosticType = "UImm" # Bits;
 }
 
+// Generic case - only to support certain assembly pseudo instructions.
+class UImmAnyAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+    : AsmOperandClass {
+  let Name = "ImmAny";
+  let RenderMethod = "addConstantUImmOperands<32>";
+  let PredicateMethod = "isSImm<" # Bits # ">";
+  let SuperClasses = Supers;
+  let DiagnosticType = "ImmAny";
+}
+
 // AsmOperandClasses require a strict ordering which is difficult to manage
 // as a hierarchy. Instead, we use a linear ordering and impose an order that
 // is in some places arbitrary.
@@ -490,8 +500,13 @@ class UImmAsmOperandClass<int Bits, list
 //     uimm5 < uimm5_64, and uimm5 < vsplat_uimm5
 //   This is entirely arbitrary. We need an ordering and what we pick is
 //   unimportant since only one is possible for a given mnemonic.
+
+def UImm32CoercedAsmOperandClass : UImmAnyAsmOperandClass<33, []> {
+  let Name = "UImm32_Coerced";
+  let DiagnosticType = "UImm32_Coerced";
+}
 def SImm32RelaxedAsmOperandClass
-    : SImmAsmOperandClass<32, []> {
+    : SImmAsmOperandClass<32, [UImm32CoercedAsmOperandClass]> {
   let Name = "SImm32_Relaxed";
   let PredicateMethod = "isAnyImm<32>";
   let DiagnosticType = "SImm32_Relaxed";
@@ -515,6 +530,8 @@ def UImm16RelaxedAsmOperandClass
   let PredicateMethod = "isAnyImm<16>";
   let DiagnosticType = "UImm16_Relaxed";
 }
+// FIXME: One of these should probably have UImm16AsmOperandClass as the
+//        superclass instead of UImm16RelaxedasmOPerandClass.
 def UImm16AsmOperandClass
     : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
 def SImm16RelaxedAsmOperandClass
@@ -872,6 +889,10 @@ def simm16_64 : Operand<i64> {
   let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass");
 }
 
+// like simm32 but coerces simm32 to uimm32.
+def uimm32_coerced : Operand<i32> {
+  let ParserMatchClass = !cast<AsmOperandClass>("UImm32CoercedAsmOperandClass");
+}
 // Like simm32 but coerces uimm32 to simm32.
 def simm32_relaxed : Operand<i32> {
   let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>";
@@ -2387,11 +2408,12 @@ def : MipsInstAlias<"sync",
 // Assembler Pseudo Instructions
 //===----------------------------------------------------------------------===//
 
-// We use i32imm on li/la to defer range checking to the assembler.
+// We use uimm32_coerced to accept a 33 bit signed number that is rendered into
+// a 32 bit number.
 class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> :
   MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
                      !strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadImm32 : LoadImmediate32<"li", i32imm, GPR32Opnd>;
+def LoadImm32 : LoadImmediate32<"li", uimm32_coerced, GPR32Opnd>;
 
 class LoadAddressFromReg32<string instr_asm, Operand MemOpnd,
                            RegisterOperand RO> :

Modified: llvm/trunk/test/MC/Mips/macro-li-bad.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-li-bad.s?rev=283353&r1=283352&r2=283353&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-li-bad.s (original)
+++ llvm/trunk/test/MC/Mips/macro-li-bad.s Wed Oct  5 13:26:19 2016
@@ -7,5 +7,5 @@
 
   .text
   li $5, 0x100000000
-  # 32-BIT: :[[@LINE-1]]:3: error: instruction requires a 32-bit immediate
-  # 64-BIT: :[[@LINE-2]]:3: error: instruction requires a 32-bit immediate
+  # 32-BIT: :[[@LINE-1]]:10: error: expected 32-bit immediate
+  # 64-BIT: :[[@LINE-2]]:10: error: expected 32-bit immediate

Modified: llvm/trunk/test/MC/Mips/macro-li.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-li.s?rev=283353&r1=283352&r2=283353&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-li.s (original)
+++ llvm/trunk/test/MC/Mips/macro-li.s Wed Oct  5 13:26:19 2016
@@ -65,3 +65,11 @@ li $5, 0xc0008000 # CHECK: lui $5, 49152
                   # CHECK: ori $5, $5, 32768    # encoding: [0x34,0xa5,0x80,0x00]
 li $5, 0x80008000 # CHECK: lui $5, 32768        # encoding: [0x3c,0x05,0x80,0x00]
                   # CHECK: ori $5, $5, 32768    # encoding: [0x34,0xa5,0x80,0x00]
+li $4, ~0xffffffff # CHECK; addiu $4, $zero, 0  # encoding: [0x24,0x04,0x00,0x00]
+li $4, ~0x80000001 # CHECK: lui $4, 32767       # encoding: [0x3c,0x04,0x7f,0xff]
+                   # CHECK: ori $4, $4, 65534   # encoding: [0x34,0x84,0xff,0xfe]
+li $4, ~0x80000000 # CHECK: lui $4, 32767       # encoding: [0x3c,0x04,0x7f,0xff]
+                   # CHECK: ori $4, $4, 65535   # encoding: [0x34,0x84,0xff,0xff]
+li $4, ~0x7fffffff # CHECK: lui $4, 32768       # encoding: [0x3c,0x04,0x80,0x00]
+li $4, ~0x00000001 # CHECK: addiu $4, $zero, -2 # encoding: [0x24,0x04,0xff,0xfe]
+li $4, ~0x00000000 # CHECK: addiu $4, $zero, -1 # encoding: [0x24,0x04,0xff,0xff]




More information about the llvm-commits mailing list