diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -2308,6 +2308,20 @@ return false; } +// (ISD::ADD (ISD::ADD base, offset1), offset2) -> (ISD::ADD base, offset1 + +// offset2) +static bool SelectAddChain(SDValue Addr, SDValue &Base, int64_t &Offset) { + bool Matched = false; + while (Addr.getOpcode() == ISD::ADD && + isa(Addr.getOperand(1))) { + Base = Addr.getOperand(0); + Offset += cast(Addr.getOperand(1))->getSExtValue(); + Addr = Base; + Matched = true; + } + return Matched; +} + bool RISCVDAGToDAGISel::SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) { if (SelectAddrFrameIndex(Addr, Base, Offset)) @@ -2322,10 +2336,16 @@ return true; } - if (CurDAG->isBaseWithConstantOffset(Addr)) { - int64_t CVal = cast(Addr.getOperand(1))->getSExtValue(); + int64_t CVal = 0; + bool Matched = SelectAddChain(Addr, Base, CVal); + if (!Matched && CurDAG->isBaseWithConstantOffset(Addr)) { + Base = Addr.getOperand(0); + CVal = cast(Addr.getOperand(1))->getSExtValue(); + Matched = true; + } + + if (Matched) { if (isInt<12>(CVal)) { - Base = Addr.getOperand(0); if (Base.getOpcode() == RISCVISD::ADD_LO) { SDValue LoOperand = Base.getOperand(1); if (auto *GA = dyn_cast(LoOperand)) { @@ -2353,11 +2373,8 @@ Offset = CurDAG->getTargetConstant(CVal, DL, VT); return true; } - } - // Handle ADD with large immediates. - if (Addr.getOpcode() == ISD::ADD && isa(Addr.getOperand(1))) { - int64_t CVal = cast(Addr.getOperand(1))->getSExtValue(); + // Handle ADD chain with large immediates. assert(!isInt<12>(CVal) && "simm12 not already handled?"); // Handle immediates in the range [-4096,-2049] or [2048, 4094]. We can use @@ -2366,7 +2383,7 @@ if (isInt<12>(CVal / 2) && isInt<12>(CVal - CVal / 2)) { int64_t Adj = CVal < 0 ? -2048 : 2047; Base = SDValue( - CurDAG->getMachineNode(RISCV::ADDI, DL, VT, Addr.getOperand(0), + CurDAG->getMachineNode(RISCV::ADDI, DL, VT, Base, CurDAG->getTargetConstant(Adj, DL, VT)), 0); Offset = CurDAG->getTargetConstant(CVal - Adj, DL, VT); @@ -2379,13 +2396,14 @@ // stores that can fold the lo12 bits. Otherwise, the ADD will get iseled // separately with the full materialized immediate creating extra // instructions. + SDValue AddrBase = Base; + SDValue AddrOffset = CurDAG->getTargetConstant(CVal, DL, VT); if (isWorthFoldingAdd(Addr) && - selectConstantAddr(CurDAG, DL, VT, Subtarget, Addr.getOperand(1), Base, + selectConstantAddr(CurDAG, DL, VT, Subtarget, AddrOffset, Base, Offset)) { // Insert an ADD instruction with the materialized Hi52 bits. - Base = SDValue( - CurDAG->getMachineNode(RISCV::ADD, DL, VT, Addr.getOperand(0), Base), - 0); + Base = SDValue(CurDAG->getMachineNode(RISCV::ADD, DL, VT, AddrBase, Base), + 0); return true; } } diff --git a/llvm/test/CodeGen/RISCV/split-offsets.ll b/llvm/test/CodeGen/RISCV/split-offsets.ll --- a/llvm/test/CodeGen/RISCV/split-offsets.ll +++ b/llvm/test/CodeGen/RISCV/split-offsets.ll @@ -13,30 +13,28 @@ ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: lw a0, 0(a0) ; RV32I-NEXT: lui a2, 20 -; RV32I-NEXT: addi a2, a2, -1920 ; RV32I-NEXT: add a1, a1, a2 ; RV32I-NEXT: add a0, a0, a2 ; RV32I-NEXT: li a2, 2 -; RV32I-NEXT: sw a2, 0(a0) +; RV32I-NEXT: sw a2, -1920(a0) ; RV32I-NEXT: li a3, 1 -; RV32I-NEXT: sw a3, 4(a0) -; RV32I-NEXT: sw a3, 0(a1) -; RV32I-NEXT: sw a2, 4(a1) +; RV32I-NEXT: sw a3, -1916(a0) +; RV32I-NEXT: sw a3, -1920(a1) +; RV32I-NEXT: sw a2, -1916(a1) ; RV32I-NEXT: ret ; ; RV64I-LABEL: test1: ; RV64I: # %bb.0: # %entry ; RV64I-NEXT: ld a0, 0(a0) ; RV64I-NEXT: lui a2, 20 -; RV64I-NEXT: addiw a2, a2, -1920 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: add a0, a0, a2 ; RV64I-NEXT: li a2, 2 -; RV64I-NEXT: sw a2, 0(a0) +; RV64I-NEXT: sw a2, -1920(a0) ; RV64I-NEXT: li a3, 1 -; RV64I-NEXT: sw a3, 4(a0) -; RV64I-NEXT: sw a3, 0(a1) -; RV64I-NEXT: sw a2, 4(a1) +; RV64I-NEXT: sw a3, -1916(a0) +; RV64I-NEXT: sw a3, -1920(a1) +; RV64I-NEXT: sw a2, -1916(a1) ; RV64I-NEXT: ret entry: %s = load ptr, ptr %sp @@ -125,23 +123,21 @@ ; RV32I-LABEL: test3: ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: lui a1, 20 -; RV32I-NEXT: addi a1, a1, -1920 ; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: li a1, 2 -; RV32I-NEXT: sw a1, 4(a0) +; RV32I-NEXT: sw a1, -1916(a0) ; RV32I-NEXT: li a1, 3 -; RV32I-NEXT: sw a1, 8(a0) +; RV32I-NEXT: sw a1, -1912(a0) ; RV32I-NEXT: ret ; ; RV64I-LABEL: test3: ; RV64I: # %bb.0: # %entry ; RV64I-NEXT: lui a1, 20 -; RV64I-NEXT: addiw a1, a1, -1920 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: li a1, 2 -; RV64I-NEXT: sw a1, 4(a0) +; RV64I-NEXT: sw a1, -1916(a0) ; RV64I-NEXT: li a1, 3 -; RV64I-NEXT: sw a1, 8(a0) +; RV64I-NEXT: sw a1, -1912(a0) ; RV64I-NEXT: ret entry: %splitgep = getelementptr i8, ptr %t, i64 80000 @@ -151,3 +147,34 @@ store i32 3, ptr %1, align 4 ret void } + +define void @test4(ptr %dest) { +; RV32I-LABEL: test4: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a0, a0, 2047 +; RV32I-NEXT: li a1, 1 +; RV32I-NEXT: sb a1, 1(a0) +; RV32I-NEXT: sb a1, 2(a0) +; RV32I-NEXT: sb a1, 3(a0) +; RV32I-NEXT: sb a1, 4(a0) +; RV32I-NEXT: ret +; +; RV64I-LABEL: test4: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a0, a0, 2047 +; RV64I-NEXT: li a1, 1 +; RV64I-NEXT: sb a1, 1(a0) +; RV64I-NEXT: sb a1, 2(a0) +; RV64I-NEXT: sb a1, 3(a0) +; RV64I-NEXT: sb a1, 4(a0) +; RV64I-NEXT: ret + %p1 = getelementptr i8, ptr %dest, i32 2048 + store i8 1, ptr %p1 + %p2 = getelementptr i8, ptr %dest, i32 2049 + store i8 1, ptr %p2 + %p3 = getelementptr i8, ptr %dest, i32 2050 + store i8 1, ptr %p3 + %p4 = getelementptr i8, ptr %dest, i32 2051 + store i8 1, ptr %p4 + ret void +} diff --git a/llvm/test/CodeGen/RISCV/xtheadmemidx.ll b/llvm/test/CodeGen/RISCV/xtheadmemidx.ll --- a/llvm/test/CodeGen/RISCV/xtheadmemidx.ll +++ b/llvm/test/CodeGen/RISCV/xtheadmemidx.ll @@ -1043,10 +1043,9 @@ ; RV32XTHEADMEMIDX-NEXT: slli a1, a1, 3 ; RV32XTHEADMEMIDX-NEXT: add a0, a1, a0 ; RV32XTHEADMEMIDX-NEXT: lui a1, 23 -; RV32XTHEADMEMIDX-NEXT: addi a1, a1, 1792 ; RV32XTHEADMEMIDX-NEXT: add a1, a0, a1 -; RV32XTHEADMEMIDX-NEXT: lw a0, 0(a1) -; RV32XTHEADMEMIDX-NEXT: lw a1, 4(a1) +; RV32XTHEADMEMIDX-NEXT: lw a0, 1792(a1) +; RV32XTHEADMEMIDX-NEXT: lw a1, 1796(a1) ; RV32XTHEADMEMIDX-NEXT: ret ; ; RV64XTHEADMEMIDX-LABEL: lrd_large_offset: