[llvm] r348067 - [RISCV] Remove RV64I SLLW/SRLW/SRAW patterns and add new test cases

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 30 21:00:01 PST 2018


Author: asb
Date: Fri Nov 30 21:00:00 2018
New Revision: 348067

URL: http://llvm.org/viewvc/llvm-project?rev=348067&view=rev
Log:
[RISCV] Remove RV64I SLLW/SRLW/SRAW patterns and add new test cases

As noted by Eli Friedman <https://reviews.llvm.org/D52977?id=168629#1315291>, 
the RV64I shift patterns for SLLW/SRLW/SRAW make some incorrect assumptions. 
SRAW assumed that (sext_inreg foo, i32) could only be produced when 
sign-extended an i32. However, it can be produced by input such as:

define i64 @tricky_ashr(i64 %a, i64 %b) {
  %1 = shl i64 %a, 32
  %2 = ashr i64 %1, 32
  %3 = ashr i64 %2, %b
  ret i64 %3
}

It's important not to select sraw in the above case, because sraw only uses 
bits lower 5 bits from the shift, while a shift of 32-63 would be valid.

Similarly, the patterns for srlw assumed (and foo, 0xffffffff) would only be 
produced when zero-extending a value that was originally i32 in LLVM IR. This
is obviously incorrect.

This patch removes the SLLW/SRLW/SRAW shift patterns for the time being and 
adds test cases that would demonstrate a miscompile if the incorrect patterns 
were re-added.

Added:
    llvm/trunk/test/CodeGen/RISCV/rv64i-tricky-shifts.ll
Modified:
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/trunk/test/CodeGen/RISCV/alu32.ll
    llvm/trunk/test/CodeGen/RISCV/alu64.ll
    llvm/trunk/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=348067&r1=348066&r2=348067&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Fri Nov 30 21:00:00 2018
@@ -211,9 +211,6 @@ def immbottomxlenset : ImmLeaf<XLenVT, [
     return countTrailingOnes<uint64_t>(Imm) >= 6;
   return countTrailingOnes<uint64_t>(Imm) >= 5;
 }]>;
-def immshifti32 : ImmLeaf<XLenVT, [{
-  return countTrailingOnes<uint64_t>(Imm) >= 5;
-}]>;
 
 // Addressing modes.
 // Necessary because a frameindex can't be matched directly in a pattern.
@@ -890,13 +887,6 @@ def ADJCALLSTACKUP   : Pseudo<(outs), (i
 
 /// RV64 patterns
 
-def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
-  return cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32;
-}]>;
-def zexti32 : PatFrags<(ops node:$src),
-                       [(and node:$src, 0xffffffff),
-                        (assertzexti32 node:$src)]>;
-
 let Predicates = [IsRV64] in {
 
 /// sext and zext
@@ -919,22 +909,7 @@ def : Pat<(sext_inreg (shl GPR:$rs1, uim
 def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
           (SRAIW GPR:$rs1, uimm5:$shamt)>;
 
-def : Pat<(sext_inreg (shl GPR:$rs1, GPR:$rs2), i32),
-          (SLLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(sext_inreg (shl GPR:$rs1, (and GPR:$rs2, immshifti32)), i32),
-          (SLLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(srl (zexti32 GPR:$rs1), GPR:$rs2),
-          (SRLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(srl (zexti32 GPR:$rs1), (and GPR:$rs2, immshifti32)),
-          (SRLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(sext_inreg (srl (zexti32 GPR:$rs1), GPR:$rs2), i32),
-          (SRLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(sext_inreg (srl (zexti32 GPR:$rs1), (and GPR:$rs2, immshifti32)), i32),
-          (SRLW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(sra (sext_inreg GPR:$rs1, i32), GPR:$rs2),
-          (SRAW GPR:$rs1, GPR:$rs2)>;
-def : Pat<(sra (sext_inreg GPR:$rs1, i32), (and GPR:$rs2, immshifti32)),
-          (SRAW GPR:$rs1, GPR:$rs2)>;
+// TODO: patterns for SLLW/SRLW/SRAW.
 
 /// Loads
 

Modified: llvm/trunk/test/CodeGen/RISCV/alu32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/alu32.ll?rev=348067&r1=348066&r2=348067&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/alu32.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/alu32.ll Fri Nov 30 21:00:00 2018
@@ -235,6 +235,8 @@ define i32 @xor(i32 %a, i32 %b) nounwind
   ret i32 %1
 }
 
+; TODO: should select srlw for RV64.
+
 define i32 @srl(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: srl:
 ; RV32I:       # %bb.0:
@@ -243,12 +245,16 @@ define i32 @srl(i32 %a, i32 %b) nounwind
 ;
 ; RV64I-LABEL: srl:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
 }
 
+; TODO: should select sraw for RV64.
+
 define i32 @sra(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: sra:
 ; RV32I:       # %bb.0:
@@ -257,7 +263,8 @@ define i32 @sra(i32 %a, i32 %b) nounwind
 ;
 ; RV64I-LABEL: sra:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1

Modified: llvm/trunk/test/CodeGen/RISCV/alu64.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/alu64.ll?rev=348067&r1=348066&r2=348067&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/alu64.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/alu64.ll Fri Nov 30 21:00:00 2018
@@ -444,10 +444,13 @@ define signext i32 @subw(i32 signext %a,
   ret i32 %1
 }
 
+; TODO: should select sllw for RV64.
+
 define signext i32 @sllw(i32 signext %a, i32 zeroext %b) {
 ; RV64I-LABEL: sllw:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
 ;
 ; RV32I-LABEL: sllw:
@@ -458,10 +461,15 @@ define signext i32 @sllw(i32 signext %a,
   ret i32 %1
 }
 
+; TODO: should select srlw for RV64.
+
 define signext i32 @srlw(i32 signext %a, i32 zeroext %b) {
 ; RV64I-LABEL: srlw:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
 ;
 ; RV32I-LABEL: srlw:
@@ -472,10 +480,13 @@ define signext i32 @srlw(i32 signext %a,
   ret i32 %1
 }
 
+; TODO: should select sraw for RV64.
+
 define signext i32 @sraw(i64 %a, i32 zeroext %b) {
 ; RV64I-LABEL: sraw:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV32I-LABEL: sraw:

Modified: llvm/trunk/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll?rev=348067&r1=348066&r2=348067&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll Fri Nov 30 21:00:00 2018
@@ -624,12 +624,13 @@ define i32 @aext_sllw_zext_zext(i32 zero
   ret i32 %1
 }
 
-; Select sllw for all cases witha signext result.
+; TODO: Select sllw for all cases witha signext result.
 
 define signext i32 @sext_sllw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_sllw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -638,7 +639,8 @@ define signext i32 @sext_sllw_aext_aext(
 define signext i32 @sext_sllw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -647,7 +649,8 @@ define signext i32 @sext_sllw_aext_sext(
 define signext i32 @sext_sllw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -656,7 +659,8 @@ define signext i32 @sext_sllw_aext_zext(
 define signext i32 @sext_sllw_sext_aext(i32 signext %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_sllw_sext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -665,7 +669,8 @@ define signext i32 @sext_sllw_sext_aext(
 define signext i32 @sext_sllw_sext_sext(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_sext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -674,7 +679,8 @@ define signext i32 @sext_sllw_sext_sext(
 define signext i32 @sext_sllw_sext_zext(i32 signext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_sext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -683,7 +689,8 @@ define signext i32 @sext_sllw_sext_zext(
 define signext i32 @sext_sllw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_sllw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -692,7 +699,8 @@ define signext i32 @sext_sllw_zext_aext(
 define signext i32 @sext_sllw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -701,7 +709,8 @@ define signext i32 @sext_sllw_zext_sext(
 define signext i32 @sext_sllw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_sllw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sllw a0, a0, a1
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = shl i32 %a, %b
   ret i32 %1
@@ -808,12 +817,14 @@ define zeroext i32 @zext_sllw_zext_zext(
   ret i32 %1
 }
 
-; srlw must always be selected for 32-bit lshr with variable arguments.
+; TODO: srlw should be selected for 32-bit lshr with variable arguments.
 
 define i32 @aext_srlw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: aext_srlw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -822,7 +833,9 @@ define i32 @aext_srlw_aext_aext(i32 %a,
 define i32 @aext_srlw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -831,7 +844,9 @@ define i32 @aext_srlw_aext_sext(i32 %a,
 define i32 @aext_srlw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -840,7 +855,9 @@ define i32 @aext_srlw_aext_zext(i32 %a,
 define i32 @aext_srlw_sext_aext(i32 signext %a, i32 %b) nounwind {
 ; RV64I-LABEL: aext_srlw_sext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -849,7 +866,9 @@ define i32 @aext_srlw_sext_aext(i32 sign
 define i32 @aext_srlw_sext_sext(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_sext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -858,7 +877,9 @@ define i32 @aext_srlw_sext_sext(i32 sign
 define i32 @aext_srlw_sext_zext(i32 signext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_sext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -867,7 +888,7 @@ define i32 @aext_srlw_sext_zext(i32 sign
 define i32 @aext_srlw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: aext_srlw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -876,7 +897,7 @@ define i32 @aext_srlw_zext_aext(i32 zero
 define i32 @aext_srlw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -885,7 +906,7 @@ define i32 @aext_srlw_zext_sext(i32 zero
 define i32 @aext_srlw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: aext_srlw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -894,7 +915,10 @@ define i32 @aext_srlw_zext_zext(i32 zero
 define signext i32 @sext_srlw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_srlw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -903,7 +927,10 @@ define signext i32 @sext_srlw_aext_aext(
 define signext i32 @sext_srlw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -912,7 +939,10 @@ define signext i32 @sext_srlw_aext_sext(
 define signext i32 @sext_srlw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -921,7 +951,10 @@ define signext i32 @sext_srlw_aext_zext(
 define signext i32 @sext_srlw_sext_aext(i32 signext %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_srlw_sext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -930,7 +963,10 @@ define signext i32 @sext_srlw_sext_aext(
 define signext i32 @sext_srlw_sext_sext(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_sext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -939,7 +975,10 @@ define signext i32 @sext_srlw_sext_sext(
 define signext i32 @sext_srlw_sext_zext(i32 signext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_sext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -948,7 +987,8 @@ define signext i32 @sext_srlw_sext_zext(
 define signext i32 @sext_srlw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_srlw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -957,7 +997,8 @@ define signext i32 @sext_srlw_zext_aext(
 define signext i32 @sext_srlw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -966,7 +1007,8 @@ define signext i32 @sext_srlw_zext_sext(
 define signext i32 @sext_srlw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_srlw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    ret
   %1 = lshr i32 %a, %b
   ret i32 %1
@@ -975,7 +1017,9 @@ define signext i32 @sext_srlw_zext_zext(
 define zeroext i32 @zext_srlw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: zext_srlw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -986,7 +1030,9 @@ define zeroext i32 @zext_srlw_aext_aext(
 define zeroext i32 @zext_srlw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -997,7 +1043,9 @@ define zeroext i32 @zext_srlw_aext_sext(
 define zeroext i32 @zext_srlw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1008,7 +1056,9 @@ define zeroext i32 @zext_srlw_aext_zext(
 define zeroext i32 @zext_srlw_sext_aext(i32 signext %a, i32 %b) nounwind {
 ; RV64I-LABEL: zext_srlw_sext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1019,7 +1069,9 @@ define zeroext i32 @zext_srlw_sext_aext(
 define zeroext i32 @zext_srlw_sext_sext(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_sext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1030,7 +1082,9 @@ define zeroext i32 @zext_srlw_sext_sext(
 define zeroext i32 @zext_srlw_sext_zext(i32 signext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_sext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1041,7 +1095,7 @@ define zeroext i32 @zext_srlw_sext_zext(
 define zeroext i32 @zext_srlw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: zext_srlw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1052,7 +1106,7 @@ define zeroext i32 @zext_srlw_zext_aext(
 define zeroext i32 @zext_srlw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1063,7 +1117,7 @@ define zeroext i32 @zext_srlw_zext_sext(
 define zeroext i32 @zext_srlw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: zext_srlw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srlw a0, a0, a1
+; RV64I-NEXT:    srl a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1071,12 +1125,14 @@ define zeroext i32 @zext_srlw_zext_zext(
   ret i32 %1
 }
 
-; sraw must be selected if the first operand is not sign-extended.
+; TODO: sraw should be selected if the first operand is not sign-extended. If the
+; first operand is sign-extended, sra is equivalent for the test cases below.
 
 define i32 @aext_sraw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: aext_sraw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1085,7 +1141,8 @@ define i32 @aext_sraw_aext_aext(i32 %a,
 define i32 @aext_sraw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: aext_sraw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1094,7 +1151,8 @@ define i32 @aext_sraw_aext_sext(i32 %a,
 define i32 @aext_sraw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: aext_sraw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1130,7 +1188,8 @@ define i32 @aext_sraw_sext_zext(i32 sign
 define i32 @aext_sraw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: aext_sraw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1139,7 +1198,8 @@ define i32 @aext_sraw_zext_aext(i32 zero
 define i32 @aext_sraw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: aext_sraw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1148,7 +1208,8 @@ define i32 @aext_sraw_zext_sext(i32 zero
 define i32 @aext_sraw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: aext_sraw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1157,7 +1218,8 @@ define i32 @aext_sraw_zext_zext(i32 zero
 define signext i32 @sext_sraw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_sraw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1166,7 +1228,8 @@ define signext i32 @sext_sraw_aext_aext(
 define signext i32 @sext_sraw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_sraw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1175,7 +1238,8 @@ define signext i32 @sext_sraw_aext_sext(
 define signext i32 @sext_sraw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_sraw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1211,7 +1275,8 @@ define signext i32 @sext_sraw_sext_zext(
 define signext i32 @sext_sraw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: sext_sraw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1220,7 +1285,8 @@ define signext i32 @sext_sraw_zext_aext(
 define signext i32 @sext_sraw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: sext_sraw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1229,7 +1295,8 @@ define signext i32 @sext_sraw_zext_sext(
 define signext i32 @sext_sraw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: sext_sraw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    ret
   %1 = ashr i32 %a, %b
   ret i32 %1
@@ -1238,7 +1305,8 @@ define signext i32 @sext_sraw_zext_zext(
 define zeroext i32 @zext_sraw_aext_aext(i32 %a, i32 %b) nounwind {
 ; RV64I-LABEL: zext_sraw_aext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1249,7 +1317,8 @@ define zeroext i32 @zext_sraw_aext_aext(
 define zeroext i32 @zext_sraw_aext_sext(i32 %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: zext_sraw_aext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1260,7 +1329,8 @@ define zeroext i32 @zext_sraw_aext_sext(
 define zeroext i32 @zext_sraw_aext_zext(i32 %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: zext_sraw_aext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1304,7 +1374,8 @@ define zeroext i32 @zext_sraw_sext_zext(
 define zeroext i32 @zext_sraw_zext_aext(i32 zeroext %a, i32 %b) nounwind {
 ; RV64I-LABEL: zext_sraw_zext_aext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1315,7 +1386,8 @@ define zeroext i32 @zext_sraw_zext_aext(
 define zeroext i32 @zext_sraw_zext_sext(i32 zeroext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: zext_sraw_zext_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret
@@ -1326,7 +1398,8 @@ define zeroext i32 @zext_sraw_zext_sext(
 define zeroext i32 @zext_sraw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
 ; RV64I-LABEL: zext_sraw_zext_zext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sraw a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli a0, a0, 32
 ; RV64I-NEXT:    ret

Added: llvm/trunk/test/CodeGen/RISCV/rv64i-tricky-shifts.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/rv64i-tricky-shifts.ll?rev=348067&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/rv64i-tricky-shifts.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/rv64i-tricky-shifts.ll Fri Nov 30 21:00:00 2018
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64I
+
+; These tests must not compile to sllw/srlw/sraw, as this would be semantically
+; incorrect in the case that %b holds a value between 32 and 63. Selection
+; patterns might make the mistake of assuming that a (sext_inreg foo, i32) can
+; only be produced when sign-extending an i32 type.
+
+define i64 @tricky_shl(i64 %a, i64 %b) {
+; RV64I-LABEL: tricky_shl:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    sll a0, a0, a1
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    ret
+  %1 = shl i64 %a, %b
+  %2 = shl i64 %1, 32
+  %3 = ashr i64 %2, 32
+  ret i64 %3
+}
+
+define i64 @tricky_lshr(i64 %a, i64 %b) {
+; RV64I-LABEL: tricky_lshr:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 32
+; RV64I-NEXT:    srl a0, a0, a1
+; RV64I-NEXT:    ret
+  %1 = and i64 %a, 4294967295
+  %2 = lshr i64 %1, %b
+  ret i64 %2
+}
+
+define i64 @tricky_ashr(i64 %a, i64 %b) {
+; RV64I-LABEL: tricky_ashr:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sra a0, a0, a1
+; RV64I-NEXT:    ret
+  %1 = shl i64 %a, 32
+  %2 = ashr i64 %1, 32
+  %3 = ashr i64 %2, %b
+  ret i64 %3
+}




More information about the llvm-commits mailing list