aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-12-22 14:33:29 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-12-22 14:33:29 -0800
commitcb759fddd32b3ac8450e4d6d84f7840db0f0ac9c (patch)
tree2c0dd4b37b8a536608837c894765509aa0e44ac5 /lib/Transforms
parent9496e82d190a7ff02acbbbe11e7b8ffe8aae5c45 (diff)
optimize legalization of shl 32
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/NaCl/ExpandI64.cpp50
1 files changed, 38 insertions, 12 deletions
diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp
index 53550db54e..f2a797439a 100644
--- a/lib/Transforms/NaCl/ExpandI64.cpp
+++ b/lib/Transforms/NaCl/ExpandI64.cpp
@@ -314,7 +314,8 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) {
case Instruction::AShr:
case Instruction::Shl: {
ensureFuncs();
- Function *F;
+ Value *Low = NULL, *High = NULL;
+ Function *F = NULL;
switch (I->getOpcode()) {
case Instruction::Add: F = Add; break;
case Instruction::Sub: F = Sub; break;
@@ -325,15 +326,28 @@ void ExpandI64::splitInst(Instruction *I, DataLayout& DL) {
case Instruction::URem: F = URem; break;
case Instruction::LShr: F = LShr; break;
case Instruction::AShr: F = AShr; break;
- case Instruction::Shl: F = Shl; break;
+ case Instruction::Shl: {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ unsigned Shifts = CI->getZExtValue();
+ if (Shifts == 32) {
+ Low = Zero;
+ High = CopyDebug(BinaryOperator::Create(Instruction::Or, Zero, Zero, "", I), I); // copy hackishly XXX TODO: eliminate x|0 to x in post-pass
+ break;
+ }
+ }
+ F = Shl;
+ break;
+ }
default: assert(0);
}
- SmallVector<Value *, 4> Args;
- for (unsigned i = 0; i < 4; i++) Args.push_back(Zero); // will be fixed
- Instruction *Low = CopyDebug(CallInst::Create(F, Args, "", I), I);
- Instruction *High = CopyDebug(CallInst::Create(GetHigh, "", I), I);
+ if (F) {
+ // use a library call, no special optimization was found
+ SmallVector<Value *, 4> Args;
+ for (unsigned i = 0; i < 4; i++) Args.push_back(Zero); // will be fixed
+ Low = CopyDebug(CallInst::Create(F, Args, "", I), I);
+ High = CopyDebug(CallInst::Create(GetHigh, "", I), I);
+ }
SplitInfo &Split = Splits[I];
- Split.ToFix.push_back(Low);
Split.LowHigh.Low = Low;
Split.LowHigh.High = High;
break;
@@ -662,11 +676,23 @@ void ExpandI64::finalizeInst(Instruction *I) {
case Instruction::Shl: {
LowHighPair LeftLH = getLowHigh(I->getOperand(0));
LowHighPair RightLH = getLowHigh(I->getOperand(1));
- Instruction *Call = Split.ToFix[0];
- Call->setOperand(0, LeftLH.Low);
- Call->setOperand(1, LeftLH.High);
- Call->setOperand(2, RightLH.Low);
- Call->setOperand(3, RightLH.High);
+ CallInst *Call = dyn_cast<CallInst>(Split.LowHigh.Low);
+ if (Call) {
+ Call->setOperand(0, LeftLH.Low);
+ Call->setOperand(1, LeftLH.High);
+ Call->setOperand(2, RightLH.Low);
+ Call->setOperand(3, RightLH.High);
+ } else {
+ // optimized case
+ switch (I->getOpcode()) {
+ case Instruction::Shl: {
+ // 32-bit shift
+ cast<Instruction>(Split.LowHigh.High)->setOperand(0, LeftLH.Low);
+ break;
+ }
+ default: assert(0);
+ }
+ }
break;
}
case Instruction::ICmp: {