From 06e16587ebc81e43b42157fa3afcfd806b59b296 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 10 Jul 2009 01:54:42 +0000 Subject: [PATCH] Add a thumb2 pass to insert IT blocks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75218 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARM.h | 2 + lib/Target/ARM/ARMInstrThumb.td | 9 -- lib/Target/ARM/ARMInstrThumb2.td | 16 +++ lib/Target/ARM/ARMTargetMachine.cpp | 3 + lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 2 +- lib/Target/ARM/Thumb2ITBlockPass.cpp | 108 ++++++++++++++++++++ test/CodeGen/Thumb2/thumb2-select.ll | 1 + test/CodeGen/Thumb2/thumb2-select_xform.ll | 1 + 8 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 lib/Target/ARM/Thumb2ITBlockPass.cpp diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 12c26e8c795..0e654d8e64d 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -108,6 +108,8 @@ FunctionPass *createARMObjectCodeEmitterPass(ARMBaseTargetMachine &TM, FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); FunctionPass *createARMConstantIslandPass(); +FunctionPass *createThumb2ITBlockPass(); + } // end namespace llvm; // Defines symbolic names for ARM registers. This defines a mapping from diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 5642710b5ca..fb7453a912b 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -66,11 +66,6 @@ def thumb_immshifted_shamt : SDNodeXFormgetTargetConstant(V, MVT::i32); }]>; -// IT block condition mask -def it_mask : Operand { - let PrintMethod = "printThumbITMask"; -} - // Define Thumb specific addressing modes. // t_addrmode_rr := reg + reg @@ -212,10 +207,6 @@ let isBranch = 1, isTerminator = 1 in def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), "b$cc $target", [/*(ARMbrcond bb:$target, imm:$cc)*/]>; -// IT block -def tIT : TI<(outs), (ins pred:$cc, it_mask:$mask), - "it$mask $cc", []>; - //===----------------------------------------------------------------------===// // Load Store Instructions. // diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index be738310729..34ce53f97f1 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -11,6 +11,16 @@ // //===----------------------------------------------------------------------===// +// IT block predicate field +def it_pred : Operand { + let PrintMethod = "printPredicateOperand"; +} + +// IT block condition mask +def it_mask : Operand { + let PrintMethod = "printThumbITMask"; +} + // Shifted operands. No register controlled shifts for Thumb2. // Note: We do not support rrx shifted operands yet. def t2_so_reg : Operand, // reg imm @@ -1121,6 +1131,12 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), "b", " $target", [/*(ARMbrcond bb:$target, imm:$cc)*/]>; + +// IT block +def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), + AddrModeNone, Size2Bytes, + "it$mask $cc", "", []>; + //===----------------------------------------------------------------------===// // Non-Instruction Patterns // diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index b3faadafc5a..a8277843833 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -173,6 +173,9 @@ bool ARMBaseTargetMachine::addPreEmitPass(PassManagerBase &PM, !DisableIfConversion && !Subtarget.isThumb()) PM.add(createIfConverterPass()); + if (Subtarget.isThumb2()) + PM.add(createThumb2ITBlockPass()); + PM.add(createARMConstantIslandPass()); return true; } diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index b298ff7715c..3b1c491ef1a 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -642,7 +642,7 @@ ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) { unsigned Mask = MI->getOperand(Op).getImm(); unsigned NumTZ = CountTrailingZeros_32(Mask); assert(NumTZ <= 3 && "Invalid IT mask!"); - for (unsigned Pos = 3, e = NumTZ; Pos >= e; --Pos) { + for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) { bool T = (Mask & (1 << Pos)) != 0; if (T) O << 't'; diff --git a/lib/Target/ARM/Thumb2ITBlockPass.cpp b/lib/Target/ARM/Thumb2ITBlockPass.cpp new file mode 100644 index 00000000000..f6f75a1a4b8 --- /dev/null +++ b/lib/Target/ARM/Thumb2ITBlockPass.cpp @@ -0,0 +1,108 @@ +//===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "thumb2-it" +#include "ARM.h" +#include "ARMInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumITs, "Number of IT blocks inserted"); + +namespace { + struct VISIBILITY_HIDDEN Thumb2ITBlockPass : public MachineFunctionPass { + static char ID; + Thumb2ITBlockPass() : MachineFunctionPass(&ID) {} + + const ARMBaseInstrInfo *TII; + ARMFunctionInfo *AFI; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "Thumb IT blocks insertion pass"; + } + + private: + bool InsertITBlocks(MachineBasicBlock &MBB); + }; + char Thumb2ITBlockPass::ID = 0; +} + +bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + MachineInstr *MI = &*MBBI; + ARMCC::CondCodes CC = TII->getPredicate(MI); + if (CC == ARMCC::AL) { + ++MBBI; + continue; + } + + // Insert an IT instruction. + DebugLoc dl = MI->getDebugLoc(); + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) + .addImm(CC); + ++MBBI; + + // Finalize IT mask. If the following instruction is not predicated or it's + // predicated on a condition that's not the same or the opposite of CC, then + // the mask is 0x8. + ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); + unsigned Mask = 0x8; + while (MBBI != E || (Mask & 1)) { + ARMCC::CondCodes NCC = TII->getPredicate(&*MBBI); + if (NCC == CC) { + Mask >>= 1; + Mask |= 0x8; + } else if (NCC == OCC) { + Mask >>= 1; + } else { + break; + } + ++MBBI; + } + MIB.addImm(Mask); + Modified = true; + ++NumITs; + } + + return Modified; +} + +bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { + const TargetMachine &TM = Fn.getTarget(); + AFI = Fn.getInfo(); + TII = static_cast(TM.getInstrInfo()); + + if (!AFI->isThumbFunction()) + return false; + + bool Modified = false; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + Modified |= InsertITBlocks(MBB); + } + + return Modified; +} + +/// createThumb2ITBlockPass - returns and instance of the Thumb IT blocks +/// insertion pass. +FunctionPass *llvm::createThumb2ITBlockPass() { + return new Thumb2ITBlockPass(); +} diff --git a/test/CodeGen/Thumb2/thumb2-select.ll b/test/CodeGen/Thumb2/thumb2-select.ll index 57f61569c19..1d51bc39561 100644 --- a/test/CodeGen/Thumb2/thumb2-select.ll +++ b/test/CodeGen/Thumb2/thumb2-select.ll @@ -4,6 +4,7 @@ ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movle | count 1 ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movls | count 1 ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep movhi | count 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep it | count 6 define i32 @f1(i32 %a.s) { entry: diff --git a/test/CodeGen/Thumb2/thumb2-select_xform.ll b/test/CodeGen/Thumb2/thumb2-select_xform.ll index 9da4ebe17d2..5332c2d6e9b 100644 --- a/test/CodeGen/Thumb2/thumb2-select_xform.ll +++ b/test/CodeGen/Thumb2/thumb2-select_xform.ll @@ -1,5 +1,6 @@ ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | count 3 ; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mvn | count 1 +; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep it | count 3 define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind { %tmp1 = icmp sgt i32 %c, 10