From: gonglingqin Date: Wed, 8 Feb 2023 08:08:08 +0000 (+0800) Subject: [LoongArch] Merge the 12bit constant address into the offset field of the instruction X-Git-Tag: upstream/17.0.6~18214 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=653d823ad22b83fea3019e94e02f8ad99a33b4c0;p=platform%2Fupstream%2Fllvm.git [LoongArch] Merge the 12bit constant address into the offset field of the instruction There are 12bit offset fields in the ld.[b/h/w/d] and st.[b/h/w/d]. When the constant address is less than 12 bits, the address calculation is incorporated into the offset field of the instruction. Differential Revision: https://reviews.llvm.org/D143470 --- diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp index 9fe7d94..ae7167c 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp @@ -138,6 +138,25 @@ bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) { return true; } +// Fold constant addresses. +bool LoongArchDAGToDAGISel::SelectAddrConstant(SDValue Addr, SDValue &Base, + SDValue &Offset) { + SDLoc DL(Addr); + MVT VT = Addr.getSimpleValueType(); + + if (!isa(Addr)) + return false; + + // If the constant is a simm12, we can fold the whole constant and use R0 as + // the base. + int64_t CVal = cast(Addr)->getSExtValue(); + if (!isInt<12>(CVal)) + return false; + Base = CurDAG->getRegister(LoongArch::R0, VT); + Offset = CurDAG->getTargetConstant(SignExtend64<12>(CVal), DL, VT); + return true; +} + bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr, SDValue &Base) { // If this is FrameIndex, don't select it. if (isa(Addr)) diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h index 230151b..3099407 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h @@ -42,6 +42,7 @@ public: std::vector &OutOps) override; bool SelectBaseAddr(SDValue Addr, SDValue &Base); + bool SelectAddrConstant(SDValue Addr, SDValue &Base, SDValue &Offset); bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base); bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index 75b2adc..0e968e0 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -364,6 +364,7 @@ def ImmSubFrom32 : SDNodeXForm; def BaseAddr : ComplexPattern; +def AddrConstant : ComplexPattern; def NonFIBaseAddr : ComplexPattern; def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa), @@ -1219,6 +1220,8 @@ def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>; multiclass LdPat { def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; + def : Pat<(vt (LoadOp (AddrConstant GPR:$rj, simm12:$imm12))), + (Inst GPR:$rj, simm12:$imm12)>; def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))), (Inst BaseAddr:$rj, simm12:$imm12)>; } @@ -1261,6 +1264,8 @@ multiclass StPat { def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), (Inst StTy:$rd, BaseAddr:$rj, 0)>; + def : Pat<(StoreOp (vt StTy:$rs2), (AddrConstant GPR:$rj, simm12:$imm12)), + (Inst StTy:$rs2, GPR:$rj, simm12:$imm12)>; def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)), (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; } diff --git a/llvm/test/CodeGen/LoongArch/load-store-offset.ll b/llvm/test/CodeGen/LoongArch/load-store-offset.ll index c744b94..68777df 100644 --- a/llvm/test/CodeGen/LoongArch/load-store-offset.ll +++ b/llvm/test/CodeGen/LoongArch/load-store-offset.ll @@ -2,185 +2,158 @@ ; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 ; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 -;; TODO: When the offset of the address is less than 12bit, merge the offset -;; of address calculation into the offset field of the instruction. - define i8 @load_i8() nounwind { ; LA32-LABEL: load_i8: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.b $a0, $a0, 0 +; LA32-NEXT: ld.b $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i8: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.b $a0, $a0, 0 +; LA64-NEXT: ld.b $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 + %a = load i8, ptr inttoptr (i64 40 to ptr), align 8 ret i8 %a } define signext i8 @load_i8_sext() nounwind { ; LA32-LABEL: load_i8_sext: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.b $a0, $a0, 0 +; LA32-NEXT: ld.b $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i8_sext: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.b $a0, $a0, 0 +; LA64-NEXT: ld.b $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i8, i8* inttoptr (i64 40 to i8*), align 8 + %a = load i8, ptr inttoptr (i64 40 to ptr), align 8 ret i8 %a } define i16 @load_i16() nounwind { ; LA32-LABEL: load_i16: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.h $a0, $a0, 0 +; LA32-NEXT: ld.h $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i16: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.h $a0, $a0, 0 +; LA64-NEXT: ld.h $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 + %a = load i16, ptr inttoptr (i64 40 to ptr), align 8 ret i16 %a } define signext i16 @load_i16_sext() nounwind { ; LA32-LABEL: load_i16_sext: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.h $a0, $a0, 0 +; LA32-NEXT: ld.h $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i16_sext: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.h $a0, $a0, 0 +; LA64-NEXT: ld.h $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i16, i16* inttoptr (i64 40 to i16*), align 8 + %a = load i16, ptr inttoptr (i64 40 to ptr), align 8 ret i16 %a } define i32 @load_i32() nounwind { ; LA32-LABEL: load_i32: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.w $a0, $a0, 0 +; LA32-NEXT: ld.w $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i32: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.w $a0, $a0, 0 +; LA64-NEXT: ld.w $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 + %a = load i32, ptr inttoptr (i64 40 to ptr), align 8 ret i32 %a } define signext i32 @load_i32_sext() nounwind { ; LA32-LABEL: load_i32_sext: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.w $a0, $a0, 0 +; LA32-NEXT: ld.w $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i32_sext: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.w $a0, $a0, 0 +; LA64-NEXT: ld.w $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i32, i32* inttoptr (i64 40 to i32*), align 8 + %a = load i32, ptr inttoptr (i64 40 to ptr), align 8 ret i32 %a } define i64 @load_i64() nounwind { ; LA32-LABEL: load_i64: ; LA32: # %bb.0: -; LA32-NEXT: ori $a0, $zero, 40 -; LA32-NEXT: ld.w $a0, $a0, 0 -; LA32-NEXT: ori $a1, $zero, 44 -; LA32-NEXT: ld.w $a1, $a1, 0 +; LA32-NEXT: ld.w $a0, $zero, 40 +; LA32-NEXT: ld.w $a1, $zero, 44 ; LA32-NEXT: ret ; ; LA64-LABEL: load_i64: ; LA64: # %bb.0: -; LA64-NEXT: ori $a0, $zero, 40 -; LA64-NEXT: ld.d $a0, $a0, 0 +; LA64-NEXT: ld.d $a0, $zero, 40 ; LA64-NEXT: ret - %a = load i64, i64* inttoptr (i64 40 to i64*), align 8 + %a = load i64, ptr inttoptr (i64 40 to ptr), align 8 ret i64 %a } define void @store_i8(i8 %v) nounwind { ; LA32-LABEL: store_i8: ; LA32: # %bb.0: -; LA32-NEXT: ori $a1, $zero, 40 -; LA32-NEXT: st.b $a0, $a1, 0 +; LA32-NEXT: st.b $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: store_i8: ; LA64: # %bb.0: -; LA64-NEXT: ori $a1, $zero, 40 -; LA64-NEXT: st.b $a0, $a1, 0 +; LA64-NEXT: st.b $a0, $zero, 40 ; LA64-NEXT: ret - store i8 %v, i8* inttoptr (i64 40 to i8*), align 8 + store i8 %v, ptr inttoptr (i64 40 to ptr), align 8 ret void } define void @store_i16(i16 %v) nounwind { ; LA32-LABEL: store_i16: ; LA32: # %bb.0: -; LA32-NEXT: ori $a1, $zero, 40 -; LA32-NEXT: st.h $a0, $a1, 0 +; LA32-NEXT: st.h $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: store_i16: ; LA64: # %bb.0: -; LA64-NEXT: ori $a1, $zero, 40 -; LA64-NEXT: st.h $a0, $a1, 0 +; LA64-NEXT: st.h $a0, $zero, 40 ; LA64-NEXT: ret - store i16 %v, i16* inttoptr (i64 40 to i16*), align 8 + store i16 %v, ptr inttoptr (i64 40 to ptr), align 8 ret void } define void @store_i32(i32 %v) nounwind { ; LA32-LABEL: store_i32: ; LA32: # %bb.0: -; LA32-NEXT: ori $a1, $zero, 40 -; LA32-NEXT: st.w $a0, $a1, 0 +; LA32-NEXT: st.w $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: store_i32: ; LA64: # %bb.0: -; LA64-NEXT: ori $a1, $zero, 40 -; LA64-NEXT: st.w $a0, $a1, 0 +; LA64-NEXT: st.w $a0, $zero, 40 ; LA64-NEXT: ret - store i32 %v, i32* inttoptr (i64 40 to i32*), align 8 + store i32 %v, ptr inttoptr (i64 40 to ptr), align 8 ret void } define void @store_i64(i64 %v) nounwind { ; LA32-LABEL: store_i64: ; LA32: # %bb.0: -; LA32-NEXT: ori $a2, $zero, 44 -; LA32-NEXT: st.w $a1, $a2, 0 -; LA32-NEXT: ori $a1, $zero, 40 -; LA32-NEXT: st.w $a0, $a1, 0 +; LA32-NEXT: st.w $a1, $zero, 44 +; LA32-NEXT: st.w $a0, $zero, 40 ; LA32-NEXT: ret ; ; LA64-LABEL: store_i64: ; LA64: # %bb.0: -; LA64-NEXT: ori $a1, $zero, 40 -; LA64-NEXT: st.d $a0, $a1, 0 +; LA64-NEXT: st.d $a0, $zero, 40 ; LA64-NEXT: ret - store i64 %v, i64* inttoptr (i64 40 to i64*), align 8 + store i64 %v, ptr inttoptr (i64 40 to ptr), align 8 ret void }