[llvm] 5b4851e - [LoongArch] Add codegen support for load/store operations

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 4 20:59:01 PDT 2022


Author: wanglei
Date: 2022-07-05T11:58:20+08:00
New Revision: 5b4851ed911397b7a88aed42460e7b3febccc90d

URL: https://github.com/llvm/llvm-project/commit/5b4851ed911397b7a88aed42460e7b3febccc90d
DIFF: https://github.com/llvm/llvm-project/commit/5b4851ed911397b7a88aed42460e7b3febccc90d.diff

LOG: [LoongArch] Add codegen support for load/store operations

This patch also support lowering global addresses.

Differential Revision: https://reviews.llvm.org/D128427

Added: 
    llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll

Modified: 
    llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.h
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
index 5b117d40e0a9c..b1df8db7d480a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
@@ -174,4 +174,12 @@ def : PatFPSelectcc<SETULE, FCMP_CULE_S, FSEL_S, FPR32>;
 def : PatFPSelectcc<SETUNE, FCMP_CUNE_S, FSEL_S, FPR32>;
 def : PatFPSelectcc<SETUO,  FCMP_CUN_S,  FSEL_S, FPR32>;
 
+/// Loads
+
+defm : LdPat<load, FLD_S, f32>;
+
+/// Stores
+
+defm : StPat<store, FST_S, FPR32, f32>;
+
 } // Predicates = [HasBasicF]

diff  --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
index 07fa61f4c3616..c3569ae84e9d5 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
@@ -185,4 +185,12 @@ def : PatFPSelectcc<SETULE, FCMP_CULE_D, FSEL_D, FPR64>;
 def : PatFPSelectcc<SETUNE, FCMP_CUNE_D, FSEL_D, FPR64>;
 def : PatFPSelectcc<SETUO,  FCMP_CUN_D,  FSEL_D, FPR64>;
 
+/// Loads
+
+defm : LdPat<load, FLD_D, f64>;
+
+/// Stores
+
+defm : StPat<store, FST_D, FPR64, f64>;
+
 } // Predicates = [HasBasicD]

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index d5a469216859c..1814b8ad2baa6 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -17,6 +17,7 @@
 #include "LoongArchRegisterInfo.h"
 #include "LoongArchSubtarget.h"
 #include "LoongArchTargetMachine.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/Support/Debug.h"
@@ -37,11 +38,16 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
   if (Subtarget.hasBasicD())
     addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);
 
+  setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT,
+                   MVT::i1, Promote);
+
   // TODO: add necessary setOperationAction calls later.
   setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom);
   setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom);
   setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom);
 
+  setOperationAction(ISD::GlobalAddress, GRLenVT, Custom);
+
   if (Subtarget.is64Bit()) {
     setOperationAction(ISD::SHL, MVT::i32, Custom);
     setOperationAction(ISD::SRA, MVT::i32, Custom);
@@ -83,6 +89,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
   switch (Op.getOpcode()) {
   default:
     report_fatal_error("unimplemented operand");
+  case ISD::GlobalAddress:
+    return lowerGlobalAddress(Op, DAG);
   case ISD::SHL_PARTS:
     return lowerShiftLeftParts(Op, DAG);
   case ISD::SRA_PARTS:
@@ -99,6 +107,24 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
   }
 }
 
+SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
+                                                    SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+  unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+
+  // FIXME: Only support PC-relative addressing to access the symbol.
+  // TODO: Add target flags.
+  if (!isPositionIndependent()) {
+    SDValue GA = DAG.getTargetGlobalAddress(GV, DL, Ty);
+    SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GA), 0);
+    SDValue Addr(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GA), 0);
+    return Addr;
+  }
+  report_fatal_error("Unable to lowerGlobalAddress");
+}
+
 SDValue LoongArchTargetLowering::lowerShiftLeftParts(SDValue Op,
                                                      SelectionDAG &DAG) const {
   SDLoc DL(Op);

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index c852577a37443..0782c73e87d2b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -86,6 +86,7 @@ class LoongArchTargetLowering : public TargetLowering {
                          const SmallVectorImpl<ISD::OutputArg> &Outs,
                          LoongArchCCAssignFn Fn) const;
 
+  SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
 };

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 6b8ee9e43f947..5e2231b783d7b 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -663,6 +663,46 @@ let Predicates = [IsLA64] in
 def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
           (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>;
 
+/// Loads
+
+multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
+  def : Pat<(vt (LoadOp GPR:$rj)), (Inst GPR:$rj, 0)>;
+  def : Pat<(vt (LoadOp (add GPR:$rj, simm12:$imm12))),
+            (Inst GPR:$rj, simm12:$imm12)>;
+}
+
+defm : LdPat<sextloadi8, LD_B>;
+defm : LdPat<extloadi8, LD_B>;
+defm : LdPat<sextloadi16, LD_H>;
+defm : LdPat<extloadi16, LD_H>;
+defm : LdPat<load, LD_W>, Requires<[IsLA32]>;
+defm : LdPat<zextloadi8, LD_BU>;
+defm : LdPat<zextloadi16, LD_HU>;
+let Predicates = [IsLA64] in {
+defm : LdPat<sextloadi32, LD_W, i64>;
+defm : LdPat<extloadi32, LD_W, i64>;
+defm : LdPat<zextloadi32, LD_WU, i64>;
+defm : LdPat<load, LD_D, i64>;
+} // Predicates = [IsLA64]
+
+/// Stores
+
+multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
+                 ValueType vt> {
+  def : Pat<(StoreOp (vt StTy:$rd), GPR:$rj),
+            (Inst StTy:$rd, GPR:$rj, 0)>;
+  def : Pat<(StoreOp (vt StTy:$rd), (add GPR:$rj, simm12:$imm12)),
+            (Inst StTy:$rd, GPR:$rj, simm12:$imm12)>;
+}
+
+defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
+defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>;
+defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>;
+let Predicates = [IsLA64] in {
+defm : StPat<truncstorei32, ST_W, GPR, i64>;
+defm : StPat<store, ST_D, GPR, i64>;
+} // Predicates = [IsLA64]
+
 //===----------------------------------------------------------------------===//
 // Assembler Pseudo Instructions
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 7416c93b4d05f..5277cd7f42428 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -22,6 +22,22 @@
 
 using namespace llvm;
 
+static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+                                    const AsmPrinter &AP) {
+  MCContext &Ctx = AP.OutContext;
+
+  // TODO: Processing target flags.
+
+  const MCExpr *ME =
+      MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
+
+  if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
+    ME = MCBinaryExpr::createAdd(
+        ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
+
+  return MCOperand::createExpr(ME);
+}
+
 bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
                                                    MCOperand &MCOp,
                                                    const AsmPrinter &AP) {
@@ -41,9 +57,11 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
   case MachineOperand::MO_Immediate:
     MCOp = MCOperand::createImm(MO.getImm());
     break;
+  case MachineOperand::MO_GlobalAddress:
+    MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP);
+    break;
   // TODO: lower special operands
   case MachineOperand::MO_MachineBasicBlock:
-  case MachineOperand::MO_GlobalAddress:
   case MachineOperand::MO_BlockAddress:
   case MachineOperand::MO_ExternalSymbol:
   case MachineOperand::MO_ConstantPoolIndex:

