aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-01-29 10:55:12 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-01-29 10:55:12 -0800
commit03d4bacfe9c77aae807d7cc7ebd8c132462b54dc (patch)
tree4a1558c1e0146ef4771a1d2903c07957966bb151
parent24515ba443b387126a07b84f3dcd47459b5c92c9 (diff)
legalize icmp eq|ne on >64 bits
-rw-r--r--lib/Transforms/NaCl/ExpandI64.cpp78
1 files changed, 50 insertions, 28 deletions
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp
index 8c4ba1a9c3..0fe5c342bf 100644
--- a/lib/Transforms/NaCl/ExpandI64.cpp
+++ b/lib/Transforms/NaCl/ExpandI64.cpp
@@ -392,21 +392,29 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) {
break;
}
case Instruction::ICmp: {
- assert(I->getOperand(0)->getType() == i64); // FIXME
- Instruction *A, *B, *C = NULL, *D = NULL, *Final;
ICmpInst *CE = dyn_cast<ICmpInst>(I);
ICmpInst::Predicate Pred = CE->getPredicate();
switch (Pred) {
- case ICmpInst::ICMP_EQ: {
- A = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_EQ, Zero, Zero), I);
- B = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_EQ, Zero, Zero), I);
- Final = CopyDebug(BinaryOperator::Create(Instruction::And, A, B, "", I), I);
- break;
- }
+ case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_NE: {
- A = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_NE, Zero, Zero), I);
- B = CopyDebug(new ICmpInst(I, ICmpInst::ICMP_NE, Zero, Zero), I);
- Final = CopyDebug(BinaryOperator::Create(Instruction::Or, A, B, "", I), I);
+ ICmpInst::Predicate PartPred; // the predicate to use on each of the parts
+ llvm::Instruction::BinaryOps CombineOp; // the predicate to use to combine the subcomparisons
+ int Num = getNumChunks(I->getOperand(0)->getType());
+ if (Pred == ICmpInst::ICMP_EQ) {
+ PartPred = ICmpInst::ICMP_EQ;
+ CombineOp = Instruction::And;
+ } else {
+ PartPred = ICmpInst::ICMP_NE;
+ CombineOp = Instruction::Or;
+ }
+ for (int i = 0; i < Num; i++) {
+ Split.ToFix.push_back(CopyDebug(new ICmpInst(I, PartPred, Zero, Zero), I));
+ }
+ // first combine 0 and 1. then combine that with 2, etc.
+ Split.ToFix.push_back(CopyDebug(BinaryOperator::Create(CombineOp, Split.ToFix[0], Split.ToFix[1], "", I), I));
+ for (int i = 2; i < Num; i++) {
+ Split.ToFix.push_back(CopyDebug(BinaryOperator::Create(CombineOp, Split.ToFix[i], Split.ToFix[Split.ToFix.size()-1], "", I), I));
+ }
break;
}
case ICmpInst::ICMP_ULT:
@@ -417,6 +425,8 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) {
case ICmpInst::ICMP_SLE:
case ICmpInst::ICMP_UGE:
case ICmpInst::ICMP_SGE: {
+ assert(I->getOperand(0)->getType() == i64);
+ Instruction *A, *B, *C, *D, *Final;
ICmpInst::Predicate StrictPred = Pred;
ICmpInst::Predicate UnsignedPred = Pred;
switch (Pred) {
@@ -435,15 +445,15 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) {
C = CopyDebug(new ICmpInst(I, UnsignedPred, Zero, Zero), I);
D = CopyDebug(BinaryOperator::Create(Instruction::And, B, C, "", I), I);
Final = CopyDebug(BinaryOperator::Create(Instruction::Or, A, D, "", I), I);
+ Split.ToFix.push_back(A);
+ Split.ToFix.push_back(B);
+ Split.ToFix.push_back(C);
+ // D is NULL or a logical operator, no need to fix it
+ Split.ToFix.push_back(Final);
break;
}
default: assert(0);
}
- Split.ToFix.push_back(A);
- Split.ToFix.push_back(B);
- Split.ToFix.push_back(C);
- // D is NULL or a logical operator, no need to fix it
- Split.ToFix.push_back(Final);
break;
}
case Instruction::Select: {
@@ -780,19 +790,31 @@ void ExpandI64::finalizeInst(Instruction *I) {
case Instruction::ICmp: {
ChunksVec Left = getChunks(I->getOperand(0));
ChunksVec Right = getChunks(I->getOperand(1));
- Instruction *A = Split.ToFix[0];
- Instruction *B = Split.ToFix[1];
- Instruction *C = Split.ToFix[2];
- Instruction *Final = Split.ToFix[3];
- if (!C) { // EQ, NE
- A->setOperand(0, Left[0]); A->setOperand(1, Right[0]);
- B->setOperand(0, Left[1]); B->setOperand(1, Right[1]);
- } else {
- A->setOperand(0, Left[1]); A->setOperand(1, Right[1]);
- B->setOperand(0, Left[1]); B->setOperand(1, Right[1]);
- C->setOperand(0, Left[0]); C->setOperand(1, Right[0]);
+ ICmpInst *CE = dyn_cast<ICmpInst>(I);
+ ICmpInst::Predicate Pred = CE->getPredicate();
+ switch (Pred) {
+ case ICmpInst::ICMP_EQ:
+ case ICmpInst::ICMP_NE: {
+ int Num = getNumChunks(I->getOperand(0)->getType());
+ for (int i = 0; i < Num; i++) {
+ Split.ToFix[i]->setOperand(0, Left[i]);
+ Split.ToFix[i]->setOperand(1, Right[i]);
+ }
+ I->replaceAllUsesWith(Split.ToFix[Split.ToFix.size()-1]);
+ break;
+ }
+ default: {
+ Instruction *A = Split.ToFix[0];
+ Instruction *B = Split.ToFix[1];
+ Instruction *C = Split.ToFix[2];
+ Instruction *Final = Split.ToFix[3];
+ A->setOperand(0, Left[1]); A->setOperand(1, Right[1]);
+ B->setOperand(0, Left[1]); B->setOperand(1, Right[1]);
+ C->setOperand(0, Left[0]); C->setOperand(1, Right[0]);
+ I->replaceAllUsesWith(Final);
+ break;
+ }
}
- I->replaceAllUsesWith(Final);
break;
}
case Instruction::Select: {