[llvm] r344432 - [RISCV] Eliminate unnecessary masking of promoted shift amounts

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 12 16:18:52 PDT 2018


Author: asb
Date: Fri Oct 12 16:18:52 2018
New Revision: 344432

URL: http://llvm.org/viewvc/llvm-project?rev=344432&view=rev
Log:
[RISCV] Eliminate unnecessary masking of promoted shift amounts

SelectionDAGBuilder::visitShift will always zero-extend a shift amount when it
is promoted to the ShiftAmountTy. This results in zero-extension (masking)
which is unnecessary for RISC-V as the shift operations only read the lower 5
or 6 bits (RV32 or RV64).

I initially proposed adding a getExtendForShiftAmount hook so the shift amount
can be any-extended (D52975). @efriedma explained this was unsafe, so I have
instead eliminate the unnecessary and operations at instruction selection time
in a manner similar to X86InstrCompiler.td.

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


Added:
    llvm/trunk/test/CodeGen/RISCV/shift-masked-shamt.ll
Modified:
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/trunk/test/CodeGen/RISCV/alu16.ll
    llvm/trunk/test/CodeGen/RISCV/alu8.ll

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=344432&r1=344431&r2=344432&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Fri Oct 12 16:18:52 2018
@@ -205,6 +205,12 @@ def ixlenimm : Operand<XLenVT> {
 // Standalone (codegen-only) immleaf patterns.
 def simm32     : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
 def simm32hi20 : ImmLeaf<XLenVT, [{return isShiftedInt<20, 12>(Imm);}]>;
+// A mask value that won't affect significant shift bits.
+def immshiftxlen : ImmLeaf<XLenVT, [{
+  if (Subtarget->is64Bit())
+    return countTrailingOnes<uint64_t>(Imm) >= 6;
+  return countTrailingOnes<uint64_t>(Imm) >= 5;
+}]>;
 
 // Addressing modes.
 // Necessary because a frameindex can't be matched directly in a pattern.
@@ -646,13 +652,24 @@ def : PatGprGpr<and, AND>;
 def : PatGprSimm12<and, ANDI>;
 def : PatGprGpr<xor, XOR>;
 def : PatGprSimm12<xor, XORI>;
-def : PatGprGpr<shl, SLL>;
 def : PatGprUimmLog2XLen<shl, SLLI>;
-def : PatGprGpr<srl, SRL>;
 def : PatGprUimmLog2XLen<srl, SRLI>;
-def : PatGprGpr<sra, SRA>;
 def : PatGprUimmLog2XLen<sra, SRAI>;
 
+// Match both a plain shift and one where the shift amount is masked (this is
+// typically introduced when the legalizer promotes the shift amount and
+// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
+// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
+multiclass VarShiftXLenPat<PatFrag ShiftOp, RVInst Inst> {
+  def : Pat<(ShiftOp GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>;
+  def : Pat<(ShiftOp GPR:$rs1, (and GPR:$rs2, immshiftxlen)),
+            (Inst GPR:$rs1, GPR:$rs2)>;
+}
+
+defm : VarShiftXLenPat<shl, SLL>;
+defm : VarShiftXLenPat<srl, SRL>;
+defm : VarShiftXLenPat<sra, SRA>;
+
 /// FrameIndex calculations
 
 def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),

Modified: llvm/trunk/test/CodeGen/RISCV/alu16.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/alu16.ll?rev=344432&r1=344431&r2=344432&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/alu16.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/alu16.ll Fri Oct 12 16:18:52 2018
@@ -6,8 +6,6 @@
 ; that legalisation of these non-native types doesn't introduce unnecessary
 ; inefficiencies.
 
-; TODO: it's unnecessary to mask (zero-extend) the shift amount.
-
 define i16 @addi(i16 %a) nounwind {
 ; RV32I-LABEL: addi:
 ; RV32I:       # %bb.0:
@@ -122,9 +120,6 @@ define i16 @sub(i16 %a, i16 %b) nounwind
 define i16 @sll(i16 %a, i16 %b) nounwind {
 ; RV32I-LABEL: sll:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    lui a2, 16
-; RV32I-NEXT:    addi a2, a2, -1
-; RV32I-NEXT:    and a1, a1, a2
 ; RV32I-NEXT:    sll a0, a0, a1
 ; RV32I-NEXT:    ret
   %1 = shl i16 %a, %b
@@ -173,7 +168,6 @@ define i16 @srl(i16 %a, i16 %b) nounwind
 ; RV32I:       # %bb.0:
 ; RV32I-NEXT:    lui a2, 16
 ; RV32I-NEXT:    addi a2, a2, -1
-; RV32I-NEXT:    and a1, a1, a2
 ; RV32I-NEXT:    and a0, a0, a2
 ; RV32I-NEXT:    srl a0, a0, a1
 ; RV32I-NEXT:    ret
@@ -184,9 +178,6 @@ define i16 @srl(i16 %a, i16 %b) nounwind
 define i16 @sra(i16 %a, i16 %b) nounwind {
 ; RV32I-LABEL: sra:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    lui a2, 16
-; RV32I-NEXT:    addi a2, a2, -1
-; RV32I-NEXT:    and a1, a1, a2
 ; RV32I-NEXT:    slli a0, a0, 16
 ; RV32I-NEXT:    srai a0, a0, 16
 ; RV32I-NEXT:    sra a0, a0, a1

Modified: llvm/trunk/test/CodeGen/RISCV/alu8.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/alu8.ll?rev=344432&r1=344431&r2=344432&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/alu8.ll (original)
+++ llvm/trunk/test/CodeGen/RISCV/alu8.ll Fri Oct 12 16:18:52 2018
@@ -6,8 +6,6 @@
 ; that legalisation of these non-native types doesn't introduce unnecessary
 ; inefficiencies.
 
-; TODO: it's unnecessary to mask (zero-extend) the shift amount.
-
 define i8 @addi(i8 %a) nounwind {
 ; RV32I-LABEL: addi:
 ; RV32I:       # %bb.0:
@@ -118,7 +116,6 @@ define i8 @sub(i8 %a, i8 %b) nounwind {
 define i8 @sll(i8 %a, i8 %b) nounwind {
 ; RV32I-LABEL: sll:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    andi a1, a1, 255
 ; RV32I-NEXT:    sll a0, a0, a1
 ; RV32I-NEXT:    ret
   %1 = shl i8 %a, %b
@@ -163,7 +160,6 @@ define i8 @xor(i8 %a, i8 %b) nounwind {
 define i8 @srl(i8 %a, i8 %b) nounwind {
 ; RV32I-LABEL: srl:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    andi a1, a1, 255
 ; RV32I-NEXT:    andi a0, a0, 255
 ; RV32I-NEXT:    srl a0, a0, a1
 ; RV32I-NEXT:    ret
@@ -174,7 +170,6 @@ define i8 @srl(i8 %a, i8 %b) nounwind {
 define i8 @sra(i8 %a, i8 %b) nounwind {
 ; RV32I-LABEL: sra:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    andi a1, a1, 255
 ; RV32I-NEXT:    slli a0, a0, 24
 ; RV32I-NEXT:    srai a0, a0, 24
 ; RV32I-NEXT:    sra a0, a0, a1

Added: llvm/trunk/test/CodeGen/RISCV/shift-masked-shamt.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/shift-masked-shamt.ll?rev=344432&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/shift-masked-shamt.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/shift-masked-shamt.ll Fri Oct 12 16:18:52 2018
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32I
+
+; This test checks that unnecessary masking of shift amount operands is
+; eliminated during instruction selection. The test needs to ensure that the
+; masking is not removed if it may affect the shift amount.
+
+define i32 @sll_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sll_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    sll a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 31
+  %2 = shl i32 %a, %1
+  ret i32 %2
+}
+
+define i32 @sll_non_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sll_non_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a1, a1, 15
+; RV32I-NEXT:    sll a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 15
+  %2 = shl i32 %a, %1
+  ret i32 %2
+}
+
+define i32 @srl_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: srl_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srl a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 4095
+  %2 = lshr i32 %a, %1
+  ret i32 %2
+}
+
+define i32 @srl_non_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: srl_non_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a1, a1, 7
+; RV32I-NEXT:    srl a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 7
+  %2 = lshr i32 %a, %1
+  ret i32 %2
+}
+
+define i32 @sra_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sra_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    sra a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 65535
+  %2 = ashr i32 %a, %1
+  ret i32 %2
+}
+
+define i32 @sra_non_redundant_mask(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: sra_non_redundant_mask:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a1, a1, 32
+; RV32I-NEXT:    sra a0, a0, a1
+; RV32I-NEXT:    ret
+  %1 = and i32 %b, 32
+  %2 = ashr i32 %a, %1
+  ret i32 %2
+}




More information about the llvm-commits mailing list