aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2008-12-09 23:19:12 +0000
committerBill Wendling <isanbard@gmail.com>2008-12-09 23:19:12 +0000
commit30a64a76492b6a92ccf6d6a6ac907ff8b2b18305 (patch)
tree2219ece0baac739d86b78ed1db234644710f007a
parent54e4c36a7349e94a84773afb56eccd4ca65b49e9 (diff)
Implement fast-isel conversion of a branch instruction that's branching on an
overflow/carry from the "arithmetic with overflow" intrinsics. It searches the machine basic block from bottom to top to find the SETO/SETC instruction that is its conditional. If an instruction modifies EFLAGS before it reaches the SETO/SETC instruction, then it defaults to the normal instruction emission. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60807 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86FastISel.cpp63
-rw-r--r--test/CodeGen/X86/add-with-overflow.ll2
2 files changed, 65 insertions, 0 deletions
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 1538439fad..9783c26097 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -748,6 +748,69 @@ bool X86FastISel::X86SelectBranch(Instruction *I) {
MBB->addSuccessor(TrueMBB);
return true;
}
+ } else if (ExtractValueInst *EI =
+ dyn_cast<ExtractValueInst>(BI->getCondition())) {
+ // Check to see if the branch instruction is from an "arithmetic with
+ // overflow" intrinsic. The main way these intrinsics are used is:
+ //
+ // %t = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %v1, i32 %v2)
+ // %sum = extractvalue { i32, i1 } %t, 0
+ // %obit = extractvalue { i32, i1 } %t, 1
+ // br i1 %obit, label %overflow, label %normal
+ //
+ // The %sum and %obit are converted in an ADD and a SETO/SETC before
+ // reaching the branch. Therefore, we search backwards through the MBB
+ // looking for the SETO/SETC instruction. If an instruction modifies the
+ // EFLAGS register before we reach the SETO/SETC instruction, then we can't
+ // convert the branch into a JO/JC instruction.
+ const MachineInstr *SetMI = 0;
+ unsigned Reg = lookUpRegForValue(EI);
+
+ for (MachineBasicBlock::const_reverse_iterator
+ RI = MBB->rbegin(), RE = MBB->rend(); RI != RE; ++RI) {
+ const MachineInstr &MI = *RI;
+
+ if (MI.modifiesRegister(Reg)) {
+ unsigned Src, Dst;
+
+ if (getInstrInfo()->isMoveInstr(MI, Src, Dst)) {
+ Reg = Src;
+ continue;
+ }
+
+ SetMI = &MI;
+ break;
+ }
+
+ const TargetInstrDesc &TID = MI.getDesc();
+ const unsigned *ImpDefs = TID.getImplicitDefs();
+
+ if (TID.hasUnmodeledSideEffects()) break;
+
+ bool ModifiesEFlags = false;
+
+ if (ImpDefs) {
+ for (unsigned u = 0; ImpDefs[u]; ++u)
+ if (ImpDefs[u] == X86::EFLAGS) {
+ ModifiesEFlags = true;
+ break;
+ }
+ }
+
+ if (ModifiesEFlags) break;
+ }
+
+ if (SetMI) {
+ unsigned OpCode = SetMI->getOpcode();
+
+ if (OpCode == X86::SETOr || OpCode == X86::SETCr) {
+ BuildMI(MBB, TII.get((OpCode == X86::SETOr) ?
+ X86::JO : X86::JC)).addMBB(TrueMBB);
+ FastEmitBranch(FalseMBB);
+ MBB->addSuccessor(TrueMBB);
+ return true;
+ }
+ }
}
// Otherwise do a clumsy setcc and re-test it.
diff --git a/test/CodeGen/X86/add-with-overflow.ll b/test/CodeGen/X86/add-with-overflow.ll
index ffab94ba9d..baf577168c 100644
--- a/test/CodeGen/X86/add-with-overflow.ll
+++ b/test/CodeGen/X86/add-with-overflow.ll
@@ -1,5 +1,7 @@
; RUN: llvm-as < %s | llc -march=x86 | grep {jo} | count 1
; RUN: llvm-as < %s | llc -march=x86 | grep {jc} | count 1
+; RUN: llvm-as < %s | llc -march=x86 -fast | grep {jo} | count 1
+; RUN: llvm-as < %s | llc -march=x86 -fast | grep {jc} | count 1
@ok = internal constant [4 x i8] c"%d\0A\00"
@no = internal constant [4 x i8] c"no\0A\00"