[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns created this revision. thomasjohns added a reviewer: marksl. Herald added a subscriber: hiraditya. thomasjohns requested review of this revision. Herald added projects: clang, LLVM. Herald added a subscriber: cfe-commits. Add a CTLZ pseudo instruction to tablegen and the ability to expand this pseudo instruction instruction to ARC assembly code. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D107611 Files: clang/lib/Basic/Targets/ARC.h llvm/lib/Target/ARC/ARCExpandPseudos.cpp llvm/lib/Target/ARC/ARCISelLowering.cpp llvm/lib/Target/ARC/ARCInstrInfo.td llvm/test/CodeGen/ARC/ctlz.ll Index: llvm/test/CodeGen/ARC/ctlz.ll === --- /dev/null +++ llvm/test/CodeGen/ARC/ctlz.ll @@ -0,0 +1,14 @@ +; RUN: llc -march=arc < %s | FileCheck %s + +target triple = "arc" + +declare i32 @llvm.ctlz.i32(i32, i1) + +; CHECK-LABEL: clz32: +; CHECK: fls.f %r0, %r0 +; CHECK: mov.eq [[R:%r[01]]], 32 +; CHECK: rsub.ne [[R]], [[R]], 31 +define i32 @clz32(i32 %x) { + %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false) + ret i32 %a +} Index: llvm/lib/Target/ARC/ARCInstrInfo.td === --- llvm/lib/Target/ARC/ARCInstrInfo.td +++ llvm/lib/Target/ARC/ARCInstrInfo.td @@ -311,6 +311,13 @@ let Predicates=[HasNorm] in { defm NORM : ArcUnaryEXT5Inst<0b01,"norm">; defm NORMH : ArcUnaryEXT5Inst<0b001000,"normh">; + +// TODO: Add `Requires<[HasBitScan]>` predicate when available. +def CTLZ : PseudoInstARC<(outs GPR32:$A), + (ins GPR32:$B), + "error.fls $A, $B", + [(set GPR32:$A, (ctlz i32:$B))]> { + let Defs = [STATUS32]; } // General Unary Instruction fragments. Index: llvm/lib/Target/ARC/ARCISelLowering.cpp === --- llvm/lib/Target/ARC/ARCISelLowering.cpp +++ llvm/lib/Target/ARC/ARCISelLowering.cpp @@ -135,6 +135,10 @@ // Sign extend inreg setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); + + // TODO: Predicate with `options.hasBitScan() ? Legal : Expand` when + // the HasBitScan predicate is available. + setOperationAction(ISD::CTLZ, MVT::i32, Legal); } const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { Index: llvm/lib/Target/ARC/ARCExpandPseudos.cpp === --- llvm/lib/Target/ARC/ARCExpandPseudos.cpp +++ llvm/lib/Target/ARC/ARCExpandPseudos.cpp @@ -13,6 +13,7 @@ #include "ARCInstrInfo.h" #include "ARCRegisterInfo.h" #include "ARCSubtarget.h" +#include "MCTargetDesc/ARCInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -35,6 +36,7 @@ private: void ExpandStore(MachineFunction &, MachineBasicBlock::iterator); + void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator); const ARCInstrInfo *TII; }; @@ -73,10 +75,45 @@ SI.eraseFromParent(); } +void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF, + MachineBasicBlock::iterator SII) { + // Expand: + // %R2 = CTLZ %R0, %STATUS + // To: + // %R2 = FLS_f_rr %R0, %STATUS + // %R2 = MOV_cc_ru6 %R2, 32, pred:1, %STATUS + // %R2 = RSUB_cc_rru6 %R2, 31, pred:2, %STATUS + MachineInstr &SI = *SII; + const MachineOperand &Dest = SI.getOperand(0); + assert(Dest.isReg()); + const MachineOperand &Src = SI.getOperand(1); + assert(Src.isReg()); + unsigned DestReg = Dest.getReg(); + + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::FLS_f_rr), + DestReg) + .add(Src) + .addReg(ARC::STATUS32, RegState::ImplicitDefine); + + unsigned Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + unsigned Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Ra) + .addImm(32) + .addImm(ARCCC::EQ) + .addReg(DestReg); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6), + Rb) + .addImm(31) + .addImm(ARCCC::NE) + .addReg(Ra); + + SI.eraseFromParent(); +} + bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) { const ARCSubtarget *STI = &MF.getSubtarget(); TII = STI->getInstrInfo(); - bool ExpandedStore = false; + bool Expanded = false; for (auto &MBB : MF) { MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { @@ -86,7 +123,11 @@ case ARC::STH_FAR: case ARC::STB_FAR: ExpandStore(MF, MBBI); -ExpandedStore = true; +Expanded = true; +break; + case ARC::CTLZ: +ExpandCTLZ(MF, MBBI); +Expanded = true; break; default: break; @@ -94,7 +135,7 @@ MBBI = NMBBI; } } - return ExpandedStore; + re
[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns added inline comments. Comment at: llvm/lib/Target/ARC/ARCInstrInfo.td:314 defm NORMH : ArcUnaryEXT5Inst<0b001000,"normh">; + +// TODO: Add `Requires<[HasBitScan]>` predicate when available. I just realized I made a bad merge here and dropped the `}`. Fixing it now. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D107611/new/ https://reviews.llvm.org/D107611 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns added inline comments. Comment at: llvm/lib/Target/ARC/ARCInstrInfo.td:314 defm NORMH : ArcUnaryEXT5Inst<0b001000,"normh">; + +// TODO: Add `Requires<[HasBitScan]>` predicate when available. thomasjohns wrote: > I just realized I made a bad merge here and dropped the `}`. Fixing it now. I'll also move this pseudo instruction to be next to the other pseudo instructions Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D107611/new/ https://reviews.llvm.org/D107611 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns updated this revision to Diff 364657. thomasjohns added a comment. Fix missing `}` after bad merge. Move CTLZ next to other pseudo instructions. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D107611/new/ https://reviews.llvm.org/D107611 Files: clang/lib/Basic/Targets/ARC.h llvm/lib/Target/ARC/ARCExpandPseudos.cpp llvm/lib/Target/ARC/ARCISelLowering.cpp llvm/lib/Target/ARC/ARCInstrInfo.td llvm/test/CodeGen/ARC/ctlz.ll Index: llvm/test/CodeGen/ARC/ctlz.ll === --- /dev/null +++ llvm/test/CodeGen/ARC/ctlz.ll @@ -0,0 +1,14 @@ +; RUN: llc -march=arc < %s | FileCheck %s + +target triple = "arc" + +declare i32 @llvm.ctlz.i32(i32, i1) + +; CHECK-LABEL: clz32: +; CHECK: fls.f %r0, %r0 +; CHECK: mov.eq [[R:%r[01]]], 32 +; CHECK: rsub.ne [[R]], [[R]], 31 +define i32 @clz32(i32 %x) { + %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false) + ret i32 %a +} Index: llvm/lib/Target/ARC/ARCInstrInfo.td === --- llvm/lib/Target/ARC/ARCInstrInfo.td +++ llvm/lib/Target/ARC/ARCInstrInfo.td @@ -133,6 +133,14 @@ "STB_FAR $dst, $addr", [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>; +// TODO: Add `Requires<[HasBitScan]>` predicate when available. +def CTLZ : PseudoInstARC<(outs GPR32:$A), + (ins GPR32:$B), + "error.fls $A, $B", + [(set GPR32:$A, (ctlz i32:$B))]> { + let Defs = [STATUS32]; +} + //===--===// // Instruction Generation multiclasses. // Generate many variants of a single instruction with a single defining Index: llvm/lib/Target/ARC/ARCISelLowering.cpp === --- llvm/lib/Target/ARC/ARCISelLowering.cpp +++ llvm/lib/Target/ARC/ARCISelLowering.cpp @@ -135,6 +135,10 @@ // Sign extend inreg setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); + + // TODO: Predicate with `options.hasBitScan() ? Legal : Expand` when + // the HasBitScan predicate is available. + setOperationAction(ISD::CTLZ, MVT::i32, Legal); } const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { Index: llvm/lib/Target/ARC/ARCExpandPseudos.cpp === --- llvm/lib/Target/ARC/ARCExpandPseudos.cpp +++ llvm/lib/Target/ARC/ARCExpandPseudos.cpp @@ -13,6 +13,7 @@ #include "ARCInstrInfo.h" #include "ARCRegisterInfo.h" #include "ARCSubtarget.h" +#include "MCTargetDesc/ARCInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -35,6 +36,7 @@ private: void ExpandStore(MachineFunction &, MachineBasicBlock::iterator); + void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator); const ARCInstrInfo *TII; }; @@ -73,10 +75,45 @@ SI.eraseFromParent(); } +void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF, + MachineBasicBlock::iterator SII) { + // Expand: + // %R2 = CTLZ %R0, %STATUS + // To: + // %R2 = FLS_f_rr %R0, %STATUS + // %R2 = MOV_cc_ru6 %R2, 32, pred:1, %STATUS + // %R2 = RSUB_cc_rru6 %R2, 31, pred:2, %STATUS + MachineInstr &SI = *SII; + const MachineOperand &Dest = SI.getOperand(0); + assert(Dest.isReg()); + const MachineOperand &Src = SI.getOperand(1); + assert(Src.isReg()); + unsigned DestReg = Dest.getReg(); + + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::FLS_f_rr), + DestReg) + .add(Src) + .addReg(ARC::STATUS32, RegState::ImplicitDefine); + + unsigned Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + unsigned Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Ra) + .addImm(32) + .addImm(ARCCC::EQ) + .addReg(DestReg); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6), + Rb) + .addImm(31) + .addImm(ARCCC::NE) + .addReg(Ra); + + SI.eraseFromParent(); +} + bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) { const ARCSubtarget *STI = &MF.getSubtarget(); TII = STI->getInstrInfo(); - bool ExpandedStore = false; + bool Expanded = false; for (auto &MBB : MF) { MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { @@ -86,7 +123,11 @@ case ARC::STH_FAR: case ARC::STB_FAR: ExpandStore(MF, MBBI); -ExpandedStore = true; +Expanded = true; +break; + case ARC::CTLZ: +ExpandCTLZ(MF, MBBI); +Expanded = true; break; default: break; @@ -94,7 +135,7 @@ MBBI = NMBBI; } } - return ExpandedStore; + return Expanded; } F
[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns updated this revision to Diff 364806. thomasjohns added a comment. llvm clang-tidy rule: prefer `Register` over `unsinged int`. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D107611/new/ https://reviews.llvm.org/D107611 Files: clang/lib/Basic/Targets/ARC.h llvm/lib/Target/ARC/ARCExpandPseudos.cpp llvm/lib/Target/ARC/ARCISelLowering.cpp llvm/lib/Target/ARC/ARCInstrInfo.td llvm/test/CodeGen/ARC/ctlz.ll Index: llvm/test/CodeGen/ARC/ctlz.ll === --- /dev/null +++ llvm/test/CodeGen/ARC/ctlz.ll @@ -0,0 +1,14 @@ +; RUN: llc -march=arc < %s | FileCheck %s + +target triple = "arc" + +declare i32 @llvm.ctlz.i32(i32, i1) + +; CHECK-LABEL: clz32: +; CHECK: fls.f %r0, %r0 +; CHECK: mov.eq [[R:%r[01]]], 32 +; CHECK: rsub.ne [[R]], [[R]], 31 +define i32 @clz32(i32 %x) { + %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false) + ret i32 %a +} Index: llvm/lib/Target/ARC/ARCInstrInfo.td === --- llvm/lib/Target/ARC/ARCInstrInfo.td +++ llvm/lib/Target/ARC/ARCInstrInfo.td @@ -133,6 +133,14 @@ "STB_FAR $dst, $addr", [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>; +// TODO: Add `Requires<[HasBitScan]>` predicate when available. +def CTLZ : PseudoInstARC<(outs GPR32:$A), + (ins GPR32:$B), + "error.fls $A, $B", + [(set GPR32:$A, (ctlz i32:$B))]> { + let Defs = [STATUS32]; +} + //===--===// // Instruction Generation multiclasses. // Generate many variants of a single instruction with a single defining Index: llvm/lib/Target/ARC/ARCISelLowering.cpp === --- llvm/lib/Target/ARC/ARCISelLowering.cpp +++ llvm/lib/Target/ARC/ARCISelLowering.cpp @@ -135,6 +135,10 @@ // Sign extend inreg setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); + + // TODO: Predicate with `options.hasBitScan() ? Legal : Expand` when + // the HasBitScan predicate is available. + setOperationAction(ISD::CTLZ, MVT::i32, Legal); } const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { Index: llvm/lib/Target/ARC/ARCExpandPseudos.cpp === --- llvm/lib/Target/ARC/ARCExpandPseudos.cpp +++ llvm/lib/Target/ARC/ARCExpandPseudos.cpp @@ -13,6 +13,7 @@ #include "ARCInstrInfo.h" #include "ARCRegisterInfo.h" #include "ARCSubtarget.h" +#include "MCTargetDesc/ARCInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -35,6 +36,7 @@ private: void ExpandStore(MachineFunction &, MachineBasicBlock::iterator); + void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator); const ARCInstrInfo *TII; }; @@ -59,8 +61,8 @@ void ARCExpandPseudos::ExpandStore(MachineFunction &MF, MachineBasicBlock::iterator SII) { MachineInstr &SI = *SII; - unsigned AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); - unsigned AddOpc = + Register AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + Register AddOpc = isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm; BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg) .addReg(SI.getOperand(1).getReg()) @@ -73,10 +75,45 @@ SI.eraseFromParent(); } +void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF, + MachineBasicBlock::iterator SII) { + // Expand: + // %R2 = CTLZ %R0, %STATUS + // To: + // %R2 = FLS_f_rr %R0, %STATUS + // %R2 = MOV_cc_ru6 %R2, 32, pred:1, %STATUS + // %R2 = RSUB_cc_rru6 %R2, 31, pred:2, %STATUS + MachineInstr &SI = *SII; + const MachineOperand &Dest = SI.getOperand(0); + assert(Dest.isReg()); + const MachineOperand &Src = SI.getOperand(1); + assert(Src.isReg()); + Register DestReg = Dest.getReg(); + + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::FLS_f_rr), + DestReg) + .add(Src) + .addReg(ARC::STATUS32, RegState::ImplicitDefine); + + Register Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + Register Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Ra) + .addImm(32) + .addImm(ARCCC::EQ) + .addReg(DestReg); + BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6), + Rb) + .addImm(31) + .addImm(ARCCC::NE) + .addReg(Ra); + + SI.eraseFromParent(); +} + bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) { const ARCSubtarget *STI = &MF.getSubtarget(); TII = STI->getInstrInfo(); - bool ExpandedStore =
[PATCH] D107611: [ARC] Add codegen for llvm.ctlz intrinsic for the ARC backend
thomasjohns updated this revision to Diff 364855. thomasjohns added a comment. Thanks for the feedback, Mark. This change prefers `MI` over `SI` naming, updates instruction writing, and makes the test case more precise (the generated code was improved and no longer had an unneeded `mov %r1, %r0`. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D107611/new/ https://reviews.llvm.org/D107611 Files: clang/lib/Basic/Targets/ARC.h llvm/lib/Target/ARC/ARCExpandPseudos.cpp llvm/lib/Target/ARC/ARCISelLowering.cpp llvm/lib/Target/ARC/ARCInstrInfo.td llvm/test/CodeGen/ARC/ctlz.ll Index: llvm/test/CodeGen/ARC/ctlz.ll === --- /dev/null +++ llvm/test/CodeGen/ARC/ctlz.ll @@ -0,0 +1,14 @@ +; RUN: llc -march=arc < %s | FileCheck %s + +target triple = "arc" + +declare i32 @llvm.ctlz.i32(i32, i1) + +; CHECK-LABEL: clz32: +; CHECK: fls.f %r0, %r0 +; CHECK-NEXT: mov.eq %r0, 32 +; CHECK-NEXT: rsub.ne %r0, %r0, 31 +define i32 @clz32(i32 %x) { + %a = call i32 @llvm.ctlz.i32(i32 %x, i1 false) + ret i32 %a +} Index: llvm/lib/Target/ARC/ARCInstrInfo.td === --- llvm/lib/Target/ARC/ARCInstrInfo.td +++ llvm/lib/Target/ARC/ARCInstrInfo.td @@ -133,6 +133,14 @@ "STB_FAR $dst, $addr", [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>; +// TODO: Add `Requires<[HasBitScan]>` predicate when available. +def CTLZ : PseudoInstARC<(outs GPR32:$A), + (ins GPR32:$B), + "error.fls $A, $B", + [(set GPR32:$A, (ctlz i32:$B))]> { + let Defs = [STATUS32]; +} + //===--===// // Instruction Generation multiclasses. // Generate many variants of a single instruction with a single defining Index: llvm/lib/Target/ARC/ARCISelLowering.cpp === --- llvm/lib/Target/ARC/ARCISelLowering.cpp +++ llvm/lib/Target/ARC/ARCISelLowering.cpp @@ -135,6 +135,10 @@ // Sign extend inreg setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); + + // TODO: Predicate with `options.hasBitScan() ? Legal : Expand` when + // the HasBitScan predicate is available. + setOperationAction(ISD::CTLZ, MVT::i32, Legal); } const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { Index: llvm/lib/Target/ARC/ARCExpandPseudos.cpp === --- llvm/lib/Target/ARC/ARCExpandPseudos.cpp +++ llvm/lib/Target/ARC/ARCExpandPseudos.cpp @@ -13,6 +13,7 @@ #include "ARCInstrInfo.h" #include "ARCRegisterInfo.h" #include "ARCSubtarget.h" +#include "MCTargetDesc/ARCInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -35,6 +36,7 @@ private: void ExpandStore(MachineFunction &, MachineBasicBlock::iterator); + void ExpandCTLZ(MachineFunction &, MachineBasicBlock::iterator); const ARCInstrInfo *TII; }; @@ -59,8 +61,8 @@ void ARCExpandPseudos::ExpandStore(MachineFunction &MF, MachineBasicBlock::iterator SII) { MachineInstr &SI = *SII; - unsigned AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); - unsigned AddOpc = + Register AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + Register AddOpc = isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm; BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg) .addReg(SI.getOperand(1).getReg()) @@ -73,10 +75,39 @@ SI.eraseFromParent(); } +void ARCExpandPseudos::ExpandCTLZ(MachineFunction &MF, + MachineBasicBlock::iterator MII) { + // Expand: + // %R2 = CTLZ %R0, %STATUS + // To: + // %R2 = FLS_f_rr %R0, %STATUS + // %R2 = MOV_cc_ru6 %R2, 32, pred:1, %STATUS + // %R2 = RSUB_cc_rru6 %R2, 31, pred:2, %STATUS + MachineInstr &MI = *MII; + const MachineOperand &Dest = MI.getOperand(0); + const MachineOperand &Src = MI.getOperand(1); + Register Ra = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + Register Rb = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass); + + BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::FLS_f_rr), Ra) + .add(Src); + BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::MOV_cc_ru6), Rb) + .addImm(32) + .addImm(ARCCC::EQ) + .addReg(Ra); + BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), TII->get(ARC::RSUB_cc_rru6)) + .add(Dest) + .addImm(31) + .addImm(ARCCC::NE) + .addReg(Rb); + + MI.eraseFromParent(); +} + bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) { const ARCSubtarget *STI = &MF.getSubtarget(); TII = ST