1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

[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.

llvm-svn: 348067
This commit is contained in:
Alex Bradbury 2018-12-01 05:00:00 +00:00
parent 5f2bf664d6
commit 272fa58228
5 changed files with 198 additions and 88 deletions

View File

@ -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), (ins i32imm:$amt1, i32imm:$amt2),
/// 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, uimm5:$shamt), i32),
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

View File

@ -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

View File

@ -444,10 +444,13 @@ define signext i32 @subw(i32 signext %a, i32 signext %b) {
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, i32 zeroext %b) {
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, i32 zeroext %b) {
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:

View File

@ -624,12 +624,13 @@ define i32 @aext_sllw_zext_zext(i32 zeroext %a, i32 zeroext %b) nounwind {
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(i32 %a, i32 %b) nounwind {
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(i32 %a, i32 signext %b) nounwind {
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(i32 %a, i32 zeroext %b) nounwind {
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(i32 signext %a, i32 %b) nounwind {
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(i32 signext %a, i32 signext %b) nounwind
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(i32 signext %a, i32 zeroext %b) nounwind
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(i32 zeroext %a, i32 %b) nounwind {
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(i32 zeroext %a, i32 signext %b) nounwind
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(i32 zeroext %a, i32 zeroext %b) nounwind
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, i32 %b) nounwind {
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, i32 signext %b) nounwind {
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, i32 zeroext %b) nounwind {
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 signext %a, i32 %b) nounwind {
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 signext %a, i32 signext %b) nounwind {
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 signext %a, i32 zeroext %b) nounwind {
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 zeroext %a, i32 %b) nounwind {
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 zeroext %a, i32 signext %b) nounwind {
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 zeroext %a, i32 zeroext %b) nounwind {
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(i32 %a, i32 %b) nounwind {
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(i32 %a, i32 signext %b) nounwind {
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(i32 %a, i32 zeroext %b) nounwind {
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(i32 signext %a, i32 %b) nounwind {
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(i32 signext %a, i32 signext %b) nounwind
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(i32 signext %a, i32 zeroext %b) nounwind
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(i32 zeroext %a, i32 %b) nounwind {
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(i32 zeroext %a, i32 signext %b) nounwind
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(i32 zeroext %a, i32 zeroext %b) nounwind
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(i32 %a, i32 %b) nounwind {
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(i32 %a, i32 signext %b) nounwind {
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(i32 %a, i32 zeroext %b) nounwind {
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(i32 signext %a, i32 %b) nounwind {
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(i32 signext %a, i32 signext %b) nounwind
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(i32 signext %a, i32 zeroext %b) nounwind
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(i32 zeroext %a, i32 %b) nounwind {
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(i32 zeroext %a, i32 signext %b) nounwind
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(i32 zeroext %a, i32 zeroext %b) nounwind
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, i32 %b) nounwind {
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, i32 signext %b) nounwind {
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 signext %a, i32 zeroext %b) nounwind {
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 zeroext %a, i32 %b) nounwind {
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 zeroext %a, i32 signext %b) nounwind {
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 zeroext %a, i32 zeroext %b) nounwind {
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(i32 %a, i32 %b) nounwind {
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(i32 %a, i32 signext %b) nounwind {
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(i32 signext %a, i32 zeroext %b) nounwind
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(i32 zeroext %a, i32 %b) nounwind {
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(i32 zeroext %a, i32 signext %b) nounwind
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(i32 zeroext %a, i32 zeroext %b) nounwind
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(i32 %a, i32 %b) nounwind {
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(i32 %a, i32 signext %b) nounwind {
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(i32 signext %a, i32 zeroext %b) nounwind
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(i32 zeroext %a, i32 %b) nounwind {
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(i32 zeroext %a, i32 signext %b) nounwind
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

View File

@ -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
}