From dd190243ee67e488521ab8eac52fa1fc96cb0651 Mon Sep 17 00:00:00 2001 From: Reed Kotler Date: Sat, 11 Oct 2014 00:55:18 +0000 Subject: [PATCH] Add basic conditional branches in mips fast-isel Summary: Implement the most basic form of conditional branches in Mips fast-isel. Test Plan: br1.ll run 4 flavors of test-suite. mips32 r1/r2 and at -O0/O2 Reviewers: dsanders Reviewed By: dsanders Subscribers: llvm-commits, rfuhler Differential Revision: http://reviews.llvm.org/D5583 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219556 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsFastISel.cpp | 55 ++++++++++++++++++++++++++---- test/CodeGen/Mips/Fast-ISel/br1.ll | 34 ++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 test/CodeGen/Mips/Fast-ISel/br1.ll diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index c7ba4add3e5..27773b02597 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -77,7 +77,9 @@ private: unsigned Alignment = 0); bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr, unsigned Alignment = 0); + bool EmitCmp(unsigned DestReg, const CmpInst *CI); bool SelectLoad(const Instruction *I); + bool SelectBranch(const Instruction *I); bool SelectRet(const Instruction *I); bool SelectStore(const Instruction *I); bool SelectIntExt(const Instruction *I); @@ -353,6 +355,38 @@ bool MipsFastISel::EmitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, return true; } +// +// This can cause a redundant sltiu to be generated. +// FIXME: try and eliminate this in a future patch. +// +bool MipsFastISel::SelectBranch(const Instruction *I) { + const BranchInst *BI = cast(I); + MachineBasicBlock *BrBB = FuncInfo.MBB; + // + // TBB is the basic block for the case where the comparison is true. + // FBB is the basic block for the case where the comparison is false. + // if (cond) goto TBB + // goto FBB + // TBB: + // + MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; + MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; + BI->getCondition(); + // For now, just try the simplest case where it's fed by a compare. + if (const CmpInst *CI = dyn_cast(BI->getCondition())) { + unsigned CondReg = createResultReg(&Mips::GPR32RegClass); + if (!EmitCmp(CondReg, CI)) + return false; + BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) + .addReg(CondReg) + .addMBB(TBB); + fastEmitBranch(FBB, DbgLoc); + FuncInfo.MBB->addSuccessor(TBB); + return true; + } + return false; +} + bool MipsFastISel::SelectLoad(const Instruction *I) { // Atomic loads need special handling. if (cast(I)->isAtomic()) @@ -560,25 +594,22 @@ bool MipsFastISel::SelectFPToI(const Instruction *I, bool IsSigned) { updateValueMap(I, DestReg); return true; } - // -// Because of how SelectCmp is called with fast-isel, you can +// Because of how EmitCmp is called with fast-isel, you can // end up with redundant "andi" instructions after the sequences emitted below. // We should try and solve this issue in the future. // -bool MipsFastISel::SelectCmp(const Instruction *I) { - const CmpInst *CI = cast(I); +bool MipsFastISel::EmitCmp(unsigned ResultReg, const CmpInst *CI) { + const Value *Left = CI->getOperand(0), *Right = CI->getOperand(1); bool IsUnsigned = CI->isUnsigned(); - const Value *Left = I->getOperand(0), *Right = I->getOperand(1); - unsigned LeftReg = getRegEnsuringSimpleIntegerWidening(Left, IsUnsigned); if (LeftReg == 0) return false; unsigned RightReg = getRegEnsuringSimpleIntegerWidening(Right, IsUnsigned); if (RightReg == 0) return false; - unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); CmpInst::Predicate P = CI->getPredicate(); + switch (P) { default: return false; @@ -689,6 +720,14 @@ bool MipsFastISel::SelectCmp(const Instruction *I) { break; } } + return true; +} + +bool MipsFastISel::SelectCmp(const Instruction *I) { + const CmpInst *CI = cast(I); + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!EmitCmp(ResultReg, CI)) + return false; updateValueMap(I, ResultReg); return true; } @@ -703,6 +742,8 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) { return SelectLoad(I); case Instruction::Store: return SelectStore(I); + case Instruction::Br: + return SelectBranch(I); case Instruction::Ret: return SelectRet(I); case Instruction::Trunc: diff --git a/test/CodeGen/Mips/Fast-ISel/br1.ll b/test/CodeGen/Mips/Fast-ISel/br1.ll new file mode 100644 index 00000000000..579a77f88fe --- /dev/null +++ b/test/CodeGen/Mips/Fast-ISel/br1.ll @@ -0,0 +1,34 @@ +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \ +; RUN: < %s | FileCheck %s +; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32 \ +; RUN: < %s | FileCheck %s + +@b = global i32 1, align 4 +@i = global i32 0, align 4 +@.str = private unnamed_addr constant [5 x i8] c"%i \0A\00", align 1 + +; Function Attrs: nounwind +define void @br() #0 { +entry: + %0 = load i32* @b, align 4 + %tobool = icmp eq i32 %0, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + store i32 6754, i32* @i, align 4 + br label %if.end + +if.end: ; preds = %entry, %if.then + ret void +; FIXME: This instruction is redundant. +; CHECK: xor $[[REG1:[0-9]+]], ${{[0-9]+}}, $zero +; CHECK: sltiu $[[REG2:[0-9]+]], $[[REG1]], 1 +; CHECK: bgtz $[[REG2]], $BB[[BL:[0-9]+_[0-9]+]] +; CHECK: nop +; CHECK: addiu ${{[0-9]+}}, $zero, 6754 +; CHECK: sw ${{[0-9]+}}, 0(${{[0-9]+}}) +; CHECK: $BB[[BL]]: + +} + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -- 2.34.1