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 @@ -2233,9 +2233,22 @@ if (!Base.isMachineOpcode()) return false; - // If the base is an ADDI, we can merge it in to the load/store. - if (Base.getMachineOpcode() != RISCV::ADDI) - return false; + if (Base.getMachineOpcode() == RISCV::ADDI) { + // If the base is an ADDI, we can merge it in to the load/store. + } else if (Base.getMachineOpcode() == RISCV::ADDIW && + isa(Base.getOperand(1)) && + Base.getOperand(0).isMachineOpcode() && + Base.getOperand(0).getMachineOpcode() == RISCV::LUI && + isa(Base.getOperand(0).getOperand(0))) { + // ADDIW can be merged if it's part of LUI+ADDIW and W doesn't change the + // value. + int64_t Offset = + SignExtend64<32>(Base.getOperand(0).getConstantOperandVal(0) << 12); + Offset += cast(Base.getOperand(1))->getSExtValue(); + if (!isInt<32>(Offset)) + return false; + } else + return false; SDValue ImmOperand = Base.getOperand(1); uint64_t Offset2 = N->getConstantOperandVal(OffsetOpIdx); diff --git a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll --- a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll +++ b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll @@ -317,3 +317,38 @@ %0 = load i64, i64* inttoptr (i64 2044 to i64*) ret i64 %0 } + +define dso_local i32 @load_const_medium() nounwind { +; RV32I-LABEL: load_const_medium: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: lw a0, -16(a0) +; RV32I-NEXT: ret +; +; RV64I-LABEL: load_const_medium: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: lw a0, -16(a0) +; RV64I-NEXT: ret +entry: + %0 = load i32, i32* inttoptr (i64 4080 to i32*) + ret i32 %0 +} + +define dso_local i32 @load_const_large() nounwind { +; RV32I-LABEL: load_const_large: +; RV32I: # %bb.0: # %entry +; RV32I-NEXT: lui a0, 524288 +; RV32I-NEXT: lw a0, -2048(a0) +; RV32I-NEXT: ret +; +; RV64I-LABEL: load_const_large: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: lui a0, 524288 +; RV64I-NEXT: addiw a0, a0, -2048 +; RV64I-NEXT: lw a0, 0(a0) +; RV64I-NEXT: ret +entry: + %0 = load i32, i32* inttoptr (i64 2147481600 to i32*) + ret i32 %0 +}