[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