[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Tue Sep 28 14:48:15 PDT 2004
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.253 -> 1.254
---
Log message:
Fold (and (setcc X, C1), (setcc X, C2))
This is important for several reasons:
1. Benchmarks have lots of code that looks like this (perlbmk in particular):
%tmp.2.i = setne int %tmp.0.i, 128 ; <bool> [#uses=1]
%tmp.6343 = seteq int %tmp.0.i, 1 ; <bool> [#uses=1]
%tmp.63 = and bool %tmp.2.i, %tmp.6343 ; <bool> [#uses=1]
we now fold away the setne, a clear improvement.
2. In the more important cases, such as (X >= 10) & (X < 20), we now produce
smaller code: (X-10) < 10.
3. Perhaps the nicest effect of this patch is that it really helps out the
code generators. In particular, for a 'range test' like the above,
instead of generating this on X86 (the difference on PPC is even more
pronounced):
cmp %EAX, 50
setge %CL
cmp %EAX, 100
setl %AL
and %CL, %AL
cmp %CL, 0
we now generate this:
add %EAX, -50
cmp %EAX, 50
Furthermore, this causes setcc's to be folded into branches more often.
These combinations trigger dozens of times in the spec benchmarks, particularly
in 176.gcc, 186.crafty, 253.perlbmk, 254.gap, & 099.go.
---
Diffs of the changes: (+121 -20)
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.253 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.254
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.253 Tue Sep 28 13:22:15 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Sep 28 16:48:02 2004
@@ -137,7 +137,7 @@
// InsertNewInstBefore - insert an instruction New before instruction Old
// in the program. Add the new instruction to the worklist.
//
- Value *InsertNewInstBefore(Instruction *New, Instruction &Old) {
+ Instruction *InsertNewInstBefore(Instruction *New, Instruction &Old) {
assert(New && New->getParent() == 0 &&
"New instruction already inserted into a basic block!");
BasicBlock *BB = Old.getParent();
@@ -334,6 +334,22 @@
return Count;
}
+// AddOne, SubOne - Add or subtract a constant one from an integer constant...
+static Constant *AddOne(ConstantInt *C) {
+ return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
+}
+static Constant *SubOne(ConstantInt *C) {
+ return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
+}
+
+// isTrueWhenEqual - Return true if the specified setcondinst instruction is
+// true when both operands are equal...
+//
+static bool isTrueWhenEqual(Instruction &I) {
+ return I.getOpcode() == Instruction::SetEQ ||
+ I.getOpcode() == Instruction::SetGE ||
+ I.getOpcode() == Instruction::SetLE;
+}
/// AssociativeOpt - Perform an optimization on an associative operator. This
/// function is designed to check a chain of associative operators for a
@@ -1203,11 +1219,113 @@
return BinaryOperator::createNot(Or);
}
- // (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
- if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
+ if (SetCondInst *RHS = dyn_cast<SetCondInst>(Op1)) {
+ // (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
return R;
+ Value *LHSVal, *RHSVal;
+ ConstantInt *LHSCst, *RHSCst;
+ Instruction::BinaryOps LHSCC, RHSCC;
+ if (match(Op0, m_SetCond(LHSCC, m_Value(LHSVal), m_ConstantInt(LHSCst))))
+ if (match(RHS, m_SetCond(RHSCC, m_Value(RHSVal), m_ConstantInt(RHSCst))))
+ if (LHSVal == RHSVal && // Found (X setcc C1) & (X setcc C2)
+ // Set[GL]E X, CST is folded to Set[GL]T elsewhere.
+ LHSCC != Instruction::SetGE && LHSCC != Instruction::SetLE &&
+ RHSCC != Instruction::SetGE && RHSCC != Instruction::SetLE) {
+ // Ensure that the larger constant is on the RHS.
+ Constant *Cmp = ConstantExpr::getSetGT(LHSCst, RHSCst);
+ SetCondInst *LHS = cast<SetCondInst>(Op0);
+ if (cast<ConstantBool>(Cmp)->getValue()) {
+ std::swap(LHS, RHS);
+ std::swap(LHSCst, RHSCst);
+ std::swap(LHSCC, RHSCC);
+ }
+
+ // At this point, we know we have have two setcc instructions
+ // comparing a value against two constants and and'ing the result
+ // together. Because of the above check, we know that we only have
+ // SetEQ, SetNE, SetLT, and SetGT here. We also know (from the
+ // FoldSetCCLogical check above), that the two constants are not
+ // equal.
+ assert(LHSCst != RHSCst && "Compares not folded above?");
+
+ switch (LHSCC) {
+ default: assert(0 && "Unknown integer condition code!");
+ case Instruction::SetEQ:
+ switch (RHSCC) {
+ default: assert(0 && "Unknown integer condition code!");
+ case Instruction::SetEQ: // (X == 13 & X == 15) -> false
+ case Instruction::SetGT: // (X == 13 & X > 15) -> false
+ return ReplaceInstUsesWith(I, ConstantBool::False);
+ case Instruction::SetNE: // (X == 13 & X != 15) -> X == 13
+ case Instruction::SetLT: // (X == 13 & X < 15) -> X == 13
+ return ReplaceInstUsesWith(I, LHS);
+ }
+ case Instruction::SetNE:
+ switch (RHSCC) {
+ default: assert(0 && "Unknown integer condition code!");
+ case Instruction::SetLT:
+ if (LHSCst == SubOne(RHSCst)) // (X != 13 & X < 14) -> X < 13
+ return new SetCondInst(Instruction::SetLT, LHSVal, LHSCst);
+ break; // (X != 13 & X < 15) -> no change
+ case Instruction::SetEQ: // (X != 13 & X == 15) -> X == 15
+ case Instruction::SetGT: // (X != 13 & X > 15) -> X > 15
+ return ReplaceInstUsesWith(I, RHS);
+ case Instruction::SetNE:
+ if (LHSCst == SubOne(RHSCst)) {// (X != 13 & X != 14) -> X-13 >u 1
+ Constant *AddCST = ConstantExpr::getNeg(LHSCst);
+ Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
+ LHSVal->getName()+".off");
+ InsertNewInstBefore(Add, I);
+ const Type *UnsType = Add->getType()->getUnsignedVersion();
+ Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
+ AddCST = ConstantExpr::getSub(RHSCst, LHSCst);
+ AddCST = ConstantExpr::getCast(AddCST, UnsType);
+ return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST);
+ }
+ break; // (X != 13 & X != 15) -> no change
+ }
+ break;
+ case Instruction::SetLT:
+ switch (RHSCC) {
+ default: assert(0 && "Unknown integer condition code!");
+ case Instruction::SetEQ: // (X < 13 & X == 15) -> false
+ case Instruction::SetGT: // (X < 13 & X > 15) -> false
+ return ReplaceInstUsesWith(I, ConstantBool::False);
+ case Instruction::SetNE: // (X < 13 & X != 15) -> X < 13
+ case Instruction::SetLT: // (X < 13 & X < 15) -> X < 13
+ return ReplaceInstUsesWith(I, LHS);
+ }
+ case Instruction::SetGT:
+ switch (RHSCC) {
+ default: assert(0 && "Unknown integer condition code!");
+ case Instruction::SetEQ: // (X > 13 & X == 15) -> X > 13
+ return ReplaceInstUsesWith(I, LHS);
+ case Instruction::SetGT: // (X > 13 & X > 15) -> X > 15
+ return ReplaceInstUsesWith(I, RHS);
+ case Instruction::SetNE:
+ if (RHSCst == AddOne(LHSCst)) // (X > 13 & X != 14) -> X > 14
+ return new SetCondInst(Instruction::SetGT, LHSVal, RHSCst);
+ break; // (X > 13 & X != 15) -> no change
+ case Instruction::SetLT: { // (X > 13 & X < 15) -> (X-14) <u 1
+ Constant *AddCST = ConstantExpr::getNeg(AddOne(LHSCst));
+ Instruction *Add = BinaryOperator::createAdd(LHSVal, AddCST,
+ LHSVal->getName()+".off");
+ InsertNewInstBefore(Add, I);
+ // Convert to unsigned for the comparison.
+ const Type *UnsType = Add->getType()->getUnsignedVersion();
+ Value *OffsetVal = InsertCastBefore(Add, UnsType, I);
+ AddCST = ConstantExpr::getAdd(AddCST, RHSCst);
+ AddCST = ConstantExpr::getCast(AddCST, UnsType);
+ return new SetCondInst(Instruction::SetLT, OffsetVal, AddCST);
+ }
+ break;
+ }
+ }
+ }
+ }
+
return Changed ? &I : 0;
}
@@ -1429,23 +1547,6 @@
return Changed ? &I : 0;
}
-// AddOne, SubOne - Add or subtract a constant one from an integer constant...
-static Constant *AddOne(ConstantInt *C) {
- return ConstantExpr::getAdd(C, ConstantInt::get(C->getType(), 1));
-}
-static Constant *SubOne(ConstantInt *C) {
- return ConstantExpr::getSub(C, ConstantInt::get(C->getType(), 1));
-}
-
-// isTrueWhenEqual - Return true if the specified setcondinst instruction is
-// true when both operands are equal...
-//
-static bool isTrueWhenEqual(Instruction &I) {
- return I.getOpcode() == Instruction::SetEQ ||
- I.getOpcode() == Instruction::SetGE ||
- I.getOpcode() == Instruction::SetLE;
-}
-
Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
bool Changed = SimplifyCommutative(I);
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
More information about the llvm-commits
mailing list