From 481eaf3a10d059b99f32efe44bff0132d6c4a4d7 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault@amd.com>
Date: Fri, 23 Oct 2015 18:07:58 +0000
Subject: [PATCH] AMDGPU: Fix parsing of 32-bit literals with sign bit set

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251132 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp    |  4 +---
 .../AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp       |  9 +++++++--
 test/MC/AMDGPU/sop1-err.s                          |  9 +++++++++
 test/MC/AMDGPU/sop1.s                              | 14 ++++++++++++++
 4 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index ad50003213d..7a295168645 100644
--- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -987,13 +987,11 @@ AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
       int64_t IntVal;
       if (getParser().parseAbsoluteExpression(IntVal))
         return MatchOperand_ParseFail;
-      APInt IntVal32(32, IntVal);
-      if (IntVal32.getSExtValue() != IntVal) {
+      if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) {
         Error(S, "invalid immediate: only 32-bit values are legal");
         return MatchOperand_ParseFail;
       }
 
-      IntVal = IntVal32.getSExtValue();
       if (Negate)
         IntVal *= -1;
       Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S));
diff --git a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
index d64ac3f6265..870b632c306 100644
--- a/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
+++ b/lib/Target/AMDGPU/InstPrinter/AMDGPUInstPrinter.cpp
@@ -283,8 +283,13 @@ void AMDGPUInstPrinter::printImmediate64(uint64_t Imm, raw_ostream &O) {
     O << "4.0";
   else if (Imm == DoubleToBits(-4.0))
     O << "-4.0";
-  else
-    llvm_unreachable("64-bit literal constants not supported");
+  else {
+    assert(isUInt<32>(Imm));
+
+    // In rare situations, we will have a 32-bit literal in a 64-bit
+    // operand. This is technically allowed for the encoding of s_mov_b64.
+    O << formatHex(static_cast<uint64_t>(Imm));
+  }
 }
 
 void AMDGPUInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
diff --git a/test/MC/AMDGPU/sop1-err.s b/test/MC/AMDGPU/sop1-err.s
index f892356b623..c54b357791a 100644
--- a/test/MC/AMDGPU/sop1-err.s
+++ b/test/MC/AMDGPU/sop1-err.s
@@ -33,5 +33,14 @@ s_mov_b32 s1, 0xfffffffff
 s_mov_b64 s[0:1], 0xfffffffff
 // CHECK: error: invalid immediate: only 32-bit values are legal
 
+s_mov_b64 s[0:1], 0xfffffffff
+// CHECK: error: invalid immediate: only 32-bit values are legal
+
+s_mov_b64 s[0:1], 0xfffffffff
+// CHECK: error: invalid immediate: only 32-bit values are legal
+
+s_mov_b64 s[0:1], 0x0000000200000000
+// CHECK: error: invalid immediate: only 32-bit values are legal
+
 // Out of range register
 s_mov_b32 s
diff --git a/test/MC/AMDGPU/sop1.s b/test/MC/AMDGPU/sop1.s
index 92ca73f2500..a99bc9ab1cd 100644
--- a/test/MC/AMDGPU/sop1.s
+++ b/test/MC/AMDGPU/sop1.s
@@ -10,12 +10,26 @@ s_mov_b32 s1, 1
 s_mov_b32 s1, 100
 // CHECK: s_mov_b32 s1, 0x64 ; encoding: [0xff,0x03,0x81,0xbe,0x64,0x00,0x00,0x00]
 
+// Literal constant sign bit
+s_mov_b32 s1, 0x80000000
+// CHECK: s_mov_b32 s1, 0x80000000 ; encoding: [0xff,0x03,0x81,0xbe,0x00,0x00,0x00,0x80]
+
+// Negative 32-bit constant
+s_mov_b32 s0, 0xfe5163ab
+// CHECK: s_mov_b32 s0, 0xfe5163ab ; encoding: [0xff,0x03,0x80,0xbe,0xab,0x63,0x51,0xfe]
+
 s_mov_b64 s[2:3], s[4:5]
 // CHECK: s_mov_b64 s[2:3], s[4:5] ; encoding: [0x04,0x04,0x82,0xbe]
 
 s_mov_b64 s[2:3], 0xffffffffffffffff
 // CHECK: s_mov_b64 s[2:3], -1 ; encoding: [0xc1,0x04,0x82,0xbe]
 
+s_mov_b64 s[2:3], 0xffffffff
+// CHECK: s_mov_b64 s[2:3], 0xffffffff ; encoding: [0xff,0x04,0x82,0xbe,0xff,0xff,0xff,0xff]
+
+s_mov_b64 s[0:1], 0x80000000
+// CHECK: s_mov_b64 s[0:1], 0x80000000 ; encoding: [0xff,0x04,0x80,0xbe,0x00,0x00,0x00,0x80]
+
 s_cmov_b32 s1, 200
 // CHECK: s_cmov_b32 s1, 0xc8 ; encoding: [0xff,0x05,0x81,0xbe,0xc8,0x00,0x00,0x00]
 
-- 
2.40.0