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,23 @@ 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 constant materialization + // and LUI+ADDI would have produced the same result. This is true for all + // simm32 values except 0x7ffff800-0x7fffffff. + 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 @@ -328,8 +328,7 @@ ; RV64I-LABEL: load_const_medium: ; RV64I: # %bb.0: # %entry ; RV64I-NEXT: lui a0, 1 -; RV64I-NEXT: addiw a0, a0, -16 -; RV64I-NEXT: lw a0, 0(a0) +; RV64I-NEXT: lw a0, -16(a0) ; RV64I-NEXT: ret entry: %0 = load i32, i32* inttoptr (i64 4080 to i32*)