OLD | NEW |
(Empty) | |
| 1 //===- PromoteI1Ops.cpp - Promote various operations on the i1 type--------===// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 // |
| 10 // This pass expands out various operations on the i1 type so that |
| 11 // these i1 operations do not need to be supported by the PNaCl |
| 12 // translator. |
| 13 // |
| 14 // This is similar to the PromoteIntegers pass in that it removes uses |
| 15 // of an unusual-size integer type. The difference is that i1 remains |
| 16 // a valid type in other operations. i1 can still be used in phi |
| 17 // nodes, "select" instructions, in "sext" and "zext", and so on. In |
| 18 // contrast, the integer types that PromoteIntegers removes are not |
| 19 // allowed in any context by PNaCl's ABI verifier. |
| 20 // |
| 21 // This pass expands out the following: |
| 22 // |
| 23 // * i1 loads and stores. |
| 24 // * All i1 comparisons and arithmetic operations, with the exception |
| 25 // of "and", "or" and "xor", because these are used in practice and |
| 26 // don't overflow. |
| 27 // |
| 28 //===----------------------------------------------------------------------===// |
| 29 |
| 30 #include "llvm/IR/BasicBlock.h" |
| 31 #include "llvm/IR/Constants.h" |
| 32 #include "llvm/IR/Instructions.h" |
| 33 #include "llvm/Pass.h" |
| 34 #include "llvm/Transforms/NaCl.h" |
| 35 |
| 36 using namespace llvm; |
| 37 |
| 38 namespace { |
| 39 class PromoteI1Ops : public BasicBlockPass { |
| 40 public: |
| 41 static char ID; // Pass identification, replacement for typeid |
| 42 PromoteI1Ops() : BasicBlockPass(ID) { |
| 43 initializePromoteI1OpsPass(*PassRegistry::getPassRegistry()); |
| 44 } |
| 45 |
| 46 virtual bool runOnBasicBlock(BasicBlock &BB); |
| 47 }; |
| 48 } |
| 49 |
| 50 char PromoteI1Ops::ID = 0; |
| 51 INITIALIZE_PASS(PromoteI1Ops, "nacl-promote-i1-ops", |
| 52 "Promote various operations on the i1 type", |
| 53 false, false) |
| 54 |
| 55 static Value *promoteValue(Value *Val, bool SignExt, Instruction *InsertPt) { |
| 56 Instruction::CastOps CastType = |
| 57 SignExt ? Instruction::SExt : Instruction::ZExt; |
| 58 return CopyDebug(CastInst::Create(CastType, Val, |
| 59 Type::getInt8Ty(Val->getContext()), |
| 60 Val->getName() + ".expand_i1_val", |
| 61 InsertPt), InsertPt); |
| 62 } |
| 63 |
| 64 bool PromoteI1Ops::runOnBasicBlock(BasicBlock &BB) { |
| 65 bool Changed = false; |
| 66 |
| 67 Type *I1Ty = Type::getInt1Ty(BB.getContext()); |
| 68 Type *I8Ty = Type::getInt8Ty(BB.getContext()); |
| 69 |
| 70 // Rewrite boolean Switch terminators: |
| 71 if (SwitchInst *Switch = dyn_cast<SwitchInst>(BB.getTerminator())) { |
| 72 Value *Condition = Switch->getCondition(); |
| 73 Type *ConditionTy = Condition->getType(); |
| 74 if (ConditionTy->isIntegerTy(1)) { |
| 75 ConstantInt *False = |
| 76 cast<ConstantInt>(ConstantInt::getFalse(ConditionTy)); |
| 77 ConstantInt *True = |
| 78 cast<ConstantInt>(ConstantInt::getTrue(ConditionTy)); |
| 79 |
| 80 SwitchInst::CaseIt FalseCase = Switch->findCaseValue(False); |
| 81 SwitchInst::CaseIt TrueCase = Switch->findCaseValue(True); |
| 82 |
| 83 BasicBlock *FalseBlock = FalseCase.getCaseSuccessor(); |
| 84 BasicBlock *TrueBlock = TrueCase.getCaseSuccessor(); |
| 85 BasicBlock *DefaultDest = Switch->getDefaultDest(); |
| 86 |
| 87 if (TrueBlock && FalseBlock) { |
| 88 // impossible destination |
| 89 DefaultDest->removePredecessor(Switch->getParent()); |
| 90 } |
| 91 |
| 92 if (!TrueBlock) { |
| 93 TrueBlock = DefaultDest; |
| 94 } |
| 95 if (!FalseBlock) { |
| 96 FalseBlock = DefaultDest; |
| 97 } |
| 98 |
| 99 CopyDebug(BranchInst::Create(TrueBlock, FalseBlock, Condition, Switch), |
| 100 Switch); |
| 101 Switch->eraseFromParent(); |
| 102 } |
| 103 } |
| 104 |
| 105 for (BasicBlock::iterator Iter = BB.begin(), E = BB.end(); Iter != E; ) { |
| 106 Instruction *Inst = Iter++; |
| 107 if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { |
| 108 if (Load->getType() == I1Ty) { |
| 109 Changed = true; |
| 110 Value *Ptr = CopyDebug( |
| 111 new BitCastInst( |
| 112 Load->getPointerOperand(), I8Ty->getPointerTo(), |
| 113 Load->getPointerOperand()->getName() + ".i8ptr", Load), Load); |
| 114 LoadInst *NewLoad = new LoadInst( |
| 115 Ptr, Load->getName() + ".pre_trunc", Load); |
| 116 CopyDebug(NewLoad, Load); |
| 117 CopyLoadOrStoreAttrs(NewLoad, Load); |
| 118 Value *Result = CopyDebug(new TruncInst(NewLoad, I1Ty, "", Load), Load); |
| 119 Result->takeName(Load); |
| 120 Load->replaceAllUsesWith(Result); |
| 121 Load->eraseFromParent(); |
| 122 } |
| 123 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { |
| 124 if (Store->getValueOperand()->getType() == I1Ty) { |
| 125 Changed = true; |
| 126 Value *Ptr = CopyDebug( |
| 127 new BitCastInst( |
| 128 Store->getPointerOperand(), I8Ty->getPointerTo(), |
| 129 Store->getPointerOperand()->getName() + ".i8ptr", Store), |
| 130 Store); |
| 131 Value *Val = promoteValue(Store->getValueOperand(), false, Store); |
| 132 StoreInst *NewStore = new StoreInst(Val, Ptr, Store); |
| 133 CopyDebug(NewStore, Store); |
| 134 CopyLoadOrStoreAttrs(NewStore, Store); |
| 135 Store->eraseFromParent(); |
| 136 } |
| 137 } else if (BinaryOperator *Op = dyn_cast<BinaryOperator>(Inst)) { |
| 138 if (Op->getType() == I1Ty && |
| 139 !(Op->getOpcode() == Instruction::And || |
| 140 Op->getOpcode() == Instruction::Or || |
| 141 Op->getOpcode() == Instruction::Xor)) { |
| 142 Value *Arg1 = promoteValue(Op->getOperand(0), false, Op); |
| 143 Value *Arg2 = promoteValue(Op->getOperand(1), false, Op); |
| 144 Value *NewOp = CopyDebug( |
| 145 BinaryOperator::Create( |
| 146 Op->getOpcode(), Arg1, Arg2, |
| 147 Op->getName() + ".pre_trunc", Op), Op); |
| 148 Value *Result = CopyDebug(new TruncInst(NewOp, I1Ty, "", Op), Op); |
| 149 Result->takeName(Op); |
| 150 Op->replaceAllUsesWith(Result); |
| 151 Op->eraseFromParent(); |
| 152 } |
| 153 } else if (ICmpInst *Op = dyn_cast<ICmpInst>(Inst)) { |
| 154 if (Op->getOperand(0)->getType() == I1Ty) { |
| 155 Value *Arg1 = promoteValue(Op->getOperand(0), Op->isSigned(), Op); |
| 156 Value *Arg2 = promoteValue(Op->getOperand(1), Op->isSigned(), Op); |
| 157 Value *Result = CopyDebug( |
| 158 new ICmpInst(Op, Op->getPredicate(), Arg1, Arg2, ""), Op); |
| 159 Result->takeName(Op); |
| 160 Op->replaceAllUsesWith(Result); |
| 161 Op->eraseFromParent(); |
| 162 } |
| 163 } |
| 164 } |
| 165 return Changed; |
| 166 } |
| 167 |
| 168 BasicBlockPass *llvm::createPromoteI1OpsPass() { |
| 169 return new PromoteI1Ops(); |
| 170 } |
OLD | NEW |