aboutsummaryrefslogtreecommitdiffstats
path: root/lib/VMCore/iOperators.cpp
blob: ba5aca13012ce212d4ca1a0e3ed0329aad6762b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//===-- iOperators.cpp - Implement binary Operators ------------*- C++ -*--===//
//
// This file implements the nontrivial binary operator instructions.
//
//===----------------------------------------------------------------------===//

#include "llvm/iOperators.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"

//===----------------------------------------------------------------------===//
//                             BinaryOperator Class
//===----------------------------------------------------------------------===//

BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2,
				       const std::string &Name) {
  switch (Op) {
  // Binary comparison operators...
  case SetLT: case SetGT: case SetLE:
  case SetGE: case SetEQ: case SetNE:
    return new SetCondInst(Op, S1, S2, Name);

  default:
    return new GenericBinaryInst(Op, S1, S2, Name);
  }
}

BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name) {
  return new GenericBinaryInst(Instruction::Sub,
                               Constant::getNullValue(Op->getType()), Op, Name);
}

BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name) {
  return new GenericBinaryInst(Instruction::Xor, Op,
                               ConstantIntegral::getAllOnesValue(Op->getType()),
                               Name);
}


// isConstantAllOnes - Helper function for several functions below
static inline bool isConstantAllOnes(const Value *V) {
  return isa<ConstantIntegral>(V) &&cast<ConstantIntegral>(V)->isAllOnesValue();
}

bool BinaryOperator::isNeg(const Value *V) {
  if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
    return Bop->getOpcode() == Instruction::Sub &&
      isa<Constant>(Bop->getOperand(0)) && cast<Constant>(V)->isNullValue();
  return false;
}

bool BinaryOperator::isNot(const Value *V) {
  if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
    return (Bop->getOpcode() == Instruction::Xor &&
            (isConstantAllOnes(Bop->getOperand(1)) ||
             isConstantAllOnes(Bop->getOperand(0))));
  return false;
}

Value *BinaryOperator::getNegArgument(BinaryOperator *Bop) {
  assert(isNeg(Bop) && "getNegArgument from non-'neg' instruction!");
  return Bop->getOperand(1);
}

const Value *BinaryOperator::getNegArgument(const BinaryOperator *Bop) {
  return getNegArgument((BinaryOperator*)Bop);
}

Value *BinaryOperator::getNotArgument(BinaryOperator *Bop) {
  assert(isNot(Bop) && "getNotArgument on non-'not' instruction!");
  Value *Op0 = Bop->getOperand(0);
  Value *Op1 = Bop->getOperand(1);
  if (isConstantAllOnes(Op0)) return Op1;

  assert(isConstantAllOnes(Op1));
  return Op0;
}

const Value *BinaryOperator::getNotArgument(const BinaryOperator *Bop) {
  return getNotArgument((BinaryOperator*)Bop);
}


// swapOperands - Exchange the two operands to this instruction.  This
// instruction is safe to use on any binary instruction and does not
// modify the semantics of the instruction.  If the instruction is
// order dependant (SetLT f.e.) the opcode is changed.
//
bool BinaryOperator::swapOperands() {
  switch (getOpcode()) {
    // Instructions that don't need opcode modification
  case Add: case Mul:
  case And: case Xor:
  case Or:
  case SetEQ: case SetNE:
    break;
    // Instructions that need opcode modification
  case SetGT: iType = SetLT; break;
  case SetLT: iType = SetGT; break;
  case SetGE: iType = SetLE; break;
  case SetLE: iType = SetGE; break;
    // Error on the side of caution
  default:
    return true;
  }
  std::swap(Operands[0], Operands[1]);
  return false;
}


//===----------------------------------------------------------------------===//
//                             SetCondInst Class
//===----------------------------------------------------------------------===//

SetCondInst::SetCondInst(BinaryOps opType, Value *S1, Value *S2, 
                         const std::string &Name) 
  : BinaryOperator(opType, S1, S2, Name) {

  OpType = opType;
  setType(Type::BoolTy);   // setcc instructions always return bool type.

  // Make sure it's a valid type...
  assert(getOpcodeName() != 0);
}

// getInverseCondition - Return the inverse of the current condition opcode.
// For example seteq -> setne, setgt -> setle, setlt -> setge, etc...
//
Instruction::BinaryOps SetCondInst::getInverseCondition() const {
  switch (getOpcode()) {
  default:
    assert(0 && "Unknown setcc opcode!");
  case SetEQ: return SetNE;
  case SetNE: return SetEQ;
  case SetGT: return SetLE;
  case SetLT: return SetGE;
  case SetGE: return SetLT;
  case SetLE: return SetGT;
  }
}