Skip to content

Commit

Permalink
[FastISel][X86] Only fold the cmp into the select when both instructi…
Browse files Browse the repository at this point in the history
…ons are in the same basic block.

If the cmp is in a different basic block, then it is possible that not all
operands of that compare have defined registers. This can happen when one of
the operands to the cmp is a load and the load gets folded into the cmp. In
this case FastISel will skip the load instruction and the vreg is never
defined.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211730 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
ributzka committed Jun 25, 2014
1 parent 91c39aa commit d01f1c4
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
20 changes: 15 additions & 5 deletions lib/Target/X86/X86FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1754,8 +1754,11 @@ bool X86FastISel::X86FastEmitCMoveSelect(const Instruction *I) {
const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
bool NeedTest = true;

// Optimize conditons coming from a compare.
if (const auto *CI = dyn_cast<CmpInst>(Cond)) {
// Optimize conditons coming from a compare if both instructions are in the
// same basic block (values defined in other basic blocks may not have
// initialized registers).
const auto *CI = dyn_cast<CmpInst>(Cond);
if (CI && (CI->getParent() == I->getParent())) {
CmpInst::Predicate Predicate = optimizeCmpPredicate(CI);

// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
Expand Down Expand Up @@ -1927,8 +1930,11 @@ bool X86FastISel::X86FastEmitSSESelect(const Instruction *I) {
if (!isTypeLegal(I->getType(), RetVT))
return false;

// Optimize conditons coming from a compare if both instructions are in the
// same basic block (values defined in other basic blocks may not have
// initialized registers).
const auto *CI = dyn_cast<FCmpInst>(I->getOperand(0));
if (!CI)
if (!CI || (CI->getParent() != I->getParent()))
return false;

if (I->getType() != CI->getOperand(0)->getType() ||
Expand Down Expand Up @@ -2023,8 +2029,12 @@ bool X86FastISel::X86FastEmitPseudoSelect(const Instruction *I) {

const Value *Cond = I->getOperand(0);
X86::CondCode CC = X86::COND_NE;
// Don't emit a test if the condition comes from a compare.
if (const auto *CI = dyn_cast<CmpInst>(Cond)) {

// Optimize conditons coming from a compare if both instructions are in the
// same basic block (values defined in other basic blocks may not have
// initialized registers).
const auto *CI = dyn_cast<CmpInst>(Cond);
if (CI && (CI->getParent() == I->getParent())) {
bool NeedSwap;
std::tie(CC, NeedSwap) = getX86ConditonCode(CI->getPredicate());
if (CC > X86::LAST_VALID_COND)
Expand Down
50 changes: 50 additions & 0 deletions test/CodeGen/X86/fast-isel-select-cmp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
; RUN: llc < %s -O0 -mtriple=x86_64-apple-darwin10 | FileCheck %s

; Test if we do not fold the cmp into select if the instructions are in
; different basic blocks.

define i32 @select_cmp_cmov_i32(i32 %a, i32 %b) {
; CHECK-LABEL: select_cmp_cmov_i32
; CHECK-LABEL: continue
; CHECK-NOT: cmp
%1 = icmp ult i32 %a, %b
br i1 %1, label %continue, label %exit

continue:
%2 = select i1 %1, i32 %a, i32 %b
ret i32 %2

exit:
ret i32 -1
}

define float @select_fcmp_oeq_f32(float %a, float %b, float %c, float %d) {
; CHECK-LABEL: select_fcmp_oeq_f32
; CHECK-LABEL: continue
; CHECK-NOT: cmp
%1 = fcmp oeq float %a, %b
br i1 %1, label %continue, label %exit

continue:
%2 = select i1 %1, float %c, float %d
ret float %2

exit:
ret float -1.0
}

define float @select_fcmp_one_f32(float %a, float %b, float %c, float %d) {
; CHECK-LABEL: select_fcmp_one_f32
; CHECK-LABEL: continue
; CHECK-NOT: ucomi
%1 = fcmp one float %a, %b
br i1 %1, label %continue, label %exit

continue:
%2 = select i1 %1, float %c, float %d
ret float %2

exit:
ret float -1.0
}

0 comments on commit d01f1c4

Please sign in to comment.