diff options
| author | Bill Wendling <isanbard@gmail.com> | 2008-12-09 23:19:12 +0000 |
|---|---|---|
| committer | Bill Wendling <isanbard@gmail.com> | 2008-12-09 23:19:12 +0000 |
| commit | 8008cb9a770efbd58d9716f020f6e082fb10fdf5 (patch) | |
| tree | ed51af07e938602b5e61dbdf1fe54bb3e3e69116 | |
| parent | 2d170896ee45030a5de0aa150c6629945f367e29 (diff) | |
| download | bcm5719-llvm-8008cb9a770efbd58d9716f020f6e082fb10fdf5.tar.gz bcm5719-llvm-8008cb9a770efbd58d9716f020f6e082fb10fdf5.zip | |
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.
llvm-svn: 60807
| -rw-r--r-- | llvm/lib/Target/X86/X86FastISel.cpp | 63 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/add-with-overflow.ll | 2 |
2 files changed, 65 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 1538439fadd..9783c26097d 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/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/llvm/test/CodeGen/X86/add-with-overflow.ll b/llvm/test/CodeGen/X86/add-with-overflow.ll index ffab94ba9dc..baf577168c1 100644 --- a/llvm/test/CodeGen/X86/add-with-overflow.ll +++ b/llvm/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" |