diff  --git a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
new file mode 100644
index 0000000000000..ed185c16a896d
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
@@ -0,0 +1,368 @@
+; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefixes=ALL,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefixes=ALL,LA64
+
+;; Check load from and store to a global mem.
+ at G = global i32 0
+
+define i32 @load_store_global(i32 %a) nounwind {
+; LA32-LABEL: load_store_global:
+; LA32:       # %bb.0:
+; LA32-NEXT:    pcalau12i $a1, G
+; LA32-NEXT:    addi.w $a2, $a1, G
+; LA32-NEXT:    ld.w $a1, $a2, 0
+; LA32-NEXT:    st.w $a0, $a2, 0
+; LA32-NEXT:    ld.w $a3, $a2, 36
+; LA32-NEXT:    st.w $a0, $a2, 36
+; LA32-NEXT:    move $a0, $a1
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: load_store_global:
+; LA64:       # %bb.0:
+; LA64-NEXT:    pcalau12i $a1, G
+; LA64-NEXT:    addi.d $a2, $a1, G
+; LA64-NEXT:    ld.w $a1, $a2, 0
+; LA64-NEXT:    st.w $a0, $a2, 0
+; LA64-NEXT:    ld.w $a3, $a2, 36
+; LA64-NEXT:    st.w $a0, $a2, 36
+; LA64-NEXT:    move $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = load volatile i32, ptr @G
+  store i32 %a, ptr @G
+  %2 = getelementptr i32, ptr @G, i32 9
+  %3 = load volatile i32, ptr %2
+  store i32 %a, ptr %2
+  ret i32 %1
+}
+
+;; Check indexed and unindexed, sext, zext and anyext loads.
+
+define i64 @ld_b(ptr %a) nounwind {
+; LA32-LABEL: ld_b:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.b $a1, $a0, 0
+; LA32-NEXT:    ld.b $a0, $a0, 1
+; LA32-NEXT:    srai.w $a1, $a0, 31
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_b:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.b $a1, $a0, 0
+; LA64-NEXT:    ld.b $a0, $a0, 1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i8, ptr %a, i64 1
+  %2 = load i8, ptr %1
+  %3 = sext i8 %2 to i64
+  %4 = load volatile i8, ptr %a
+  ret i64 %3
+}
+
+define i64 @ld_h(ptr %a) nounwind {
+; LA32-LABEL: ld_h:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.h $a1, $a0, 0
+; LA32-NEXT:    ld.h $a0, $a0, 4
+; LA32-NEXT:    srai.w $a1, $a0, 31
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_h:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.h $a1, $a0, 0
+; LA64-NEXT:    ld.h $a0, $a0, 4
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i16, ptr %a, i64 2
+  %2 = load i16, ptr %1
+  %3 = sext i16 %2 to i64
+  %4 = load volatile i16, ptr %a
+  ret i64 %3
+}
+
+define i64 @ld_w(ptr %a) nounwind {
+; LA32-LABEL: ld_w:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.w $a1, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, 12
+; LA32-NEXT:    srai.w $a1, $a0, 31
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_w:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.w $a1, $a0, 0
+; LA64-NEXT:    ld.w $a0, $a0, 12
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i32, ptr %a, i64 3
+  %2 = load i32, ptr %1
+  %3 = sext i32 %2 to i64
+  %4 = load volatile i32, ptr %a
+  ret i64 %3
+}
+
+define i64 @ld_d(ptr %a) nounwind {
+; LA32-LABEL: ld_d:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.w $a1, $a0, 4
+; LA32-NEXT:    ld.w $a1, $a0, 0
+; LA32-NEXT:    ld.w $a1, $a0, 28
+; LA32-NEXT:    ld.w $a0, $a0, 24
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_d:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.d $a1, $a0, 0
+; LA64-NEXT:    ld.d $a0, $a0, 24
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i64, ptr %a, i64 3
+  %2 = load i64, ptr %1
+  %3 = load volatile i64, ptr %a
+  ret i64 %2
+}
+
+define i64 @ld_bu(ptr %a) nounwind {
+; LA32-LABEL: ld_bu:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.bu $a1, $a0, 0
+; LA32-NEXT:    ld.bu $a2, $a0, 4
+; LA32-NEXT:    add.w $a0, $a2, $a1
+; LA32-NEXT:    sltu $a1, $a0, $a2
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_bu:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.bu $a1, $a0, 0
+; LA64-NEXT:    ld.bu $a0, $a0, 4
+; LA64-NEXT:    add.d $a0, $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i8, ptr %a, i64 4
+  %2 = load i8, ptr %1
+  %3 = zext i8 %2 to i64
+  %4 = load volatile i8, ptr %a
+  %5 = zext i8 %4 to i64
+  %6 = add i64 %3, %5
+  ret i64 %6
+}
+
+define i64 @ld_hu(ptr %a) nounwind {
+; LA32-LABEL: ld_hu:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.hu $a1, $a0, 0
+; LA32-NEXT:    ld.hu $a2, $a0, 10
+; LA32-NEXT:    add.w $a0, $a2, $a1
+; LA32-NEXT:    sltu $a1, $a0, $a2
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_hu:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.hu $a1, $a0, 0
+; LA64-NEXT:    ld.hu $a0, $a0, 10
+; LA64-NEXT:    add.d $a0, $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i16, ptr %a, i64 5
+  %2 = load i16, ptr %1
+  %3 = zext i16 %2 to i64
+  %4 = load volatile i16, ptr %a
+  %5 = zext i16 %4 to i64
+  %6 = add i64 %3, %5
+  ret i64 %6
+}
+
+define i64 @ld_wu(ptr %a) nounwind {
+; LA32-LABEL: ld_wu:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.w $a1, $a0, 0
+; LA32-NEXT:    ld.w $a2, $a0, 20
+; LA32-NEXT:    add.w $a0, $a2, $a1
+; LA32-NEXT:    sltu $a1, $a0, $a2
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_wu:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.wu $a1, $a0, 0
+; LA64-NEXT:    ld.wu $a0, $a0, 20
+; LA64-NEXT:    add.d $a0, $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i32, ptr %a, i64 5
+  %2 = load i32, ptr %1
+  %3 = zext i32 %2 to i64
+  %4 = load volatile i32, ptr %a
+  %5 = zext i32 %4 to i64
+  %6 = add i64 %3, %5
+  ret i64 %6
+}
+
+;; Check indexed and unindexed stores.
+
+define void @st_b(ptr %a, i8 %b) nounwind {
+; ALL-LABEL: st_b:
+; ALL:       # %bb.0:
+; ALL-NEXT:    st.b $a1, $a0, 6
+; ALL-NEXT:    st.b $a1, $a0, 0
+; ALL-NEXT:    jirl $zero, $ra, 0
+  store i8 %b, ptr %a
+  %1 = getelementptr i8, ptr %a, i64 6
+  store i8 %b, ptr %1
+  ret void
+}
+
+define void @st_h(ptr %a, i16 %b) nounwind {
+; ALL-LABEL: st_h:
+; ALL:       # %bb.0:
+; ALL-NEXT:    st.h $a1, $a0, 14
+; ALL-NEXT:    st.h $a1, $a0, 0
+; ALL-NEXT:    jirl $zero, $ra, 0
+  store i16 %b, ptr %a
+  %1 = getelementptr i16, ptr %a, i64 7
+  store i16 %b, ptr %1
+  ret void
+}
+
+define void @st_w(ptr %a, i32 %b) nounwind {
+; ALL-LABEL: st_w:
+; ALL:       # %bb.0:
+; ALL-NEXT:    st.w $a1, $a0, 28
+; ALL-NEXT:    st.w $a1, $a0, 0
+; ALL-NEXT:    jirl $zero, $ra, 0
+  store i32 %b, ptr %a
+  %1 = getelementptr i32, ptr %a, i64 7
+  store i32 %b, ptr %1
+  ret void
+}
+
+define void @st_d(ptr %a, i64 %b) nounwind {
+; LA32-LABEL: st_d:
+; LA32:       # %bb.0:
+; LA32-NEXT:    st.w $a2, $a0, 68
+; LA32-NEXT:    st.w $a2, $a0, 4
+; LA32-NEXT:    st.w $a1, $a0, 64
+; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: st_d:
+; LA64:       # %bb.0:
+; LA64-NEXT:    st.d $a1, $a0, 64
+; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    jirl $zero, $ra, 0
+  store i64 %b, ptr %a
+  %1 = getelementptr i64, ptr %a, i64 8
+  store i64 %b, ptr %1
+  ret void
+}
+
+;; Check load from and store to an i1 location.
+define i64 @load_sext_zext_anyext_i1(ptr %a) nounwind {
+  ;; sextload i1
+; LA32-LABEL: load_sext_zext_anyext_i1:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.b $a1, $a0, 0
+; LA32-NEXT:    ld.bu $a1, $a0, 1
+; LA32-NEXT:    ld.bu $a2, $a0, 2
+; LA32-NEXT:    sub.w $a0, $a2, $a1
+; LA32-NEXT:    sltu $a1, $a2, $a1
+; LA32-NEXT:    sub.w $a1, $zero, $a1
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: load_sext_zext_anyext_i1:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.b $a1, $a0, 0
+; LA64-NEXT:    ld.bu $a1, $a0, 1
+; LA64-NEXT:    ld.bu $a0, $a0, 2
+; LA64-NEXT:    sub.d $a0, $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i1, ptr %a, i64 1
+  %2 = load i1, ptr %1
+  %3 = sext i1 %2 to i64
+  ;; zextload i1
+  %4 = getelementptr i1, ptr %a, i64 2
+  %5 = load i1, ptr %4
+  %6 = zext i1 %5 to i64
+  %7 = add i64 %3, %6
+  ;; extload i1 (anyext). Produced as the load is unused.
+  %8 = load volatile i1, ptr %a
+  ret i64 %7
+}
+
+define i16 @load_sext_zext_anyext_i1_i16(ptr %a) nounwind {
+  ;; sextload i1
+; LA32-LABEL: load_sext_zext_anyext_i1_i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.b $a1, $a0, 0
+; LA32-NEXT:    ld.bu $a1, $a0, 1
+; LA32-NEXT:    ld.bu $a0, $a0, 2
+; LA32-NEXT:    sub.w $a0, $a0, $a1
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: load_sext_zext_anyext_i1_i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.b $a1, $a0, 0
+; LA64-NEXT:    ld.bu $a1, $a0, 1
+; LA64-NEXT:    ld.bu $a0, $a0, 2
+; LA64-NEXT:    sub.d $a0, $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr i1, ptr %a, i64 1
+  %2 = load i1, ptr %1
+  %3 = sext i1 %2 to i16
+  ;; zextload i1
+  %4 = getelementptr i1, ptr %a, i64 2
+  %5 = load i1, ptr %4
+  %6 = zext i1 %5 to i16
+  %7 = add i16 %3, %6
+  ;; extload i1 (anyext). Produced as the load is unused.
+  %8 = load volatile i1, ptr %a
+  ret i16 %7
+}
+
+define i64 @ld_sd_constant(i64 %a) nounwind {
+; LA32-LABEL: ld_sd_constant:
+; LA32:       # %bb.0:
+; LA32-NEXT:    lu12i.w $a3, -136485
+; LA32-NEXT:    ori $a4, $a3, 3823
+; LA32-NEXT:    ld.w $a2, $a4, 0
+; LA32-NEXT:    st.w $a0, $a4, 0
+; LA32-NEXT:    ori $a0, $a3, 3827
+; LA32-NEXT:    ld.w $a3, $a0, 0
+; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    move $a0, $a2
+; LA32-NEXT:    move $a1, $a3
+; LA32-NEXT:    jirl $zero, $ra, 0
+;
+; LA64-LABEL: ld_sd_constant:
+; LA64:       # %bb.0:
+; LA64-NEXT:    lu12i.w $a1, -136485
+; LA64-NEXT:    ori $a1, $a1, 3823
+; LA64-NEXT:    lu32i.d $a1, -147729
+; LA64-NEXT:    lu52i.d $a2, $a1, -534
+; LA64-NEXT:    ld.d $a1, $a2, 0
+; LA64-NEXT:    st.d $a0, $a2, 0
+; LA64-NEXT:    move $a0, $a1
+; LA64-NEXT:    jirl $zero, $ra, 0
+  %1 = inttoptr i64 16045690984833335023 to ptr
+  %2 = load volatile i64, ptr %1
+  store i64 %a, ptr %1
+  ret i64 %2
+}
+
+;; Check load from and store to a float location.
+define float @load_store_float(ptr %a, float %b) nounwind {
+; ALL-LABEL: load_store_float:
+; ALL:       # %bb.0:
+; ALL-NEXT:    fld.s $fa1, $a0, 4
+; ALL-NEXT:    fst.s $fa0, $a0, 4
+; ALL-NEXT:    fmov.s $fa0, $fa1
+; ALL-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr float, ptr %a, i64 1
+  %2 = load float, ptr %1
+  store float %b, ptr %1
+  ret float %2
+}
+
+;; Check load from and store to a double location.
+define double @load_store_double(ptr %a, double %b) nounwind {
+; ALL-LABEL: load_store_double:
+; ALL:       # %bb.0:
+; ALL-NEXT:    fld.d $fa1, $a0, 8
+; ALL-NEXT:    fst.d $fa0, $a0, 8
+; ALL-NEXT:    fmov.d $fa0, $fa1
+; ALL-NEXT:    jirl $zero, $ra, 0
+  %1 = getelementptr double, ptr %a, i64 1
+  %2 = load double, ptr %1
+  store double %b, ptr %1
+  ret double %2
+}


        


More information about the llvm-commits mailing list