[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner lattner at cs.uiuc.edu
Wed Aug 13 15:17:01 PDT 2003


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.116 -> 1.117

---
Log message:

Implement instcombine optimizations:
   (A <setcc1> B) logicalop (A <setcc2> B)  -> (A <setcc3> B) or true or false

Where setcc[123] is one of the 6 setcc instructions, and logicalop is one of: And, Or, Xor



---
Diffs of the changes:

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.116 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.117
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.116	Wed Aug 13 14:01:45 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Wed Aug 13 15:16:26 2003
@@ -112,6 +112,7 @@
       WorkList.push_back(New);              // Add to worklist
     }
 
+  public:
     // ReplaceInstUsesWith - This method is to be used when an instruction is
     // found to be dead, replacable with another preexisting expression.  Here
     // we add all uses of I to the worklist, replace all uses of I with the new
@@ -123,7 +124,7 @@
       I.replaceAllUsesWith(V);
       return &I;
     }
-
+  private:
     /// InsertOperandCastBefore - This inserts a cast of V to DestTy before the
     /// InsertBefore instruction.  This is specialized a bit to avoid inserting
     /// casts that are known to not do anything...
@@ -638,6 +639,86 @@
   return CS->getValue() == Val+1;
 }
 
+/// getSetCondCode - Encode a setcc opcode into a three bit mask.  These bits
+/// are carefully arranged to allow folding of expressions such as:
+///
+///      (A < B) | (A > B) --> (A != B)
+///
+/// Bit value '4' represents that the comparison is true if A > B, bit value '2'
+/// represents that the comparison is true if A == B, and bit value '1' is true
+/// if A < B.
+///
+static unsigned getSetCondCode(const SetCondInst *SCI) {
+  switch (SCI->getOpcode()) {
+    // False -> 0
+  case Instruction::SetGT: return 1;
+  case Instruction::SetEQ: return 2;
+  case Instruction::SetGE: return 3;
+  case Instruction::SetLT: return 4;
+  case Instruction::SetNE: return 5;
+  case Instruction::SetLE: return 6;
+    // True -> 7
+  default:
+    assert(0 && "Invalid SetCC opcode!");
+    return 0;
+  }
+}
+
+/// getSetCCValue - This is the complement of getSetCondCode, which turns an
+/// opcode and two operands into either a constant true or false, or a brand new
+/// SetCC instruction.
+static Value *getSetCCValue(unsigned Opcode, Value *LHS, Value *RHS) {
+  switch (Opcode) {
+  case 0: return ConstantBool::False;
+  case 1: return new SetCondInst(Instruction::SetGT, LHS, RHS);
+  case 2: return new SetCondInst(Instruction::SetEQ, LHS, RHS);
+  case 3: return new SetCondInst(Instruction::SetGE, LHS, RHS);
+  case 4: return new SetCondInst(Instruction::SetLT, LHS, RHS);
+  case 5: return new SetCondInst(Instruction::SetNE, LHS, RHS);
+  case 6: return new SetCondInst(Instruction::SetLE, LHS, RHS);
+  case 7: return ConstantBool::True;
+  default: assert(0 && "Illegal SetCCCode!"); return 0;
+  }
+}
+
+// FoldSetCCLogical - Implements (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
+struct FoldSetCCLogical {
+  InstCombiner &IC;
+  Value *LHS, *RHS;
+  FoldSetCCLogical(InstCombiner &ic, SetCondInst *SCI)
+    : IC(ic), LHS(SCI->getOperand(0)), RHS(SCI->getOperand(1)) {}
+  bool shouldApply(Value *V) const {
+    if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
+      return (SCI->getOperand(0) == LHS && SCI->getOperand(1) == RHS ||
+              SCI->getOperand(0) == RHS && SCI->getOperand(1) == LHS);
+    return false;
+  }
+  Instruction *apply(BinaryOperator &Log) const {
+    SetCondInst *SCI = cast<SetCondInst>(Log.getOperand(0));
+    if (SCI->getOperand(0) != LHS) {
+      assert(SCI->getOperand(1) == LHS);
+      SCI->swapOperands();  // Swap the LHS and RHS of the SetCC
+    }
+
+    unsigned LHSCode = getSetCondCode(SCI);
+    unsigned RHSCode = getSetCondCode(cast<SetCondInst>(Log.getOperand(1)));
+    unsigned Code;
+    switch (Log.getOpcode()) {
+    case Instruction::And: Code = LHSCode & RHSCode; break;
+    case Instruction::Or:  Code = LHSCode | RHSCode; break;
+    case Instruction::Xor: Code = LHSCode ^ RHSCode; break;
+    default: assert(0 && "Illegal logical opcode!");
+    }
+
+    Value *RV = getSetCCValue(Code, LHS, RHS);
+    if (Instruction *I = dyn_cast<Instruction>(RV))
+      return I;
+    // Otherwise, it's a constant boolean value...
+    return IC.ReplaceInstUsesWith(Log, RV);
+  }
+};
+
+
 
 Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
@@ -704,6 +785,11 @@
   if (Op0NotVal == Op1 || Op1NotVal == Op0)  // A & ~A  == ~A & A == 0
     return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
 
+  // (setcc1 A, B) & (setcc2 A, B) --> (setcc3 A, B)
+  if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
+    if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
+      return R;
+
   return Changed ? &I : 0;
 }
 
@@ -776,6 +862,11 @@
     return BinaryOperator::createNot(And);
   }
 
+  // (setcc1 A, B) | (setcc2 A, B) --> (setcc3 A, B)
+  if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
+    if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
+      return R;
+
   return Changed ? &I : 0;
 }
 
@@ -852,6 +943,11 @@
     if (Constant *C2 = dyn_castMaskingAnd(Op1))
       if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue())
         return BinaryOperator::create(Instruction::Or, Op0, Op1);
+
+  // (setcc1 A, B) ^ (setcc2 A, B) --> (setcc3 A, B)
+  if (SetCondInst *RHS = dyn_cast<SetCondInst>(I.getOperand(1)))
+    if (Instruction *R = AssociativeOpt(I, FoldSetCCLogical(*this, RHS)))
+      return R;
 
   return Changed ? &I : 0;
 }





More information about the llvm-commits mailing list