Index: lib/Target/Mips/MipsISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.h +++ lib/Target/Mips/MipsISelDAGToDAG.h @@ -80,6 +80,18 @@ virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectIntAddrMSAAlign(SDValue Addr, SDValue &Base, + SDValue &Offset, unsigned Align) const; + + virtual bool selectIntAddrMSAAlign2(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + + virtual bool selectIntAddrMSAAlign4(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + + virtual bool selectIntAddrMSAAlign8(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset, SDValue &Alias); Index: lib/Target/Mips/MipsISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.cpp +++ lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -108,6 +108,30 @@ return false; } +bool MipsDAGToDAGISel::selectIntAddrMSAAlign( + SDValue Addr, SDValue &Base, SDValue &Offset, unsigned Align) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectIntAddrMSAAlign2(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectIntAddrMSAAlign4(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectIntAddrMSAAlign8(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, SDValue &Offset, SDValue &Alias) { llvm_unreachable("Unimplemented function."); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1073,6 +1073,12 @@ ComplexPattern; def addrimm10 : ComplexPattern; +def addrimm10al2 : ComplexPattern; +def addrimm10al4 : ComplexPattern; +def addrimm10al8 : ComplexPattern; //===----------------------------------------------------------------------===// // Instructions specific format Index: lib/Target/Mips/MipsMSAInstrInfo.td =================================================================== --- lib/Target/Mips/MipsMSAInstrInfo.td +++ lib/Target/Mips/MipsMSAInstrInfo.td @@ -2308,9 +2308,12 @@ } class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>; -class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, mem_simm10_lsl1>; -class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, mem_simm10_lsl2>; -class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, mem_simm10_lsl3>; +class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, + mem_simm10_lsl1, addrimm10al2>; +class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, + mem_simm10_lsl2, addrimm10al4>; +class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, + mem_simm10_lsl3, addrimm10al8>; class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128BOpnd>; class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128HOpnd>; @@ -2642,9 +2645,12 @@ } class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>; -class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, mem_simm10_lsl1>; -class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, mem_simm10_lsl2>; -class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, mem_simm10_lsl3>; +class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, + mem_simm10_lsl1, addrimm10al2>; +class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, + mem_simm10_lsl2, addrimm10al4>; +class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, + mem_simm10_lsl3, addrimm10al8>; class SUBS_S_B_DESC : MSA_3R_DESC_BASE<"subs_s.b", int_mips_subs_s_b, MSA128BOpnd>; @@ -3524,16 +3530,16 @@ def : MSAPat<(extractelt (v4i32 MSA128W:$ws), immZExt4:$idx), (COPY_S_W MSA128W:$ws, immZExt4:$idx)>; -def : MSAPat<(v8f16 (load addrimm10:$addr)), (LD_H addrimm10:$addr)>; -def : MSAPat<(v4f32 (load addrimm10:$addr)), (LD_W addrimm10:$addr)>; -def : MSAPat<(v2f64 (load addrimm10:$addr)), (LD_D addrimm10:$addr)>; +def : MSAPat<(v8f16 (load addrimm10al2:$addr)), (LD_H addrimm10al2:$addr)>; +def : MSAPat<(v4f32 (load addrimm10al4:$addr)), (LD_W addrimm10al4:$addr)>; +def : MSAPat<(v2f64 (load addrimm10al8:$addr)), (LD_D addrimm10al8:$addr)>; -def ST_FH : MSAPat<(store (v8f16 MSA128H:$ws), addrimm10:$addr), - (ST_H MSA128H:$ws, addrimm10:$addr)>; -def ST_FW : MSAPat<(store (v4f32 MSA128W:$ws), addrimm10:$addr), - (ST_W MSA128W:$ws, addrimm10:$addr)>; -def ST_FD : MSAPat<(store (v2f64 MSA128D:$ws), addrimm10:$addr), - (ST_D MSA128D:$ws, addrimm10:$addr)>; +def ST_FH : MSAPat<(store (v8f16 MSA128H:$ws), addrimm10al2:$addr), + (ST_H MSA128H:$ws, addrimm10al2:$addr)>; +def ST_FW : MSAPat<(store (v4f32 MSA128W:$ws), addrimm10al4:$addr), + (ST_W MSA128W:$ws, addrimm10al4:$addr)>; +def ST_FD : MSAPat<(store (v2f64 MSA128D:$ws), addrimm10al8:$addr), + (ST_D MSA128D:$ws, addrimm10al8:$addr)>; class MSA_FABS_PSEUDO_DESC_BASE(Base)) { + if (ConstantSDNode *CN = dyn_cast(Offset)) { + unsigned CnstOff = CN->getZExtValue(); + unsigned OffsetDiff = OffsetToAlignment(CnstOff, Align); + // If offset is not aligned, change it to the first greater offset + // that is aligned. + if(OffsetDiff) + Offset = CurDAG->getTargetConstant(CnstOff + OffsetDiff, SDLoc(Addr), + Addr.getValueType()); + } + } + + return true; + } + + return selectAddrDefault(Addr, Base, Offset); +} + +bool MipsSEDAGToDAGISel::selectIntAddrMSAAlign2(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + return selectIntAddrMSAAlign(Addr, Base, Offset, 2); +} + +bool MipsSEDAGToDAGISel::selectIntAddrMSAAlign4(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + return selectIntAddrMSAAlign(Addr, Base, Offset, 4); +} + +bool MipsSEDAGToDAGISel::selectIntAddrMSAAlign8(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + return selectIntAddrMSAAlign(Addr, Base, Offset, 8); +} + // Select constant vector splats. // // Returns true and sets Imm if: Index: test/CodeGen/Mips/msa/i5_ld_st.ll =================================================================== --- test/CodeGen/Mips/msa/i5_ld_st.ll +++ test/CodeGen/Mips/msa/i5_ld_st.ll @@ -22,6 +22,21 @@ ; CHECK: st.b ; CHECK: .size llvm_mips_ld_b_test ; + +define void @llvm_mips_ld_b_unaligned_test() nounwind { +entry: + %0 = bitcast <16 x i8>* @llvm_mips_ld_b_ARG to i8* + %1 = tail call <16 x i8> @llvm.mips.ld.b(i8* %0, i32 9) + store <16 x i8> %1, <16 x i8>* @llvm_mips_ld_b_RES + ret void +} + +; CHECK: llvm_mips_ld_b_unaligned_test: +; CHECK: ld.b [[R1:\$w[0-9]+]], 9( +; CHECK: st.b +; CHECK: .size llvm_mips_ld_b_unaligned_test +; + @llvm_mips_ld_h_ARG = global <8 x i16> , align 16 @llvm_mips_ld_h_RES = global <8 x i16> , align 16 @@ -40,6 +55,21 @@ ; CHECK: st.h ; CHECK: .size llvm_mips_ld_h_test ; + +define void @llvm_mips_ld_h_unaligned_test() nounwind { +entry: + %0 = bitcast <8 x i16>* @llvm_mips_ld_h_ARG to i8* + %1 = tail call <8 x i16> @llvm.mips.ld.h(i8* %0, i32 9) + store <8 x i16> %1, <8 x i16>* @llvm_mips_ld_h_RES + ret void +} + +; CHECK: llvm_mips_ld_h_unaligned_test: +; CHECK: ld.h [[R1:\$w[0-9]+]], 10( +; CHECK: st.h +; CHECK: .size llvm_mips_ld_h_unaligned_test +; + @llvm_mips_ld_w_ARG = global <4 x i32> , align 16 @llvm_mips_ld_w_RES = global <4 x i32> , align 16 @@ -61,6 +91,20 @@ @llvm_mips_ld_d_ARG = global <2 x i64> , align 16 @llvm_mips_ld_d_RES = global <2 x i64> , align 16 +define void @llvm_mips_ld_w_unaligned_test() nounwind { +entry: + %0 = bitcast <4 x i32>* @llvm_mips_ld_w_ARG to i8* + %1 = tail call <4 x i32> @llvm.mips.ld.w(i8* %0, i32 9) + store <4 x i32> %1, <4 x i32>* @llvm_mips_ld_w_RES + ret void +} + +; CHECK: llvm_mips_ld_w_unaligned_test: +; CHECK: ld.w [[R1:\$w[0-9]+]], 12( +; CHECK: st.w +; CHECK: .size llvm_mips_ld_w_unaligned_test +; + define void @llvm_mips_ld_d_test() nounwind { entry: %0 = bitcast <2 x i64>* @llvm_mips_ld_d_ARG to i8* @@ -76,6 +120,21 @@ ; CHECK: st.d ; CHECK: .size llvm_mips_ld_d_test ; + +define void @llvm_mips_ld_d_unaligned_ttest() nounwind { +entry: + %0 = bitcast <2 x i64>* @llvm_mips_ld_d_ARG to i8* + %1 = tail call <2 x i64> @llvm.mips.ld.d(i8* %0, i32 9) + store <2 x i64> %1, <2 x i64>* @llvm_mips_ld_d_RES + ret void +} + +; CHECK: llvm_mips_ld_d_unaligned_ttest: +; CHECK: ld.d [[R1:\$w[0-9]+]], 16( +; CHECK: st.d +; CHECK: .size llvm_mips_ld_d_unaligned_ttest +; + @llvm_mips_st_b_ARG = global <16 x i8> , align 16 @llvm_mips_st_b_RES = global <16 x i8> , align 16 @@ -94,6 +153,21 @@ ; CHECK: st.b [[R1:\$w[0-9]+]], 16( ; CHECK: .size llvm_mips_st_b_test ; + +define void @llvm_mips_st_b_unaligned_test() nounwind { +entry: + %0 = load <16 x i8>, <16 x i8>* @llvm_mips_st_b_ARG + %1 = bitcast <16 x i8>* @llvm_mips_st_b_RES to i8* + tail call void @llvm.mips.st.b(<16 x i8> %0, i8* %1, i32 9) + ret void +} + +; CHECK: llvm_mips_st_b_unaligned_test: +; CHECK: ld.b +; CHECK: st.b [[R1:\$w[0-9]+]], 9( +; CHECK: .size llvm_mips_st_b_unaligned_test +; + @llvm_mips_st_h_ARG = global <8 x i16> , align 16 @llvm_mips_st_h_RES = global <8 x i16> , align 16 @@ -112,6 +186,21 @@ ; CHECK: st.h [[R1:\$w[0-9]+]], 16( ; CHECK: .size llvm_mips_st_h_test ; + +define void @llvm_mips_st_h_unaligned_test() nounwind { +entry: + %0 = load <8 x i16>, <8 x i16>* @llvm_mips_st_h_ARG + %1 = bitcast <8 x i16>* @llvm_mips_st_h_RES to i8* + tail call void @llvm.mips.st.h(<8 x i16> %0, i8* %1, i32 9) + ret void +} + +; CHECK: llvm_mips_st_h_unaligned_test: +; CHECK: ld.h +; CHECK: st.h [[R1:\$w[0-9]+]], 10( +; CHECK: .size llvm_mips_st_h_unaligned_test +; + @llvm_mips_st_w_ARG = global <4 x i32> , align 16 @llvm_mips_st_w_RES = global <4 x i32> , align 16 @@ -130,6 +219,21 @@ ; CHECK: st.w [[R1:\$w[0-9]+]], 16( ; CHECK: .size llvm_mips_st_w_test ; + +define void @llvm_mips_st_w_unaligned_test() nounwind { +entry: + %0 = load <4 x i32>, <4 x i32>* @llvm_mips_st_w_ARG + %1 = bitcast <4 x i32>* @llvm_mips_st_w_RES to i8* + tail call void @llvm.mips.st.w(<4 x i32> %0, i8* %1, i32 9) + ret void +} + +; CHECK: llvm_mips_st_w_unaligned_test: +; CHECK: ld.w +; CHECK: st.w [[R1:\$w[0-9]+]], 12( +; CHECK: .size llvm_mips_st_w_unaligned_test +; + @llvm_mips_st_d_ARG = global <2 x i64> , align 16 @llvm_mips_st_d_RES = global <2 x i64> , align 16 @@ -148,3 +252,17 @@ ; CHECK: st.d [[R1:\$w[0-9]+]], 16( ; CHECK: .size llvm_mips_st_d_test ; + +define void @llvm_mips_st_d_unaligned_test() nounwind { +entry: + %0 = load <2 x i64>, <2 x i64>* @llvm_mips_st_d_ARG + %1 = bitcast <2 x i64>* @llvm_mips_st_d_RES to i8* + tail call void @llvm.mips.st.d(<2 x i64> %0, i8* %1, i32 9) + ret void +} + +; CHECK: llvm_mips_st_d_unaligned_test: +; CHECK: ld.d +; CHECK: st.d [[R1:\$w[0-9]+]], 16( +; CHECK: .size llvm_mips_st_d_unaligned_test +;