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);
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<BranchInst>(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<CmpInst>(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<LoadInst>(I)->isAtomic())
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<CmpInst>(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;
break;
}
}
+ return true;
+}
+
+bool MipsFastISel::SelectCmp(const Instruction *I) {
+ const CmpInst *CI = cast<CmpInst>(I);
+ unsigned ResultReg = createResultReg(&Mips::GPR32RegClass);
+ if (!EmitCmp(ResultReg, CI))
+ return false;
updateValueMap(I, ResultReg);
return true;
}
return SelectLoad(I);
case Instruction::Store:
return SelectStore(I);
+ case Instruction::Br:
+ return SelectBranch(I);
case Instruction::Ret:
return SelectRet(I);
case Instruction::Trunc:
--- /dev/null
+; 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" }