Index: lib/Target/Mips/MipsFastISel.cpp =================================================================== --- lib/Target/Mips/MipsFastISel.cpp +++ lib/Target/Mips/MipsFastISel.cpp @@ -1337,6 +1337,68 @@ switch (II->getIntrinsicID()) { default: return false; + case Intrinsic::bswap: { + Type *RetTy = II->getCalledFunction()->getReturnType(); + + MVT VT; + if (!isTypeSupported(RetTy, VT)) + return false; + + unsigned SrcReg = getRegForValue(II->getOperand(0)); + if (SrcReg == 0) + return false; + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + if (DestReg == 0) + return false; + if (VT == MVT::i16) { + if (Subtarget->hasMips32r2()) { + emitInst(Mips::WSBH, DestReg).addReg(SrcReg); + updateValueMap(II, DestReg); + return true; + } else { + unsigned TempReg[3]; + for (int i = 0; i < 3; i++) { + TempReg[i] = createResultReg(&Mips::GPR32RegClass); + if (TempReg[i] == 0) + return false; + } + emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8); + emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8); + emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]); + emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF); + updateValueMap(II, DestReg); + return true; + } + } else if (VT == MVT::i32) { + if (Subtarget->hasMips32r2()) { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::WSBH, TempReg).addReg(SrcReg); + emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16); + updateValueMap(II, DestReg); + return true; + } else { + unsigned TempReg[9]; + for (int i = 0; i < 9; i++) { + TempReg[i] = createResultReg(&Mips::GPR32RegClass); + if (TempReg[i] == 0) + return false; + } + emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8); + emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24); + emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00); + emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]); + emitInst(Mips::SLL, TempReg[4]).addReg(SrcReg).addImm(8); + emitInst(Mips::LUi, TempReg[5]).addImm(0xFF); + emitInst(Mips::AND, TempReg[6]).addReg(TempReg[4]).addReg(TempReg[5]); + emitInst(Mips::SLL, TempReg[7]).addReg(SrcReg).addImm(24); + emitInst(Mips::OR, TempReg[8]).addReg(TempReg[3]).addReg(TempReg[6]); + emitInst(Mips::OR, DestReg).addReg(TempReg[7]).addReg(TempReg[8]); + updateValueMap(II, DestReg); + return true; + } + } + return false; + } case Intrinsic::memcpy: case Intrinsic::memmove: { const auto *MTI = cast(II); Index: test/CodeGen/Mips/Fast-ISel/bswap1.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/Fast-ISel/bswap1.ll @@ -0,0 +1,103 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32r2 +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s -check-prefix=mips32 + +@a = global i16 -21829, align 2 +@b = global i32 -1430532899, align 4 +@a1 = common global i16 0, align 2 +@b1 = common global i32 0, align 4 + +; Function Attrs: nounwind +define void @b16() #0 { +entry: +; mips32: .ent b16 +; mips32r2: .ent b16 + %0 = load i16* @a, align 2 + %1 = call i16 @llvm.bswap.i16(i16 %0) + store i16 %1, i16* @a1, align 2 + ret void +; mips32: lw $[[A_ADDR:[0-9]+]], %got(a)($[[GOT_ADDR:[0-9]+]]) +; mips32: lhu $[[A_VAL:[0-9]+]], 0($[[A_ADDR]]) +; mips32: sll $[[TMP1:[0-9]+]], $[[A_VAL]], 8 +; mips32: srl $[[TMP2:[0-9]+]], $[[A_VAL]], 8 +; mips32: or $[[TMP3:[0-9]+]], $[[TMP1]], $[[TMP2]] +; mips32: andi $[[TMP4:[0-9]+]], $[[TMP3]], 65535 +; mips32r2: lw $[[A_ADDR:[0-9]+]], %got(a)($[[GOT_ADDR:[0-9]+]]) +; mips32r2: lhu $[[A_VAL:[0-9]+]], 0($[[A_ADDR]]) +; mips32r2: wsbh $[[RESULT:[0-9]+]], $[[A_VAL]] + +} + +; Function Attrs: nounwind readnone +declare i16 @llvm.bswap.i16(i16) #1 + +; Function Attrs: nounwind +define void @b32() #0 { +entry: +; mips32: .ent b32 +; mips32r2: .ent b32 + %0 = load i32* @b, align 4 + %1 = call i32 @llvm.bswap.i32(i32 %0) + store i32 %1, i32* @b1, align 4 +; mips32: lw $[[B_ADDR:[0-9]+]], %got(b)($[[GOT_ADDR:[0-9]+]]) +; mips32: lw $[[B_VAL:[0-9]+]], 0($[[B_ADDR]]) +; mips32: srl $[[TMP1:[0-9]+]], $[[B_VAL]], 8 +; mips32: srl $[[TMP3:[0-9]+]], $[[B_VAL]], 24 +; mips32: andi $[[TMP2:[0-9]+]], $[[TMP1]], 65280 +; mips32: or $[[TMP5:[0-9]+]], $[[TMP3]], $[[TMP2]] +; mips32: sll $[[TMP6:[0-9]+]], $[[B_VAL]], 8 +; mips32: lui $[[TMP7:[0-9]+]], 255 +; mips32: and $[[TMP8:[0-9]+]], $[[TMP6]], $[[TMP7]] +; mips32: sll $[[TMP9:[0-9]+]], $[[B_VAL]], 24 +; mips32: or $[[TMP10:[0-9]+]], $[[TMP5]], $[[TMP8]] +; mips32: or $[[RESULT:[0-9]+]], $[[TMP9]], $[[TMP10]] +; mips32r2: lw $[[B_ADDR:[0-9]+]], %got(b)($[[GOT_ADDR:[0-9]+]]) +; mips32r2: lw $[[B_VAL:[0-9]+]], 0($[[B_ADDR]]) +; mips32r2: wsbh $[[TMP:[0-9]+]], $[[B_VAL]] +; mips32r2: rotr $[[RESULT:[0-9]+]], $[[TMP]], 16 + + ret void +} + +; Function Attrs: nounwind readnone +declare i32 @llvm.bswap.i32(i32) #1 + +; Function Attrs: nounwind +define i32 @main() #0 { +entry: + %retval = alloca i32, align 4 + store i32 0, i32* %retval + call void @b16() + call void @b32() + %0 = load i16* @a1, align 2 + %conv = zext i16 %0 to i32 + %cmp = icmp ne i32 %conv, 48042 + br i1 %cmp, label %if.then, label %lor.lhs.false + +lor.lhs.false: ; preds = %entry + %1 = load i32* @b1, align 4 + %cmp2 = icmp ne i32 %1, -573785174 + br i1 %cmp2, label %if.then, label %if.end + +if.then: ; preds = %lor.lhs.false, %entry + call void @abort() #3 + unreachable + +if.end: ; preds = %lor.lhs.false + ret i32 0 +} + +; Function Attrs: noreturn +declare void @abort() #2 + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { noreturn "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { noreturn } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"PIC Level", i32 2} +!1 = !{!"clang version 3.7.0 (gitosis@dmz-portal.mips.com:clang.git 2adf9bd38f42d034c2d9c2ff6ae3fc0c54339f67) (gitosis@dmz-portal.mips.com:llvm.git 9b4ff07be7fcb382b4a506705635acf72044dfce)"}