let rs2 = funct5;
}
+let Predicates = [HasVendorXTHeadMemIdx], DecoderNamespace = "THeadMemIdx",
+ hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+class THLoadIndexed<RegisterClass Ty, bits<5> funct5, string opcodestr>
+ : RVInstR<!shl(funct5, 2), !if(!eq(Ty, GPR), 0b100, 0b110), OPC_CUSTOM_0,
+ (outs Ty:$rd), (ins GPR:$rs1, GPR:$rs2, uimm2:$uimm2),
+ opcodestr, "$rd, $rs1, $rs2, $uimm2"> {
+ bits<2> uimm2;
+ let Inst{26-25} = uimm2;
+}
+
+class THLoadUpdate<bits<5> funct5, string opcodestr>
+ : RVInstI<0b100, OPC_CUSTOM_0, (outs GPR:$rd, GPR:$rs1_wb),
+ (ins GPR:$rs1, simm5:$simm5, uimm2:$uimm2),
+ opcodestr, "$rd, (${rs1}), $simm5, $uimm2"> {
+ bits<5> simm5;
+ bits<2> uimm2;
+ let imm12{11-7} = funct5;
+ let imm12{6-5} = uimm2;
+ let imm12{4-0} = simm5;
+ let Constraints = "@earlyclobber $rd, $rs1_wb = $rs1";
+}
+}
+
+let Predicates = [HasVendorXTHeadMemIdx], DecoderNamespace = "THeadMemIdx",
+ hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+class THStoreIndexed<RegisterClass StTy, bits<5> funct5, string opcodestr>
+ : RVInstR<!shl(funct5, 2), !if(!eq(StTy, GPR), 0b101, 0b111), OPC_CUSTOM_0,
+ (outs), (ins StTy:$rd, GPR:$rs1, GPR:$rs2, uimm2:$uimm2),
+ opcodestr, "$rd, $rs1, $rs2, $uimm2"> {
+ bits<2> uimm2;
+ let Inst{26-25} = uimm2;
+}
+
+class THStoreUpdate<bits<5> funct5, string opcodestr>
+ : RVInstI<0b101, OPC_CUSTOM_0, (outs GPR:$rs1_up),
+ (ins GPR:$rd, GPR:$rs1, simm5:$simm5, uimm2:$uimm2),
+ opcodestr, "$rd, (${rs1}), $simm5, $uimm2"> {
+ bits<5> simm5;
+ bits<2> uimm2;
+ let imm12{11-7} = funct5;
+ let imm12{6-5} = uimm2;
+ let imm12{4-0} = simm5;
+ let Constraints = "$rs1_up = $rs1";
+}
+}
+
//===----------------------------------------------------------------------===//
// Combination of instruction classes.
// Use these multiclasses to define instructions more easily.
Sched<[WriteSTD, WriteSTD, ReadStoreData, ReadMemBase]>;
}
+let Predicates = [HasVendorXTHeadMemIdx] in {
+// T-Head Load/Store + Update instructions.
+def TH_LBIA : THLoadUpdate<0b00011, "th.lbia">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LBIB : THLoadUpdate<0b00001, "th.lbib">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LBUIA : THLoadUpdate<0b10011, "th.lbuia">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LBUIB : THLoadUpdate<0b10001, "th.lbuib">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_LHIA : THLoadUpdate<0b00111, "th.lhia">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LHIB : THLoadUpdate<0b00101, "th.lhib">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LHUIA : THLoadUpdate<0b10111, "th.lhuia">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LHUIB : THLoadUpdate<0b10101, "th.lhuib">,
+ Sched<[WriteLDH, ReadMemBase]>;
+
+def TH_LWIA : THLoadUpdate<0b01011, "th.lwia">,
+ Sched<[WriteLDW, ReadMemBase]>;
+def TH_LWIB : THLoadUpdate<0b01001, "th.lwib">,
+ Sched<[WriteLDW, ReadMemBase]>;
+
+def TH_SBIA : THStoreUpdate<0b00011, "th.sbia">,
+ Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
+def TH_SBIB : THStoreUpdate<0b00001, "th.sbib">,
+ Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
+
+def TH_SHIA : THStoreUpdate<0b00111, "th.shia">,
+ Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
+def TH_SHIB : THStoreUpdate<0b00101, "th.shib">,
+ Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
+
+def TH_SWIA : THStoreUpdate<0b01011, "th.swia">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+def TH_SWIB : THStoreUpdate<0b01001, "th.swib">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+
+// T-Head Load/Store Indexed instructions.
+def TH_LRB : THLoadIndexed<GPR, 0b00000, "th.lrb">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LRBU : THLoadIndexed<GPR, 0b10000, "th.lrbu">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LURB : THLoadIndexed<GPR, 0b00010, "th.lurb">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LURBU : THLoadIndexed<GPR, 0b10010, "th.lurbu">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_LRH : THLoadIndexed<GPR, 0b00100, "th.lrh">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LRHU : THLoadIndexed<GPR, 0b10100, "th.lrhu">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LURH : THLoadIndexed<GPR, 0b00110, "th.lurh">,
+ Sched<[WriteLDB, ReadMemBase]>;
+def TH_LURHU : THLoadIndexed<GPR, 0b10110, "th.lurhu">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_LRW : THLoadIndexed<GPR, 0b01000, "th.lrw">,
+ Sched<[WriteLDW, ReadMemBase]>;
+def TH_LURW : THLoadIndexed<GPR, 0b01010, "th.lurw">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_SRB : THStoreIndexed<GPR, 0b00000, "th.srb">,
+ Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
+def TH_SURB : THStoreIndexed<GPR, 0b00010, "th.surb">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_SRH : THStoreIndexed<GPR, 0b00100, "th.srh">,
+ Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
+def TH_SURH : THStoreIndexed<GPR, 0b00110, "th.surh">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_SRW : THStoreIndexed<GPR, 0b01000, "th.srw">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+def TH_SURW : THStoreIndexed<GPR, 0b01010, "th.surw">,
+ Sched<[WriteLDB, ReadMemBase]>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx, IsRV64] in {
+// T-Head Load/Store + Update instructions.
+def TH_LWUIA : THLoadUpdate<0b11011, "th.lwuia">,
+ Sched<[WriteLDH, ReadMemBase]>;
+def TH_LWUIB : THLoadUpdate<0b11001, "th.lwuib">,
+ Sched<[WriteLDH, ReadMemBase]>;
+
+def TH_LDIA : THLoadUpdate<0b01111, "th.ldia">,
+ Sched<[WriteLDW, ReadMemBase]>;
+def TH_LDIB : THLoadUpdate<0b01101, "th.ldib">,
+ Sched<[WriteLDW, ReadMemBase]>;
+
+def TH_SDIA : THStoreUpdate<0b01111, "th.sdia">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+def TH_SDIB : THStoreUpdate<0b01101, "th.sdib">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+
+// T-Head Load/Store Indexed instructions.
+def TH_LRWU : THLoadIndexed<GPR, 0b11000, "th.lrwu">,
+ Sched<[WriteLDW, ReadMemBase]>;
+def TH_LURWU : THLoadIndexed<GPR, 0b11010, "th.lurwu">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_LRD : THLoadIndexed<GPR, 0b01100, "th.lrd">,
+ Sched<[WriteLDW, ReadMemBase]>;
+def TH_LURD : THLoadIndexed<GPR, 0b01110, "th.lurd">,
+ Sched<[WriteLDB, ReadMemBase]>;
+
+def TH_SRD : THStoreIndexed<GPR, 0b01100, "th.srd">,
+ Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
+def TH_SURD : THStoreIndexed<GPR, 0b01110, "th.surd">,
+ Sched<[WriteLDB, ReadMemBase]>;
+}
+
let Predicates = [HasVendorXTHeadVdot],
Constraints = "@earlyclobber $vd",
RVVConstraint = WidenV in {
def TH_SYNC_I : THCacheInst_void<0b11010, "th.sync.i">;
def TH_SYNC_IS : THCacheInst_void<0b11011, "th.sync.is">;
}
+
+def AddrRegRegScale : ComplexPattern<iPTR, 3, "SelectAddrRegRegScale<3>">;
+def AddrRegZextRegScale
+ : ComplexPattern<iPTR, 3, "SelectAddrRegZextRegScale<3, 32>",
+ [], [], 10>;
+
+multiclass LdIdxPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> {
+def : Pat<(vt (LoadOp (AddrRegRegScale GPR:$rs1, GPR:$rs2, uimm2:$uimm2))),
+ (Inst GPR:$rs1, GPR:$rs2, uimm2:$uimm2)>;
+}
+
+multiclass LdZextIdxPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> {
+def : Pat<(vt (LoadOp (AddrRegZextRegScale GPR:$rs1, GPR:$rs2, uimm2:$uimm2))),
+ (Inst GPR:$rs1, GPR:$rs2, uimm2:$uimm2)>;
+}
+
+multiclass StIdxPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,
+ ValueType vt = XLenVT> {
+def : Pat<(StoreOp (vt StTy:$rd),
+ (AddrRegRegScale GPR:$rs1, GPR:$rs2, uimm2:$uimm2)),
+ (Inst StTy:$rd, GPR:$rs1, GPR:$rs2, uimm2:$uimm2)>;
+}
+
+multiclass StZextIdxPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,
+ ValueType vt = XLenVT> {
+def : Pat<(StoreOp (vt StTy:$rd),
+ (AddrRegZextRegScale GPR:$rs1, GPR:$rs2, uimm2:$uimm2)),
+ (Inst StTy:$rd, GPR:$rs1, GPR:$rs2, uimm2:$uimm2)>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx] in {
+defm : LdIdxPat<extloadi8, TH_LRB>;
+defm : LdIdxPat<sextloadi8, TH_LRB>;
+defm : LdIdxPat<zextloadi8, TH_LRBU>;
+
+defm : LdIdxPat<extloadi16, TH_LRH>;
+defm : LdIdxPat<sextloadi16, TH_LRH>;
+defm : LdIdxPat<zextloadi16, TH_LRHU>;
+
+defm : StIdxPat<truncstorei8, TH_SRB, GPR>;
+defm : StIdxPat<truncstorei16, TH_SRH, GPR>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx, IsRV32] in {
+defm : LdIdxPat<load, TH_LRW>;
+defm : StIdxPat<store, TH_SRW, GPR>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx, IsRV64] in {
+defm : LdZextIdxPat<extloadi8, TH_LURB>;
+defm : LdZextIdxPat<sextloadi8, TH_LURB>;
+defm : LdZextIdxPat<zextloadi8, TH_LURBU>;
+
+defm : LdZextIdxPat<extloadi16, TH_LURH>;
+defm : LdZextIdxPat<sextloadi16, TH_LURH>;
+defm : LdZextIdxPat<zextloadi16, TH_LURHU>;
+
+defm : LdIdxPat<extloadi32, TH_LRW>;
+defm : LdIdxPat<sextloadi32, TH_LRW>;
+defm : LdIdxPat<zextloadi32, TH_LRWU>;
+
+defm : LdZextIdxPat<extloadi32, TH_LURW>;
+defm : LdZextIdxPat<sextloadi32, TH_LURW>;
+defm : LdZextIdxPat<zextloadi32, TH_LURWU>;
+
+defm : LdIdxPat<load, TH_LRD>;
+defm : LdZextIdxPat<load, TH_LURD>;
+
+defm : StZextIdxPat<truncstorei8, TH_SURB, GPR>;
+defm : StZextIdxPat<truncstorei16, TH_SURH, GPR>;
+defm : StIdxPat<truncstorei32, TH_SRW, GPR>;
+defm : StZextIdxPat<truncstorei32, TH_SURW, GPR>;
+defm : StIdxPat<store, TH_SRD, GPR>;
+defm : StZextIdxPat<store, TH_SURD, GPR>;
+}
+
+def simm5shl2 : ComplexPattern<XLenVT, 2, "selectSimm5Shl2">;
+
+multiclass StoreUpdatePat<PatFrag st, Instruction Inst, ValueType vt = XLenVT> {
+def : Pat<(st (vt GPR:$rd), GPR:$rs1, (simm5shl2 simm5:$simm5, uimm2:$uimm2)),
+ (Inst GPR:$rd, GPR:$rs1, simm5:$simm5, uimm2:$uimm2)>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx] in {
+defm : StoreUpdatePat<post_truncsti8, TH_SBIA>;
+defm : StoreUpdatePat<pre_truncsti8, TH_SBIB>;
+defm : StoreUpdatePat<post_truncsti16, TH_SHIA>;
+defm : StoreUpdatePat<pre_truncsti16, TH_SHIB>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx, IsRV32] in {
+defm : StoreUpdatePat<post_store, TH_SWIA>;
+defm : StoreUpdatePat<pre_store, TH_SWIB>;
+}
+
+let Predicates = [HasVendorXTHeadMemIdx, IsRV64] in {
+defm : StoreUpdatePat<post_truncsti32, TH_SWIA>;
+defm : StoreUpdatePat<pre_truncsti32, TH_SWIB>;
+defm : StoreUpdatePat<post_store, TH_SDIA>;
+defm : StoreUpdatePat<pre_store, TH_SDIB>;
+}
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+d -mattr=+xtheadmemidx -mattr=+m -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32XTHEADMEMIDX
+; RUN: llc -mtriple=riscv64 -mattr=+d -mattr=+xtheadmemidx -mattr=+m -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV64XTHEADMEMIDX
+
+define i8* @lbia(i8* %base, i8* %addr.2, i8 %a) {
+; RV32XTHEADMEMIDX-LABEL: lbia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lbia a3, (a0), -1, 0
+; RV32XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV32XTHEADMEMIDX-NEXT: sb a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lbia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lbia a3, (a0), -1, 0
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sb a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i8, i8* %base, i8 0
+ %ld = load i8, i8* %addr
+ %addr.1 = getelementptr i8, i8* %base, i8 -1
+ %res = add i8 %ld, %a
+ store i8 %res, i8* %addr.2
+ ret i8* %addr.1
+}
+
+define i8* @lbib(i8* %base, i8 %a) {
+; RV32XTHEADMEMIDX-LABEL: lbib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lbib a2, (a0), 1, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: sb a1, 1(a0)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lbib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lbib a2, (a0), 1, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV64XTHEADMEMIDX-NEXT: sb a1, 1(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i8, i8* %base, i8 1
+ %ld = load i8, i8* %addr
+ %addr.1 = getelementptr i8, i8* %base, i8 2
+ %res = add i8 %ld, %a
+ store i8 %res, i8* %addr.1
+ ret i8* %addr
+}
+
+define i8* @lbuia(i8* %base, i64* %addr.2, i64 %a) {
+; RV32XTHEADMEMIDX-LABEL: lbuia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lbuia a4, (a0), -1, 0
+; RV32XTHEADMEMIDX-NEXT: add a2, a4, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a2, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a4
+; RV32XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: sw a3, 4(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lbuia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lbuia a3, (a0), -1, 0
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sd a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i8, i8* %base, i8 0
+ %ld = load i8, i8* %addr
+ %zext = zext i8 %ld to i64
+ %addr.1 = getelementptr i8, i8* %base, i8 -1
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.2
+ ret i8* %addr.1
+}
+
+define i8* @lbuib(i8* %base, i64 %a, i64* %addr.1) {
+; RV32XTHEADMEMIDX-LABEL: lbuib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lbuib a4, (a0), 1, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a4, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a1, a4
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a4
+; RV32XTHEADMEMIDX-NEXT: sw a1, 0(a3)
+; RV32XTHEADMEMIDX-NEXT: sw a2, 4(a3)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lbuib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lbuib a3, (a0), 1, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a3, a1
+; RV64XTHEADMEMIDX-NEXT: sd a1, 0(a2)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i8, i8* %base, i8 1
+ %ld = load i8, i8* %addr
+ %zext = zext i8 %ld to i64
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.1
+ ret i8* %addr
+}
+
+define i16* @lhia(i16* %base, i16* %addr.2, i16 %a) {
+; RV32XTHEADMEMIDX-LABEL: lhia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lhia a3, (a0), -16, 1
+; RV32XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV32XTHEADMEMIDX-NEXT: sh a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lhia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lhia a3, (a0), -16, 1
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sh a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i16, i16* %base, i16 0
+ %ld = load i16, i16* %addr
+ %addr.1 = getelementptr i16, i16* %base, i16 -16
+ %res = add i16 %ld, %a
+ store i16 %res, i16* %addr.2
+ ret i16* %addr.1
+}
+
+define i16* @lhib(i16* %base, i16 %a) {
+; RV32XTHEADMEMIDX-LABEL: lhib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lhib a2, (a0), 2, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: sh a1, 2(a0)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lhib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lhib a2, (a0), 2, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV64XTHEADMEMIDX-NEXT: sh a1, 2(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i16, i16* %base, i16 1
+ %ld = load i16, i16* %addr
+ %addr.1 = getelementptr i16, i16* %base, i16 2
+ %res = add i16 %ld, %a
+ store i16 %res, i16* %addr.1
+ ret i16* %addr
+}
+
+define i16* @lhuia(i16* %base, i64* %addr.2, i64 %a) {
+; RV32XTHEADMEMIDX-LABEL: lhuia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lhuia a4, (a0), -16, 1
+; RV32XTHEADMEMIDX-NEXT: add a2, a4, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a2, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a4
+; RV32XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: sw a3, 4(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lhuia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lhuia a3, (a0), -16, 1
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sd a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i16, i16* %base, i16 0
+ %ld = load i16, i16* %addr
+ %zext = zext i16 %ld to i64
+ %addr.1 = getelementptr i16, i16* %base, i16 -16
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.2
+ ret i16* %addr.1
+}
+
+define i16* @lhuib(i16* %base, i64 %a, i64* %addr.1) {
+; RV32XTHEADMEMIDX-LABEL: lhuib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lhuib a4, (a0), 2, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a4, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a1, a4
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a4
+; RV32XTHEADMEMIDX-NEXT: sw a1, 0(a3)
+; RV32XTHEADMEMIDX-NEXT: sw a2, 4(a3)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lhuib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lhuib a3, (a0), 2, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a3, a1
+; RV64XTHEADMEMIDX-NEXT: sd a1, 0(a2)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i16, i16* %base, i16 1
+ %ld = load i16, i16* %addr
+ %zext = zext i16 %ld to i64
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.1
+ ret i16* %addr
+}
+
+define i32* @lwia(i32* %base, i32* %addr.2, i32 %a) {
+; RV32XTHEADMEMIDX-LABEL: lwia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lwia a3, (a0), -16, 2
+; RV32XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV32XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lwia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lwia a3, (a0), -16, 2
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i32, i32* %base, i32 0
+ %ld = load i32, i32* %addr
+ %addr.1 = getelementptr i32, i32* %base, i32 -16
+ %res = add i32 %ld, %a
+ store i32 %res, i32* %addr.2
+ ret i32* %addr.1
+}
+
+define i32* @lwib(i32* %base, i32 %a) {
+; RV32XTHEADMEMIDX-LABEL: lwib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lwib a2, (a0), 4, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: sw a1, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lwib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lwib a2, (a0), 4, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV64XTHEADMEMIDX-NEXT: sw a1, 4(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i32, i32* %base, i32 1
+ %ld = load i32, i32* %addr
+ %addr.1 = getelementptr i32, i32* %base, i32 2
+ %res = add i32 %ld, %a
+ store i32 %res, i32* %addr.1
+ ret i32* %addr
+}
+
+define i32* @lwuia(i32* %base, i64* %addr.2, i64 %a) {
+; RV32XTHEADMEMIDX-LABEL: lwuia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lwia a4, (a0), -16, 2
+; RV32XTHEADMEMIDX-NEXT: add a2, a4, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a2, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a4
+; RV32XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: sw a3, 4(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lwuia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lwuia a3, (a0), -16, 2
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sd a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i32, i32* %base, i32 0
+ %ld = load i32, i32* %addr
+ %zext = zext i32 %ld to i64
+ %addr.1 = getelementptr i32, i32* %base, i32 -16
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.2
+ ret i32* %addr.1
+}
+
+define i32* @lwuib(i32* %base, i64 %a, i64* %addr.1) {
+; RV32XTHEADMEMIDX-LABEL: lwuib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lwib a4, (a0), 4, 0
+; RV32XTHEADMEMIDX-NEXT: add a1, a4, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a1, a4
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a4
+; RV32XTHEADMEMIDX-NEXT: sw a1, 0(a3)
+; RV32XTHEADMEMIDX-NEXT: sw a2, 4(a3)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lwuib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lwuib a3, (a0), 4, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a3, a1
+; RV64XTHEADMEMIDX-NEXT: sd a1, 0(a2)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i32, i32* %base, i32 1
+ %ld = load i32, i32* %addr
+ %zext = zext i32 %ld to i64
+ %res = add i64 %zext, %a
+ store i64 %res, i64* %addr.1
+ ret i32* %addr
+}
+
+define i64* @ldia(i64* %base, i64* %addr.2, i64 %a) {
+; RV32XTHEADMEMIDX-LABEL: ldia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: lw a4, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: lw a5, 0(a0)
+; RV32XTHEADMEMIDX-NEXT: addi a0, a0, -128
+; RV32XTHEADMEMIDX-NEXT: add a3, a4, a3
+; RV32XTHEADMEMIDX-NEXT: add a2, a5, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a4, a2, a5
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a4
+; RV32XTHEADMEMIDX-NEXT: sw a2, 0(a1)
+; RV32XTHEADMEMIDX-NEXT: sw a3, 4(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: ldia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.ldia a3, (a0), -16, 3
+; RV64XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV64XTHEADMEMIDX-NEXT: sd a2, 0(a1)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i64, i64* %base, i64 0
+ %ld = load i64, i64* %addr
+ %addr.1 = getelementptr i64, i64* %base, i64 -16
+ %res = add i64 %ld, %a
+ store i64 %res, i64* %addr.2
+ ret i64* %addr.1
+}
+
+define i64* @ldib(i64* %base, i64 %a) {
+; RV32XTHEADMEMIDX-LABEL: ldib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lwib a3, (a0), 8, 0
+; RV32XTHEADMEMIDX-NEXT: lw a4, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: add a1, a3, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a3, a1, a3
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a3
+; RV32XTHEADMEMIDX-NEXT: add a2, a4, a2
+; RV32XTHEADMEMIDX-NEXT: sw a1, 8(a0)
+; RV32XTHEADMEMIDX-NEXT: sw a2, 12(a0)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: ldib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.ldib a2, (a0), 8, 0
+; RV64XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV64XTHEADMEMIDX-NEXT: sd a1, 8(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr = getelementptr i64, i64* %base, i64 1
+ %ld = load i64, i64* %addr
+ %addr.1 = getelementptr i64, i64* %base, i64 2
+ %res = add i64 %ld, %a
+ store i64 %res, i64* %addr.1
+ ret i64* %addr
+}
+
+define i8* @sbia(i8* %base, i8 %a, i8 %b) {
+; RV32XTHEADMEMIDX-LABEL: sbia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.sbia a1, (a0), 1, 0
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: sbia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.sbia a1, (a0), 1, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i8, i8* %base, i8 1
+ %res = add i8 %a, %b
+ store i8 %res, i8* %base
+ ret i8* %addr.1
+}
+
+define i8* @sbib(i8* %base, i8 %a, i8 %b) {
+; RV32XTHEADMEMIDX-LABEL: sbib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.sbib a1, (a0), 1, 0
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: sbib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.sbib a1, (a0), 1, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i8, i8* %base, i8 1
+ %res = add i8 %a, %b
+ store i8 %res, i8* %addr.1
+ ret i8* %addr.1
+}
+
+define i16* @shia(i16* %base, i16 %a, i16 %b) {
+; RV32XTHEADMEMIDX-LABEL: shia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.shia a1, (a0), -9, 1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: shia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.shia a1, (a0), -9, 1
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i16, i16* %base, i16 -9
+ %res = add i16 %a, %b
+ store i16 %res, i16* %base
+ ret i16* %addr.1
+}
+
+define i16* @shib(i16* %base, i16 %a, i16 %b) {
+; RV32XTHEADMEMIDX-LABEL: shib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.shib a1, (a0), 2, 0
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: shib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.shib a1, (a0), 2, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i16, i16* %base, i16 1
+ %res = add i16 %a, %b
+ store i16 %res, i16* %addr.1
+ ret i16* %addr.1
+}
+
+define i32* @swia(i32* %base, i32 %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: swia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.swia a1, (a0), 8, 2
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: swia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.swia a1, (a0), 8, 2
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i32, i32* %base, i32 8
+ %res = add i32 %a, %b
+ store i32 %res, i32* %base
+ ret i32* %addr.1
+}
+
+define i32* @swib(i32* %base, i32 %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: swib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.swib a1, (a0), -13, 3
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: swib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.swib a1, (a0), -13, 3
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i32, i32* %base, i32 -26
+ %res = add i32 %a, %b
+ store i32 %res, i32* %addr.1
+ ret i32* %addr.1
+}
+
+define i64* @sdia(i64* %base, i64 %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: sdia:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: addi a5, a0, 64
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a1, a3
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a3, a1
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: sw a3, 0(a0)
+; RV32XTHEADMEMIDX-NEXT: sw a1, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: mv a0, a5
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: sdia:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.sdia a1, (a0), 8, 3
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i64, i64* %base, i64 8
+ %res = add i64 %a, %b
+ store i64 %res, i64* %base
+ ret i64* %addr.1
+}
+
+define i64* @sdib(i64* %base, i64 %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: sdib:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a1, a3
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a3, a1
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: th.swib a3, (a0), 8, 0
+; RV32XTHEADMEMIDX-NEXT: sw a1, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: sdib:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.sdib a1, (a0), 8, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i64, i64* %base, i64 1
+ %res = add i64 %a, %b
+ store i64 %res, i64* %addr.1
+ ret i64* %addr.1
+}
+
+define i64 @lrb(i8* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrb:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrb a1, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrb:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrb a0, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i8, i8* %a, i64 %b
+ %2 = load i8, i8* %1, align 1
+ %3 = sext i8 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurb(i8* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurb:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrb a1, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurb:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurb a0, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i8, i8* %a, i64 %1
+ %3 = load i8, i8* %2, align 1
+ %4 = sext i8 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrbu(i8* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrbu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrbu a1, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrbu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrbu a0, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i8, i8* %a, i64 %b
+ %2 = load i8, i8* %1, align 1
+ %3 = zext i8 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurbu(i8* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurbu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrbu a1, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurbu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurbu a0, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i8, i8* %a, i64 %1
+ %3 = load i8, i8* %2, align 1
+ %4 = zext i8 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrh(i16* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrh:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrh a1, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrh:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrh a0, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i16, i16* %a, i64 %b
+ %2 = load i16, i16* %1, align 4
+ %3 = sext i16 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurh(i16* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurh:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrh a1, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurh:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurh a0, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i16, i16* %a, i64 %1
+ %3 = load i16, i16* %2, align 4
+ %4 = sext i16 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrhu(i16* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrhu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrhu a1, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrhu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrhu a0, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i16, i16* %a, i64 %b
+ %2 = load i16, i16* %1, align 4
+ %3 = zext i16 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurhu(i16* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurhu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrhu a1, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurhu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurhu a0, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i16, i16* %a, i64 %1
+ %3 = load i16, i16* %2, align 4
+ %4 = zext i16 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrw(i32* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrw:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrw:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrw a0, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i32, i32* %a, i64 %b
+ %2 = load i32, i32* %1, align 4
+ %3 = sext i32 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurw(i32* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurw:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: srai a2, a1, 31
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurw:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurw a0, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i32, i32* %a, i64 %1
+ %3 = load i32, i32* %2, align 4
+ %4 = sext i32 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrwu(i32* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrwu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrwu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrwu a0, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i32, i32* %a, i64 %b
+ %2 = load i32, i32* %1, align 4
+ %3 = zext i32 %2 to i64
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurwu(i32* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurwu:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurwu:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurwu a0, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i32, i32* %a, i64 %1
+ %3 = load i32, i32* %2, align 4
+ %4 = zext i32 %3 to i64
+ %5 = add i64 %4, %4
+ ret i64 %5
+}
+
+define i64 @lrd(i64* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrd:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: slli a2, a1, 3
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT: add a0, a0, a2
+; RV32XTHEADMEMIDX-NEXT: lw a2, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrd:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lrd a0, a0, a1, 3
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = getelementptr i64, i64* %a, i64 %b
+ %2 = load i64, i64* %1, align 8
+ %3 = add i64 %2, %2
+ ret i64 %3
+}
+
+define i64 @lrd_2(i64* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrd_2:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: addi a2, a0, 96
+; RV32XTHEADMEMIDX-NEXT: th.lrw a2, a2, a1, 3
+; RV32XTHEADMEMIDX-NEXT: addi a0, a0, 100
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT: add a0, a2, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a2, a0, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a1
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrd_2:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: addi a0, a0, 96
+; RV64XTHEADMEMIDX-NEXT: th.lrd a0, a0, a1, 3
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i64 %b, 12
+ %2 = getelementptr i64, i64* %a, i64 %1
+ %3 = load i64, i64* %2, align 8
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define i64 @lurd(i64* %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: lurd:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: slli a2, a1, 3
+; RV32XTHEADMEMIDX-NEXT: th.lrw a1, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT: add a0, a0, a2
+; RV32XTHEADMEMIDX-NEXT: lw a2, 4(a0)
+; RV32XTHEADMEMIDX-NEXT: add a0, a1, a1
+; RV32XTHEADMEMIDX-NEXT: sltu a1, a0, a1
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: add a1, a2, a1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lurd:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: th.lurd a0, a0, a1, 3
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = getelementptr i64, i64* %a, i64 %1
+ %3 = load i64, i64* %2, align 8
+ %4 = add i64 %3, %3
+ ret i64 %4
+}
+
+define void @srb(i8* %a, i64 %b, i8 %c) {
+; RV32XTHEADMEMIDX-LABEL: srb:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a3
+; RV32XTHEADMEMIDX-NEXT: th.srb a3, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: srb:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.srb a2, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i8 %c, %c
+ %2 = getelementptr i8, i8* %a, i64 %b
+ store i8 %1, i8* %2, align 8
+ ret void
+}
+
+define void @surb(i8* %a, i32 %b, i8 %c) {
+; RV32XTHEADMEMIDX-LABEL: surb:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: th.srb a2, a0, a1, 0
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: surb:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.surb a2, a0, a1, 0
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = add i8 %c, %c
+ %3 = getelementptr i8, i8* %a, i64 %1
+ store i8 %2, i8* %3, align 8
+ ret void
+}
+
+define void @srh(i16* %a, i64 %b, i16 %c) {
+; RV32XTHEADMEMIDX-LABEL: srh:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a3
+; RV32XTHEADMEMIDX-NEXT: th.srh a3, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: srh:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.srh a2, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i16 %c, %c
+ %2 = getelementptr i16, i16* %a, i64 %b
+ store i16 %1, i16* %2, align 8
+ ret void
+}
+
+define void @surh(i16* %a, i32 %b, i16 %c) {
+; RV32XTHEADMEMIDX-LABEL: surh:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: th.srh a2, a0, a1, 1
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: surh:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.surh a2, a0, a1, 1
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = add i16 %c, %c
+ %3 = getelementptr i16, i16* %a, i64 %1
+ store i16 %2, i16* %3, align 8
+ ret void
+}
+
+define void @srw(i32* %a, i64 %b, i32 %c) {
+; RV32XTHEADMEMIDX-LABEL: srw:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a3
+; RV32XTHEADMEMIDX-NEXT: th.srw a3, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: srw:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.srw a2, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i32 %c, %c
+ %2 = getelementptr i32, i32* %a, i64 %b
+ store i32 %1, i32* %2, align 8
+ ret void
+}
+
+define void @surw(i32* %a, i32 %b, i32 %c) {
+; RV32XTHEADMEMIDX-LABEL: surw:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV32XTHEADMEMIDX-NEXT: th.srw a2, a0, a1, 2
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: surw:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.surw a2, a0, a1, 2
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = add i32 %c, %c
+ %3 = getelementptr i32, i32* %a, i64 %1
+ store i32 %2, i32* %3, align 8
+ ret void
+}
+
+define void @srd(i64* %a, i64 %b, i64 %c) {
+; RV32XTHEADMEMIDX-LABEL: srd:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a2, a3, a3
+; RV32XTHEADMEMIDX-NEXT: sltu a3, a2, a3
+; RV32XTHEADMEMIDX-NEXT: add a4, a4, a4
+; RV32XTHEADMEMIDX-NEXT: add a3, a4, a3
+; RV32XTHEADMEMIDX-NEXT: slli a4, a1, 3
+; RV32XTHEADMEMIDX-NEXT: add a4, a0, a4
+; RV32XTHEADMEMIDX-NEXT: th.srw a2, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT: sw a3, 4(a4)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: srd:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.srd a2, a0, a1, 3
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i64 %c, %c
+ %2 = getelementptr i64, i64* %a, i64 %b
+ store i64 %1, i64* %2, align 8
+ ret void
+}
+
+define void @surd(i64* %a, i32 %b, i64 %c) {
+; RV32XTHEADMEMIDX-LABEL: surd:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a4, a2, a2
+; RV32XTHEADMEMIDX-NEXT: sltu a2, a4, a2
+; RV32XTHEADMEMIDX-NEXT: add a3, a3, a3
+; RV32XTHEADMEMIDX-NEXT: add a2, a3, a2
+; RV32XTHEADMEMIDX-NEXT: slli a3, a1, 3
+; RV32XTHEADMEMIDX-NEXT: add a3, a0, a3
+; RV32XTHEADMEMIDX-NEXT: th.srw a4, a0, a1, 3
+; RV32XTHEADMEMIDX-NEXT: sw a2, 4(a3)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: surd:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a2, a2, a2
+; RV64XTHEADMEMIDX-NEXT: th.surd a2, a0, a1, 3
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = zext i32 %b to i64
+ %2 = add i64 %c, %c
+ %3 = getelementptr i64, i64* %a, i64 %1
+ store i64 %2, i64* %3, align 8
+ ret void
+}
+
+define i32* @test_simm5(i32* %base, i32 %a, i32 %b) {
+; RV32XTHEADMEMIDX-LABEL: test_simm5:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV32XTHEADMEMIDX-NEXT: th.swia a1, (a0), -12, 2
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: test_simm5:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: add a1, a1, a2
+; RV64XTHEADMEMIDX-NEXT: th.swia a1, (a0), -12, 2
+; RV64XTHEADMEMIDX-NEXT: ret
+ %addr.1 = getelementptr i32, i32* %base, i32 -12
+ %res = add i32 %a, %b
+ store i32 %res, i32* %base
+ ret i32* %addr.1
+}
+
+define i64 @lrd_large_shift(i64* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrd_large_shift:
+; RV32XTHEADMEMIDX: # %bb.0:
+; RV32XTHEADMEMIDX-NEXT: slli a1, a1, 5
+; RV32XTHEADMEMIDX-NEXT: add a1, a1, a0
+; RV32XTHEADMEMIDX-NEXT: lw a0, 384(a1)
+; RV32XTHEADMEMIDX-NEXT: lw a1, 388(a1)
+; RV32XTHEADMEMIDX-NEXT: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrd_large_shift:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: slli a1, a1, 5
+; RV64XTHEADMEMIDX-NEXT: add a0, a1, a0
+; RV64XTHEADMEMIDX-NEXT: ld a0, 384(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i64 %b, 12
+ %2 = shl i64 %1, 2
+ %3 = getelementptr i64, i64* %a, i64 %2
+ %4 = load i64, i64* %3, align 8
+ ret i64 %4
+}
+
+define i64 @lrd_large_offset(i64* %a, i64 %b) {
+; RV32XTHEADMEMIDX-LABEL: lrd_large_offset:
+; RV32XTHEADMEMIDX: # %bb.0:
+; 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: ret
+;
+; RV64XTHEADMEMIDX-LABEL: lrd_large_offset:
+; RV64XTHEADMEMIDX: # %bb.0:
+; RV64XTHEADMEMIDX-NEXT: slli a1, a1, 3
+; RV64XTHEADMEMIDX-NEXT: add a0, a1, a0
+; RV64XTHEADMEMIDX-NEXT: lui a1, 23
+; RV64XTHEADMEMIDX-NEXT: add a0, a0, a1
+; RV64XTHEADMEMIDX-NEXT: ld a0, 1792(a0)
+; RV64XTHEADMEMIDX-NEXT: ret
+ %1 = add i64 %b, 12000
+ %2 = getelementptr i64, i64* %a, i64 %1
+ %3 = load i64, i64* %2, align 8
+ ret i64 %3
+}