From: Alex Bradbury Date: Tue, 21 Nov 2017 08:23:08 +0000 (+0000) Subject: [RISCV] Use register X0 (ZERO) for constant 0 X-Git-Tag: android-x86-7.1-r4~8285 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f9cc39148ab38031f8ba7957360f61ef0d483b9c;p=android-x86%2Fexternal-llvm.git [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318738 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 78f61fa4184..97ad7a571c8 100644 --- a/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/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(); + 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(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/test/CodeGen/RISCV/bare-select.ll b/test/CodeGen/RISCV/bare-select.ll index d4a29ffa29b..ec98b6d18b2 100644 --- a/test/CodeGen/RISCV/bare-select.ll +++ b/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/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll b/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll index f10f7799fbb..6521f66cf6a 100644 --- a/test/CodeGen/RISCV/bswap-ctlz-cttz-ctpop.ll +++ b/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/test/CodeGen/RISCV/sext-zext-trunc.ll b/test/CodeGen/RISCV/sext-zext-trunc.ll index 1855d55b4df..7c5f1205b76 100644 --- a/test/CodeGen/RISCV/sext-zext-trunc.ll +++ b/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