|
31 | 31 | #include "llvm/IR/Constants.h" |
32 | 32 | #include "llvm/IR/Dominators.h" |
33 | 33 | #include "llvm/IR/Function.h" |
| 34 | +#include "llvm/IR/IRBuilder.h" |
34 | 35 | #include "llvm/IR/InstrTypes.h" |
35 | 36 | #include "llvm/IR/Instruction.h" |
36 | 37 | #include "llvm/IR/Instructions.h" |
@@ -964,32 +965,45 @@ class EarlyCSE { |
964 | 965 | bool overridingStores(const ParseMemoryInst &Earlier, |
965 | 966 | const ParseMemoryInst &Later); |
966 | 967 |
|
967 | | - Value *getOrCreateResult(Value *Inst, Type *ExpectedType) const { |
968 | | - // TODO: We could insert relevant casts on type mismatch here. |
969 | | - if (auto *LI = dyn_cast<LoadInst>(Inst)) |
970 | | - return LI->getType() == ExpectedType ? LI : nullptr; |
971 | | - if (auto *SI = dyn_cast<StoreInst>(Inst)) { |
972 | | - Value *V = SI->getValueOperand(); |
973 | | - return V->getType() == ExpectedType ? V : nullptr; |
| 968 | + Value *getOrCreateResult(Instruction *Inst, Type *ExpectedType) const { |
| 969 | + if (!isa<IntrinsicInst, LoadInst, StoreInst>(Inst)) |
| 970 | + llvm_unreachable("Instruction not supported"); |
| 971 | + |
| 972 | + // The load or the store's first operand. |
| 973 | + Value *V; |
| 974 | + if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { |
| 975 | + if (isHandledNonTargetIntrinsic(II->getIntrinsicID())) |
| 976 | + switch (II->getIntrinsicID()) { |
| 977 | + case Intrinsic::masked_load: |
| 978 | + V = II; |
| 979 | + break; |
| 980 | + case Intrinsic::masked_store: |
| 981 | + V = II->getOperand(0); |
| 982 | + break; |
| 983 | + default: |
| 984 | + return nullptr; |
| 985 | + } |
| 986 | + else |
| 987 | + return TTI.getOrCreateResultFromMemIntrinsic(II, ExpectedType); |
| 988 | + } else { |
| 989 | + V = isa<LoadInst>(Inst) ? Inst : cast<StoreInst>(Inst)->getValueOperand(); |
974 | 990 | } |
975 | | - assert(isa<IntrinsicInst>(Inst) && "Instruction not supported"); |
976 | | - auto *II = cast<IntrinsicInst>(Inst); |
977 | | - if (isHandledNonTargetIntrinsic(II->getIntrinsicID())) |
978 | | - return getOrCreateResultNonTargetMemIntrinsic(II, ExpectedType); |
979 | | - return TTI.getOrCreateResultFromMemIntrinsic(II, ExpectedType); |
980 | | - } |
981 | 991 |
|
982 | | - Value *getOrCreateResultNonTargetMemIntrinsic(IntrinsicInst *II, |
983 | | - Type *ExpectedType) const { |
984 | | - // TODO: We could insert relevant casts on type mismatch here. |
985 | | - switch (II->getIntrinsicID()) { |
986 | | - case Intrinsic::masked_load: |
987 | | - return II->getType() == ExpectedType ? II : nullptr; |
988 | | - case Intrinsic::masked_store: { |
989 | | - Value *V = II->getOperand(0); |
990 | | - return V->getType() == ExpectedType ? V : nullptr; |
991 | | - } |
992 | | - } |
| 992 | + Type *ActualType = V->getType(); |
| 993 | + BasicBlock *TheBB = Inst->getParent(); |
| 994 | + |
| 995 | + // First handle the case when no cast is required. |
| 996 | + if (ActualType == ExpectedType) |
| 997 | + return V; |
| 998 | + |
| 999 | + // Try to create BitCast, SExt, or Trunc. |
| 1000 | + IRBuilder<> Builder(TheBB, std::next(Inst->getIterator())); |
| 1001 | + if (CastInst::castIsValid(Instruction::BitCast, V, ExpectedType)) |
| 1002 | + return Builder.CreateBitCast(V, ExpectedType); |
| 1003 | + if (CastInst::castIsValid(Instruction::SExt, V, ExpectedType)) |
| 1004 | + return Builder.CreateSExt(V, ExpectedType); |
| 1005 | + if (CastInst::castIsValid(Instruction::Trunc, V, ExpectedType)) |
| 1006 | + return Builder.CreateTrunc(V, ExpectedType); |
993 | 1007 | return nullptr; |
994 | 1008 | } |
995 | 1009 |
|
|
0 commit comments