[llvm] 00eff96 - [RISCV] Add missing patterns for rotr with immediate for Zbb/Zbp extensions.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 3 10:05:46 PST 2020
Author: Craig Topper
Date: 2020-11-03T10:04:52-08:00
New Revision: 00eff96e1d02969ff1c1416a266b4d29506cd1c0
URL: https://github.com/llvm/llvm-project/commit/00eff96e1d02969ff1c1416a266b4d29506cd1c0
DIFF: https://github.com/llvm/llvm-project/commit/00eff96e1d02969ff1c1416a266b4d29506cd1c0.diff
LOG: [RISCV] Add missing patterns for rotr with immediate for Zbb/Zbp extensions.
DAGCombine doesn't canonicalize rotl/rotr with immediate so we
need patterns for both.
Remove the custom matcher for rotl to RORI and just use a SDNodeXForm
to convert the immediate instead. Doing this gives priority to the
rev32/rev16 versions of grevi over rori since an explicit immediate
is more precise than any immediate. I also added rotr patterns for
rev32/rev16. And removed the (or (shl), (shr)) patterns that should be
combined to rotl by DAG combine.
There is at least one other grev pattern that probably needs a
another rotr pattern, but we need more test coverage first.
Differential Revision: https://reviews.llvm.org/D90575
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
llvm/lib/Target/RISCV/RISCVInstrInfoB.td
llvm/test/CodeGen/RISCV/rv32Zbbp.ll
llvm/test/CodeGen/RISCV/rv32Zbp.ll
llvm/test/CodeGen/RISCV/rv64Zbbp.ll
llvm/test/CodeGen/RISCV/rv64Zbp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index ca21c005ad4d..641018703e35 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -284,44 +284,6 @@ bool RISCVDAGToDAGISel::SelectSROI(SDValue N, SDValue &RS1, SDValue &Shamt) {
return false;
}
-// Check that it is a RORI (Rotate Right Immediate). We first check that
-// it is the right node tree:
-//
-// (ROTL RS1, VC)
-//
-// The compiler translates immediate rotations to the right given by the call
-// to the rotateright32/rotateright64 intrinsics as rotations to the left.
-// Since the rotation to the left can be easily emulated as a rotation to the
-// right by negating the constant, there is no encoding for ROLI.
-// We then select the immediate left rotations as RORI by the complementary
-// constant:
-//
-// Shamt == XLen - VC
-
-bool RISCVDAGToDAGISel::SelectRORI(SDValue N, SDValue &RS1, SDValue &Shamt) {
- MVT XLenVT = Subtarget->getXLenVT();
- if (N.getOpcode() == ISD::ROTL) {
- if (isa<ConstantSDNode>(N.getOperand(1))) {
- if (XLenVT == MVT::i64) {
- uint64_t VC = N.getConstantOperandVal(1);
- Shamt = CurDAG->getTargetConstant((64 - VC), SDLoc(N),
- N.getOperand(1).getValueType());
- RS1 = N.getOperand(0);
- return true;
- }
- if (XLenVT == MVT::i32) {
- uint32_t VC = N.getConstantOperandVal(1);
- Shamt = CurDAG->getTargetConstant((32 - VC), SDLoc(N),
- N.getOperand(1).getValueType());
- RS1 = N.getOperand(0);
- return true;
- }
- }
- }
- return false;
-}
-
-
// Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
// on RV64).
// SLLIUW is the same as SLLI except for the fact that it clears the bits
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
index bc1655b673d7..10096c39cdbe 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
@@ -47,7 +47,6 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
bool SelectSLOI(SDValue N, SDValue &RS1, SDValue &Shamt);
bool SelectSROI(SDValue N, SDValue &RS1, SDValue &Shamt);
- bool SelectRORI(SDValue N, SDValue &RS1, SDValue &Shamt);
bool SelectSLLIUW(SDValue N, SDValue &RS1, SDValue &Shamt);
bool SelectSLOIW(SDValue N, SDValue &RS1, SDValue &Shamt);
bool SelectSROIW(SDValue N, SDValue &RS1, SDValue &Shamt);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
index aecb429fdd15..dc9baf3f12eb 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td
@@ -46,6 +46,14 @@ def ImmSub32 : SDNodeXForm<imm, [{
N->getValueType(0));
}]>;
+
+// Convert rotl immediate to a rotr immediate.
+def ImmROTL2R : SDNodeXForm<imm, [{
+ uint64_t XLen = Subtarget->getXLen();
+ return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
+ N->getValueType(0));
+}]>;
+
//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
@@ -644,7 +652,6 @@ def : CompressPat<(PACK GPRC:$rs1, GPRC:$rs1, X0),
//===----------------------------------------------------------------------===//
def SLOIPat : ComplexPattern<XLenVT, 2, "SelectSLOI", [or]>;
def SROIPat : ComplexPattern<XLenVT, 2, "SelectSROI", [or]>;
-def RORIPat : ComplexPattern<XLenVT, 2, "SelectRORI", [rotl]>;
def SLLIUWPat : ComplexPattern<i64, 2, "SelectSLLIUW", [and]>;
def SLOIWPat : ComplexPattern<i64, 2, "SelectSLOIW", [sext_inreg]>;
def SROIWPat : ComplexPattern<i64, 2, "SelectSROIW", [or]>;
@@ -709,10 +716,12 @@ def : Pat<(SROIPat GPR:$rs1, uimmlog2xlen:$shamt),
// There's no encoding for roli in the current version of the 'B' extension
// (v0.92) as it can be implemented with rori by negating the immediate.
-// For this reason we pattern-match only against rori[w].
-let Predicates = [HasStdExtZbbOrZbp] in
-def : Pat<(RORIPat GPR:$rs1, uimmlog2xlen:$shamt),
+let Predicates = [HasStdExtZbbOrZbp] in {
+def : Pat<(rotr GPR:$rs1, uimmlog2xlen:$shamt),
(RORI GPR:$rs1, uimmlog2xlen:$shamt)>;
+def : Pat<(rotl GPR:$rs1, uimmlog2xlen:$shamt),
+ (RORI GPR:$rs1, (ImmROTL2R uimmlog2xlen:$shamt))>;
+}
// We don't pattern-match sbclri[w], sbseti[w], sbinvi[w] because they are
// pattern-matched by simple andi, ori, and xori.
@@ -778,9 +787,9 @@ def : Pat<(or (and (shl GPR:$rs1, (i32 8)), (i32 0xFF00FF00)),
(and (srl GPR:$rs1, (i32 8)), (i32 0x00FF00FF))),
(GREVI GPR:$rs1, (i32 8))>;
def : Pat<(rotr (bswap GPR:$rs1), (i32 16)), (GREVI GPR:$rs1, (i32 8))>;
-def : Pat<(or (shl GPR:$rs1, (i32 16)), (srl GPR:$rs1, (i32 16))),
- (GREVI GPR:$rs1, (i32 16))>;
+// FIXME: Is grev better than rori?
def : Pat<(rotl GPR:$rs1, (i32 16)), (GREVI GPR:$rs1, (i32 16))>;
+def : Pat<(rotr GPR:$rs1, (i32 16)), (GREVI GPR:$rs1, (i32 16))>;
def : Pat<(bswap GPR:$rs1), (GREVI GPR:$rs1, (i32 24))>;
def : Pat<(bitreverse GPR:$rs1), (GREVI GPR:$rs1, (i32 31))>;
} // Predicates = [HasStdExtZbp, IsRV32]
@@ -801,9 +810,9 @@ def : Pat<(or (and (shl GPR:$rs1, (i64 8)), (i64 0xFF00FF00FF00FF00)),
def : Pat<(or (and (shl GPR:$rs1, (i64 16)), (i64 0xFFFF0000FFFF0000)),
(and (srl GPR:$rs1, (i64 16)), (i64 0x0000FFFF0000FFFF))),
(GREVI GPR:$rs1, (i64 16))>;
-def : Pat<(or (shl GPR:$rs1, (i64 32)), (srl GPR:$rs1, (i64 32))),
- (GREVI GPR:$rs1, (i64 32))>;
+// FIXME: Is grev better than rori?
def : Pat<(rotl GPR:$rs1, (i64 32)), (GREVI GPR:$rs1, (i64 32))>;
+def : Pat<(rotr GPR:$rs1, (i64 32)), (GREVI GPR:$rs1, (i64 32))>;
def : Pat<(bswap GPR:$rs1), (GREVI GPR:$rs1, (i64 56))>;
def : Pat<(bitreverse GPR:$rs1), (GREVI GPR:$rs1, (i64 63))>;
} // Predicates = [HasStdExtZbp, IsRV64]
diff --git a/llvm/test/CodeGen/RISCV/rv32Zbbp.ll b/llvm/test/CodeGen/RISCV/rv32Zbbp.ll
index 3fe32b5282d9..4457945c7f6a 100644
--- a/llvm/test/CodeGen/RISCV/rv32Zbbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv32Zbbp.ll
@@ -663,20 +663,17 @@ define i32 @rori_i32_fshr(i32 %a) nounwind {
;
; RV32IB-LABEL: rori_i32_fshr:
; RV32IB: # %bb.0:
-; RV32IB-NEXT: addi a1, zero, 31
-; RV32IB-NEXT: ror a0, a0, a1
+; RV32IB-NEXT: rori a0, a0, 31
; RV32IB-NEXT: ret
;
; RV32IBB-LABEL: rori_i32_fshr:
; RV32IBB: # %bb.0:
-; RV32IBB-NEXT: addi a1, zero, 31
-; RV32IBB-NEXT: ror a0, a0, a1
+; RV32IBB-NEXT: rori a0, a0, 31
; RV32IBB-NEXT: ret
;
; RV32IBP-LABEL: rori_i32_fshr:
; RV32IBP: # %bb.0:
-; RV32IBP-NEXT: addi a1, zero, 31
-; RV32IBP-NEXT: ror a0, a0, a1
+; RV32IBP-NEXT: rori a0, a0, 31
; RV32IBP-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
diff --git a/llvm/test/CodeGen/RISCV/rv32Zbp.ll b/llvm/test/CodeGen/RISCV/rv32Zbp.ll
index ff2e903bb541..fdbadc8ed2f9 100644
--- a/llvm/test/CodeGen/RISCV/rv32Zbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv32Zbp.ll
@@ -646,12 +646,12 @@ define i32 @grev16_i32(i32 %a) nounwind {
;
; RV32IB-LABEL: grev16_i32:
; RV32IB: # %bb.0:
-; RV32IB-NEXT: rori a0, a0, 16
+; RV32IB-NEXT: rev16 a0, a0
; RV32IB-NEXT: ret
;
; RV32IBP-LABEL: grev16_i32:
; RV32IBP: # %bb.0:
-; RV32IBP-NEXT: rori a0, a0, 16
+; RV32IBP-NEXT: rev16 a0, a0
; RV32IBP-NEXT: ret
%shl = shl i32 %a, 16
%shr = lshr i32 %a, 16
@@ -672,12 +672,12 @@ define signext i32 @grev16_i32_fshl(i32 signext %a) nounwind {
;
; RV32IB-LABEL: grev16_i32_fshl:
; RV32IB: # %bb.0:
-; RV32IB-NEXT: rori a0, a0, 16
+; RV32IB-NEXT: rev16 a0, a0
; RV32IB-NEXT: ret
;
; RV32IBP-LABEL: grev16_i32_fshl:
; RV32IBP: # %bb.0:
-; RV32IBP-NEXT: rori a0, a0, 16
+; RV32IBP-NEXT: rev16 a0, a0
; RV32IBP-NEXT: ret
%or = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 16)
ret i32 %or
@@ -693,14 +693,12 @@ define signext i32 @grev16_i32_fshr(i32 signext %a) nounwind {
;
; RV32IB-LABEL: grev16_i32_fshr:
; RV32IB: # %bb.0:
-; RV32IB-NEXT: addi a1, zero, 16
-; RV32IB-NEXT: ror a0, a0, a1
+; RV32IB-NEXT: rev16 a0, a0
; RV32IB-NEXT: ret
;
; RV32IBP-LABEL: grev16_i32_fshr:
; RV32IBP: # %bb.0:
-; RV32IBP-NEXT: addi a1, zero, 16
-; RV32IBP-NEXT: ror a0, a0, a1
+; RV32IBP-NEXT: rev16 a0, a0
; RV32IBP-NEXT: ret
%or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 16)
ret i32 %or
@@ -719,14 +717,14 @@ define i64 @grev16_i64(i64 %a) nounwind {
;
; RV32IB-LABEL: grev16_i64:
; RV32IB: # %bb.0:
-; RV32IB-NEXT: rori a0, a0, 16
-; RV32IB-NEXT: rori a1, a1, 16
+; RV32IB-NEXT: rev16 a0, a0
+; RV32IB-NEXT: rev16 a1, a1
; RV32IB-NEXT: ret
;
; RV32IBP-LABEL: grev16_i64:
; RV32IBP: # %bb.0:
-; RV32IBP-NEXT: rori a0, a0, 16
-; RV32IBP-NEXT: rori a1, a1, 16
+; RV32IBP-NEXT: rev16 a0, a0
+; RV32IBP-NEXT: rev16 a1, a1
; RV32IBP-NEXT: ret
%and = shl i64 %a, 16
%shl = and i64 %and, -281470681808896
diff --git a/llvm/test/CodeGen/RISCV/rv64Zbbp.ll b/llvm/test/CodeGen/RISCV/rv64Zbbp.ll
index f145c69dc58e..063a695b164c 100644
--- a/llvm/test/CodeGen/RISCV/rv64Zbbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv64Zbbp.ll
@@ -456,20 +456,17 @@ define i64 @rori_i64_fshr(i64 %a) nounwind {
;
; RV64IB-LABEL: rori_i64_fshr:
; RV64IB: # %bb.0:
-; RV64IB-NEXT: addi a1, zero, 63
-; RV64IB-NEXT: ror a0, a0, a1
+; RV64IB-NEXT: rori a0, a0, 63
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: rori_i64_fshr:
; RV64IBB: # %bb.0:
-; RV64IBB-NEXT: addi a1, zero, 63
-; RV64IBB-NEXT: ror a0, a0, a1
+; RV64IBB-NEXT: rori a0, a0, 63
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: rori_i64_fshr:
; RV64IBP: # %bb.0:
-; RV64IBP-NEXT: addi a1, zero, 63
-; RV64IBP-NEXT: ror a0, a0, a1
+; RV64IBP-NEXT: rori a0, a0, 63
; RV64IBP-NEXT: ret
%1 = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
diff --git a/llvm/test/CodeGen/RISCV/rv64Zbp.ll b/llvm/test/CodeGen/RISCV/rv64Zbp.ll
index 17c399ddcecd..933a7cacb93a 100644
--- a/llvm/test/CodeGen/RISCV/rv64Zbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv64Zbp.ll
@@ -840,12 +840,12 @@ define i64 @grev32(i64 %a) nounwind {
;
; RV64IB-LABEL: grev32:
; RV64IB: # %bb.0:
-; RV64IB-NEXT: rori a0, a0, 32
+; RV64IB-NEXT: rev32 a0, a0
; RV64IB-NEXT: ret
;
; RV64IBP-LABEL: grev32:
; RV64IBP: # %bb.0:
-; RV64IBP-NEXT: rori a0, a0, 32
+; RV64IBP-NEXT: rev32 a0, a0
; RV64IBP-NEXT: ret
%shl = shl i64 %a, 32
%shr = lshr i64 %a, 32
@@ -866,12 +866,12 @@ define i64 @grev32_fshl(i64 %a) nounwind {
;
; RV64IB-LABEL: grev32_fshl:
; RV64IB: # %bb.0:
-; RV64IB-NEXT: rori a0, a0, 32
+; RV64IB-NEXT: rev32 a0, a0
; RV64IB-NEXT: ret
;
; RV64IBP-LABEL: grev32_fshl:
; RV64IBP: # %bb.0:
-; RV64IBP-NEXT: rori a0, a0, 32
+; RV64IBP-NEXT: rev32 a0, a0
; RV64IBP-NEXT: ret
%or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 32)
ret i64 %or
@@ -887,14 +887,12 @@ define i64 @grev32_fshr(i64 %a) nounwind {
;
; RV64IB-LABEL: grev32_fshr:
; RV64IB: # %bb.0:
-; RV64IB-NEXT: addi a1, zero, 32
-; RV64IB-NEXT: ror a0, a0, a1
+; RV64IB-NEXT: rev32 a0, a0
; RV64IB-NEXT: ret
;
; RV64IBP-LABEL: grev32_fshr:
; RV64IBP: # %bb.0:
-; RV64IBP-NEXT: addi a1, zero, 32
-; RV64IBP-NEXT: ror a0, a0, a1
+; RV64IBP-NEXT: rev32 a0, a0
; RV64IBP-NEXT: ret
%or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 32)
ret i64 %or
More information about the llvm-commits
mailing list