diff options
| author | Alex Bradbury <asb@lowrisc.org> | 2017-11-21 08:23:08 +0000 |
|---|---|---|
| committer | Alex Bradbury <asb@lowrisc.org> | 2017-11-21 08:23:08 +0000 |
| commit | 0c7b3643f715b1c2920331b43aca94997b58681d (patch) | |
| tree | 53e21f5bd97ea3d808320244fce4a769a936309c | |
| parent | ffc435e9c78e61f3ce7213840021300a06a984e7 (diff) | |
| download | bcm5719-llvm-0c7b3643f715b1c2920331b43aca94997b58681d.tar.gz bcm5719-llvm-0c7b3643f715b1c2920331b43aca94997b58681d.zip | |
[RISCV] Use register X0 (ZERO) for constant 0
The obvious approach of defining a pattern like the one below actually doesn't
work:
`def : Pat<(i32 0), (i32 X0)>;`
As was noted when Lanai made this change (https://reviews.llvm.org/rL288215),
attempting to handle the constant 0 in tablegen leads to assertions due to a
physical register being used where a virtual register is expected.
llvm-svn: 318738
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 30 | ||||
| -rw-r--r-- | llvm/test/CodeGen/RISCV/bare-select.ll | 3 | ||||
| -rw-r--r-- | llvm/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll | 20 | ||||
| -rw-r--r-- | llvm/test/CodeGen/RISCV/sext-zext-trunc.ll | 19 |
4 files changed, 43 insertions, 29 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 78f61fa4184..97ad7a571c8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -26,6 +26,8 @@ using namespace llvm; // SelectionDAG operations. namespace { class RISCVDAGToDAGISel final : public SelectionDAGISel { + const RISCVSubtarget *Subtarget; + public: explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine) : SelectionDAGISel(TargetMachine) {} @@ -34,6 +36,11 @@ public: return "RISCV DAG->DAG Pattern Instruction Selection"; } + bool runOnMachineFunction(MachineFunction &MF) override { + Subtarget = &MF.getSubtarget<RISCVSubtarget>(); + return SelectionDAGISel::runOnMachineFunction(MF); + } + void Select(SDNode *Node) override; // Include the pieces autogenerated from the target description. @@ -42,6 +49,9 @@ public: } void RISCVDAGToDAGISel::Select(SDNode *Node) { + unsigned Opcode = Node->getOpcode(); + MVT XLenVT = Subtarget->getXLenVT(); + // Dump information about the Node being selected. DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << "\n"); @@ -52,6 +62,26 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { return; } + // Instruction Selection not handled by the auto-generated tablegen selection + // should be handled here. + EVT VT = Node->getValueType(0); + switch (Opcode) { + case ISD::Constant: + if (VT == XLenVT) { + ConstantSDNode *ConstNode = cast<ConstantSDNode>(Node); + // Materialize zero constants as copies from X0. This allows the coalescer + // to propagate these into other instructions. + if (ConstNode->isNullValue()) { + SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), + SDLoc(Node), RISCV::X0, XLenVT); + return ReplaceNode(Node, New.getNode()); + } + } + break; + default: + break; + } + // Select the default instruction. SelectCode(Node); } diff --git a/llvm/test/CodeGen/RISCV/bare-select.ll b/llvm/test/CodeGen/RISCV/bare-select.ll index d4a29ffa29b..ec98b6d18b2 100644 --- a/llvm/test/CodeGen/RISCV/bare-select.ll +++ b/llvm/test/CodeGen/RISCV/bare-select.ll @@ -6,8 +6,7 @@ define i32 @bare_select(i1 %a, i32 %b, i32 %c) { ; RV32I-LABEL: bare_select: ; RV32I: # BB#0: ; RV32I-NEXT: andi a0, a0, 1 -; RV32I-NEXT: addi a3, zero, 0 -; RV32I-NEXT: bne a0, a3, .LBB0_2 +; RV32I-NEXT: bne a0, zero, .LBB0_2 ; RV32I-NEXT: # BB#1: ; RV32I-NEXT: addi a1, a2, 0 ; RV32I-NEXT: .LBB0_2: diff --git a/llvm/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll index f10f7799fbb..6521f66cf6a 100644 --- a/llvm/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll +++ b/llvm/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll @@ -86,8 +86,7 @@ define i8 @test_cttz_i8(i8 %a) nounwind { ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 8 ; RV32I-NEXT: andi a2, a1, 255 -; RV32I-NEXT: addi a3, zero, 0 -; RV32I-NEXT: beq a2, a3, .LBB3_2 +; RV32I-NEXT: beq a2, zero, .LBB3_2 ; RV32I-NEXT: jal zero, .LBB3_1 ; RV32I-NEXT: .LBB3_1: # %cond.false ; RV32I-NEXT: addi a0, a1, -1 @@ -131,8 +130,7 @@ define i16 @test_cttz_i16(i16 %a) nounwind { ; RV32I-NEXT: lui a2, 16 ; RV32I-NEXT: addi a2, a2, -1 ; RV32I-NEXT: and a2, a1, a2 -; RV32I-NEXT: addi a3, zero, 0 -; RV32I-NEXT: beq a2, a3, .LBB4_2 +; RV32I-NEXT: beq a2, zero, .LBB4_2 ; RV32I-NEXT: jal zero, .LBB4_1 ; RV32I-NEXT: .LBB4_1: # %cond.false ; RV32I-NEXT: addi a0, a1, -1 @@ -173,8 +171,7 @@ define i32 @test_cttz_i32(i32 %a) nounwind { ; RV32I-NEXT: sw ra, 12(s0) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 32 -; RV32I-NEXT: addi a2, zero, 0 -; RV32I-NEXT: beq a1, a2, .LBB5_2 +; RV32I-NEXT: beq a1, zero, .LBB5_2 ; RV32I-NEXT: jal zero, .LBB5_1 ; RV32I-NEXT: .LBB5_1: # %cond.false ; RV32I-NEXT: addi a0, a1, -1 @@ -215,8 +212,7 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV32I-NEXT: sw ra, 12(s0) ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: addi a0, zero, 32 -; RV32I-NEXT: addi a2, zero, 0 -; RV32I-NEXT: beq a1, a2, .LBB6_2 +; RV32I-NEXT: beq a1, zero, .LBB6_2 ; RV32I-NEXT: jal zero, .LBB6_1 ; RV32I-NEXT: .LBB6_1: # %cond.false ; RV32I-NEXT: srli a0, a1, 1 @@ -314,13 +310,13 @@ define i64 @test_cttz_i64(i64 %a) nounwind { ; RV32I-NEXT: addi a0, a1, 0 ; RV32I-NEXT: addi a1, s3, 0 ; RV32I-NEXT: jalr ra, s6, 0 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: bne s2, a1, .LBB7_2 +; RV32I-NEXT: bne s2, zero, .LBB7_2 ; RV32I-NEXT: # BB#1: ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: addi s1, a0, 32 ; RV32I-NEXT: .LBB7_2: ; RV32I-NEXT: addi a0, s1, 0 +; RV32I-NEXT: addi a1, zero, 0 ; RV32I-NEXT: lw s7, 0(s0) ; RV32I-NEXT: lw s6, 4(s0) ; RV32I-NEXT: lw s5, 8(s0) @@ -494,13 +490,13 @@ define i64 @test_cttz_i64_zero_undef(i64 %a) nounwind { ; RV32I-NEXT: addi a0, a1, 0 ; RV32I-NEXT: addi a1, s3, 0 ; RV32I-NEXT: jalr ra, s6, 0 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: bne s2, a1, .LBB11_2 +; RV32I-NEXT: bne s2, zero, .LBB11_2 ; RV32I-NEXT: # BB#1: ; RV32I-NEXT: srli a0, a0, 24 ; RV32I-NEXT: addi s1, a0, 32 ; RV32I-NEXT: .LBB11_2: ; RV32I-NEXT: addi a0, s1, 0 +; RV32I-NEXT: addi a1, zero, 0 ; RV32I-NEXT: lw s7, 0(s0) ; RV32I-NEXT: lw s6, 4(s0) ; RV32I-NEXT: lw s5, 8(s0) diff --git a/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll b/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll index 1855d55b4df..7c5f1205b76 100644 --- a/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll +++ b/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll @@ -2,52 +2,41 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefix=RV32I -; FIXME: an unncessary register is allocated just to store 0. X0 should be -; used instead - define i8 @sext_i1_to_i8(i1 %a) { -; TODO: the addi that stores 0 in t1 is unnecessary ; RV32I-LABEL: sext_i1_to_i8: ; RV32I: # BB#0: ; RV32I-NEXT: andi a0, a0, 1 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: sub a0, a1, a0 +; RV32I-NEXT: sub a0, zero, a0 ; RV32I-NEXT: jalr zero, ra, 0 %1 = sext i1 %a to i8 ret i8 %1 } define i16 @sext_i1_to_i16(i1 %a) { -; TODO: the addi that stores 0 in t1 is unnecessary ; RV32I-LABEL: sext_i1_to_i16: ; RV32I: # BB#0: ; RV32I-NEXT: andi a0, a0, 1 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: sub a0, a1, a0 +; RV32I-NEXT: sub a0, zero, a0 ; RV32I-NEXT: jalr zero, ra, 0 %1 = sext i1 %a to i16 ret i16 %1 } define i32 @sext_i1_to_i32(i1 %a) { -; TODO: the addi that stores 0 in t1 is unnecessary ; RV32I-LABEL: sext_i1_to_i32: ; RV32I: # BB#0: ; RV32I-NEXT: andi a0, a0, 1 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: sub a0, a1, a0 +; RV32I-NEXT: sub a0, zero, a0 ; RV32I-NEXT: jalr zero, ra, 0 %1 = sext i1 %a to i32 ret i32 %1 } define i64 @sext_i1_to_i64(i1 %a) { -; TODO: the addi that stores 0 in t1 is unnecessary ; RV32I-LABEL: sext_i1_to_i64: ; RV32I: # BB#0: ; RV32I-NEXT: andi a0, a0, 1 -; RV32I-NEXT: addi a1, zero, 0 -; RV32I-NEXT: sub a0, a1, a0 +; RV32I-NEXT: sub a0, zero, a0 ; RV32I-NEXT: addi a1, a0, 0 ; RV32I-NEXT: jalr zero, ra, 0 %1 = sext i1 %a to i64 |

