[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp
Chris Lattner
lattner at cs.uiuc.edu
Fri Jun 11 00:39:01 PDT 2004
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.260 -> 1.261
---
Log message:
By far, one of the most common uses of isnan is to make 'isunordered'
comparisons. In an 'isunordered' predicate, which looks like this at
the LLVM level:
%a = call bool %llvm.isnan(double %X)
%b = call bool %llvm.isnan(double %Y)
%COM = or bool %a, %b
We used to generate this code:
fxch %ST(1)
fucomip %ST(0), %ST(0)
setp %AL
fucomip %ST(0), %ST(0)
setp %AH
or %AL, %AH
With this patch, we generate this code:
fucomip %ST(0), %ST(1)
fstp %ST(0)
setp %AL
Which should make alkis happy. Tested as X86/compare_folding.llx:test1
---
Diffs of the changes: (+59 -14)
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.260 llvm/lib/Target/X86/InstSelectSimple.cpp:1.261
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.260 Thu Jun 10 23:49:02 2004
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri Jun 11 00:33:49 2004
@@ -329,6 +329,9 @@
MachineBasicBlock::iterator MBBI,
Constant *C, unsigned Reg);
+ void emitUCOMr(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
+ unsigned LHS, unsigned RHS);
+
/// makeAnotherReg - This method returns the next register number we haven't
/// yet used.
///
@@ -887,6 +890,19 @@
X86::SETSr, X86::SETNSr },
};
+/// emitUCOMr - In the future when we support processors before the P6, this
+/// wraps the logic for emitting an FUCOMr vs FUCOMIr.
+void ISel::emitUCOMr(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
+ unsigned LHS, unsigned RHS) {
+ if (0) { // for processors prior to the P6
+ BuildMI(*MBB, IP, X86::FUCOMr, 2).addReg(LHS).addReg(RHS);
+ BuildMI(*MBB, IP, X86::FNSTSW8r, 0);
+ BuildMI(*MBB, IP, X86::SAHF, 1);
+ } else {
+ BuildMI(*MBB, IP, X86::FUCOMIr, 2).addReg(LHS).addReg(RHS);
+ }
+}
+
// EmitComparison - This function emits a comparison of the two operands,
// returning the extended setcc code to use.
unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
@@ -1004,13 +1020,7 @@
BuildMI(*MBB, IP, X86::CMP32rr, 2).addReg(Op0r).addReg(Op1r);
break;
case cFP:
- if (0) { // for processors prior to the P6
- BuildMI(*MBB, IP, X86::FUCOMr, 2).addReg(Op0r).addReg(Op1r);
- BuildMI(*MBB, IP, X86::FNSTSW8r, 0);
- BuildMI(*MBB, IP, X86::SAHF, 1);
- } else {
- BuildMI(*MBB, IP, X86::FUCOMIr, 2).addReg(Op0r).addReg(Op1r);
- }
+ emitUCOMr(MBB, IP, Op0r, Op1r);
break;
case cLong:
@@ -1609,6 +1619,31 @@
doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args);
}
+/// dyncastIsNan - Return the operand of an isnan operation if this is an isnan.
+///
+static Value *dyncastIsNan(Value *V) {
+ if (CallInst *CI = dyn_cast<CallInst>(V))
+ if (Function *F = CI->getCalledFunction())
+ if (F->getIntrinsicID() == Intrinsic::isnan)
+ return CI->getOperand(1);
+ return 0;
+}
+
+/// isOnlyUsedByUnorderedComparisons - Return true if this value is only used by
+/// or's whos operands are all calls to the isnan predicate.
+static bool isOnlyUsedByUnorderedComparisons(Value *V) {
+ assert(dyncastIsNan(V) && "The value isn't an isnan call!");
+
+ // Check all uses, which will be or's of isnans if this predicate is true.
+ for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
+ Instruction *I = cast<Instruction>(*UI);
+ if (I->getOpcode() != Instruction::Or) return false;
+ if (I->getOperand(0) != V && !dyncastIsNan(I->getOperand(0))) return false;
+ if (I->getOperand(1) != V && !dyncastIsNan(I->getOperand(1))) return false;
+ }
+
+ return true;
+}
/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
/// function, lowering any calls to unknown intrinsic functions into the
@@ -1699,14 +1734,10 @@
return;
case Intrinsic::isnan:
+ // If this is only used by 'isunordered' style comparisons, don't emit it.
+ if (isOnlyUsedByUnorderedComparisons(&CI)) return;
TmpReg1 = getReg(CI.getOperand(1));
- if (0) { // for processors prior to the P6
- BuildMI(BB, X86::FUCOMr, 2).addReg(TmpReg1).addReg(TmpReg1);
- BuildMI(BB, X86::FNSTSW8r, 0);
- BuildMI(BB, X86::SAHF, 1);
- } else {
- BuildMI(BB, X86::FUCOMIr, 2).addReg(TmpReg1).addReg(TmpReg1);
- }
+ emitUCOMr(BB, BB->end(), TmpReg1, TmpReg1);
TmpReg2 = getReg(CI);
BuildMI(BB, X86::SETPr, 0, TmpReg2);
return;
@@ -2122,6 +2153,20 @@
return;
}
+ if (Op0->getType() == Type::BoolTy) {
+ if (OperatorClass == 3)
+ // If this is an or of two isnan's, emit an FP comparison directly instead
+ // of or'ing two isnan's together.
+ if (Value *LHS = dyncastIsNan(Op0))
+ if (Value *RHS = dyncastIsNan(Op1)) {
+ unsigned Op0Reg = getReg(RHS, MBB, IP), Op1Reg = getReg(LHS, MBB, IP);
+ emitUCOMr(MBB, IP, Op0Reg, Op1Reg);
+ BuildMI(*MBB, IP, X86::SETPr, 0, DestReg);
+ return;
+ }
+
+ }
+
// sub 0, X -> neg X
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0))
if (OperatorClass == 1 && CI->isNullValue()) {
More information about the llvm-commits
mailing list