[NVPTX] SHL.64 $r, 31 cannot be converted to a mulwide.s32
authorDmitry Vassiliev <dvassiliev@accesssoftek.com>
Wed, 24 Aug 2022 09:39:41 +0000 (11:39 +0200)
committerDmitry Vassiliev <dvassiliev@accesssoftek.com>
Wed, 24 Aug 2022 09:39:41 +0000 (11:39 +0200)
In order to convert to mulwide.s32, we compute the 2nd operand as MulWide.32 $r, (1 << 31).
(1 << 31) is interpreted as a negative number, and is not equivalent to the original instruction.
The code `int64_t r = (int64_t)a << 31;` incorrectly compiled to `mul.wide.s32 %rd7, %r1, -2147483648;`

Reviewed By: jchlanda

Differential Revision: https://reviews.llvm.org/D132516

llvm/lib/Target/NVPTX/NVPTXInstrInfo.td
llvm/test/CodeGen/NVPTX/mulwide.ll

index 6f9c40f..ecb363f 100644 (file)
@@ -731,16 +731,16 @@ def UInt16Const : PatLeaf<(imm), [{
   return v.isIntN(16);
 }]>;
 
-def Int5Const : PatLeaf<(imm), [{
-  // Check if 0 <= v < 32; only then will the result of (x << v) be an int32.
+def IntConst_0_30 : PatLeaf<(imm), [{
+  // Check if 0 <= v < 31; only then will the result of (x << v) be an int32.
   const APInt &v = N->getAPIntValue();
-  return v.sge(0) && v.slt(32);
+  return v.sge(0) && v.slt(31);
 }]>;
 
-def Int4Const : PatLeaf<(imm), [{
-  // Check if 0 <= v < 16; only then will the result of (x << v) be an int16.
+def IntConst_0_14 : PatLeaf<(imm), [{
+  // Check if 0 <= v < 15; only then will the result of (x << v) be an int16.
   const APInt &v = N->getAPIntValue();
-  return v.sge(0) && v.slt(16);
+  return v.sge(0) && v.slt(15);
 }]>;
 
 def SHL2MUL32 : SDNodeXForm<imm, [{
@@ -756,17 +756,17 @@ def SHL2MUL16 : SDNodeXForm<imm, [{
 }]>;
 
 // Convert "sign/zero-extend, then shift left by an immediate" to mul.wide.
-def : Pat<(shl (sext Int32Regs:$a), (i32 Int5Const:$b)),
+def : Pat<(shl (sext Int32Regs:$a), (i32 IntConst_0_30:$b)),
           (MULWIDES64Imm Int32Regs:$a, (SHL2MUL32 node:$b))>,
       Requires<[doMulWide]>;
-def : Pat<(shl (zext Int32Regs:$a), (i32 Int5Const:$b)),
+def : Pat<(shl (zext Int32Regs:$a), (i32 IntConst_0_30:$b)),
           (MULWIDEU64Imm Int32Regs:$a, (SHL2MUL32 node:$b))>,
       Requires<[doMulWide]>;
 
-def : Pat<(shl (sext Int16Regs:$a), (i16 Int4Const:$b)),
+def : Pat<(shl (sext Int16Regs:$a), (i16 IntConst_0_14:$b)),
           (MULWIDES32Imm Int16Regs:$a, (SHL2MUL16 node:$b))>,
       Requires<[doMulWide]>;
-def : Pat<(shl (zext Int16Regs:$a), (i16 Int4Const:$b)),
+def : Pat<(shl (zext Int16Regs:$a), (i16 IntConst_0_14:$b)),
           (MULWIDEU32Imm Int16Regs:$a, (SHL2MUL16 node:$b))>,
       Requires<[doMulWide]>;
 
index c420569..ff86708 100644 (file)
@@ -90,3 +90,23 @@ define i64 @mulwides7(i7 %a, i7 %b) {
   %val2 = mul i64 %val0, %val1
   ret i64 %val2
 }
+
+; OPT-LABEL: @shl30
+; NOOPT-LABEL: @shl30
+define i64 @shl30(i32 %a) {
+; OPT: mul.wide
+; NOOPT: shl.b64
+  %conv = sext i32 %a to i64
+  %shl = shl i64 %conv, 30
+  ret i64 %shl
+}
+
+; OPT-LABEL: @shl31
+; NOOPT-LABEL: @shl31
+define i64 @shl31(i32 %a) {
+; OPT-NOT: mul.wide
+; NOOPT-NOT: mul.wide
+  %conv = sext i32 %a to i64
+  %shl = shl i64 %conv, 31
+  ret i64 %shl
+}