mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-24 11:36:10 +00:00
[CodeGenPrepare] Teach the addressing mode matcher how to promote zext.
I.e., teach it about 'sext (zext a to ty) to ty2' => zext a to ty2. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217629 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
85d436d90a
commit
dcc0e7eaa1
@ -1297,6 +1297,29 @@ class TypePromotionTransaction {
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Build a zero extension instruction.
|
||||
class ZExtBuilder : public TypePromotionAction {
|
||||
public:
|
||||
/// \brief Build a zero extension instruction of \p Opnd producing a \p Ty
|
||||
/// result.
|
||||
/// zext Opnd to Ty.
|
||||
ZExtBuilder(Instruction *InsertPt, Value *Opnd, Type *Ty)
|
||||
: TypePromotionAction(Inst) {
|
||||
IRBuilder<> Builder(InsertPt);
|
||||
Inst = cast<Instruction>(Builder.CreateZExt(Opnd, Ty, "promoted"));
|
||||
DEBUG(dbgs() << "Do: ZExtBuilder: " << *Inst << "\n");
|
||||
}
|
||||
|
||||
/// \brief Get the built instruction.
|
||||
Instruction *getBuiltInstruction() { return Inst; }
|
||||
|
||||
/// \brief Remove the built instruction.
|
||||
void undo() override {
|
||||
DEBUG(dbgs() << "Undo: ZExtBuilder: " << *Inst << "\n");
|
||||
Inst->eraseFromParent();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Mutate an instruction to another type.
|
||||
class TypeMutator : public TypePromotionAction {
|
||||
/// Record the original type.
|
||||
@ -1425,6 +1448,8 @@ public:
|
||||
Instruction *createTrunc(Instruction *Opnd, Type *Ty);
|
||||
/// Same as IRBuilder::createSExt.
|
||||
Instruction *createSExt(Instruction *Inst, Value *Opnd, Type *Ty);
|
||||
/// Same as IRBuilder::createZExt.
|
||||
Instruction *createZExt(Instruction *Inst, Value *Opnd, Type *Ty);
|
||||
/// Same as Instruction::moveBefore.
|
||||
void moveBefore(Instruction *Inst, Instruction *Before);
|
||||
/// @}
|
||||
@ -1472,6 +1497,14 @@ Instruction *TypePromotionTransaction::createSExt(Instruction *Inst,
|
||||
return I;
|
||||
}
|
||||
|
||||
Instruction *TypePromotionTransaction::createZExt(Instruction *Inst,
|
||||
Value *Opnd, Type *Ty) {
|
||||
std::unique_ptr<ZExtBuilder> Ptr(new ZExtBuilder(Inst, Opnd, Ty));
|
||||
Instruction *I = Ptr->getBuiltInstruction();
|
||||
Actions.push_back(std::move(Ptr));
|
||||
return I;
|
||||
}
|
||||
|
||||
void TypePromotionTransaction::moveBefore(Instruction *Inst,
|
||||
Instruction *Before) {
|
||||
Actions.push_back(
|
||||
@ -1684,16 +1717,16 @@ class TypePromotionHelper {
|
||||
}
|
||||
|
||||
/// \brief Utility function to promote the operand of \p SExt when this
|
||||
/// operand is a promotable trunc or sext.
|
||||
/// operand is a promotable trunc or sext or zext.
|
||||
/// \p PromotedInsts maps the instructions to their type before promotion.
|
||||
/// \p CreatedInsts[out] contains how many non-free instructions have been
|
||||
/// created to promote the operand of SExt.
|
||||
/// Should never be called directly.
|
||||
/// \return The promoted value which is used instead of SExt.
|
||||
static Value *promoteOperandForTruncAndSExt(Instruction *SExt,
|
||||
TypePromotionTransaction &TPT,
|
||||
InstrToOrigTy &PromotedInsts,
|
||||
unsigned &CreatedInsts);
|
||||
static Value *promoteOperandForTruncAndAnyExt(Instruction *SExt,
|
||||
TypePromotionTransaction &TPT,
|
||||
InstrToOrigTy &PromotedInsts,
|
||||
unsigned &CreatedInsts);
|
||||
|
||||
/// \brief Utility function to promote the operand of \p SExt when this
|
||||
/// operand is promotable and is not a supported trunc or sext.
|
||||
@ -1729,8 +1762,8 @@ public:
|
||||
bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
|
||||
Type *ConsideredSExtType,
|
||||
const InstrToOrigTy &PromotedInsts) {
|
||||
// We can always get through sext.
|
||||
if (isa<SExtInst>(Inst))
|
||||
// We can always get through sext or zext.
|
||||
if (isa<SExtInst>(Inst) || isa<ZExtInst>(Inst))
|
||||
return true;
|
||||
|
||||
// We can get through binary operator, if it is legal. In other words, the
|
||||
@ -1798,8 +1831,9 @@ TypePromotionHelper::Action TypePromotionHelper::getAction(
|
||||
|
||||
// SExt or Trunc instructions.
|
||||
// Return the related handler.
|
||||
if (isa<SExtInst>(SExtOpnd) || isa<TruncInst>(SExtOpnd))
|
||||
return promoteOperandForTruncAndSExt;
|
||||
if (isa<SExtInst>(SExtOpnd) || isa<TruncInst>(SExtOpnd) ||
|
||||
isa<ZExtInst>(SExtOpnd))
|
||||
return promoteOperandForTruncAndAnyExt;
|
||||
|
||||
// Regular instruction.
|
||||
// Abort early if we will have to insert non-free instructions.
|
||||
@ -1809,15 +1843,24 @@ TypePromotionHelper::Action TypePromotionHelper::getAction(
|
||||
return promoteOperandForOther;
|
||||
}
|
||||
|
||||
Value *TypePromotionHelper::promoteOperandForTruncAndSExt(
|
||||
Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||
llvm::Instruction *SExt, TypePromotionTransaction &TPT,
|
||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts) {
|
||||
// By construction, the operand of SExt is an instruction. Otherwise we cannot
|
||||
// get through it and this method should not be called.
|
||||
Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
|
||||
// Replace sext(trunc(opnd)) or sext(sext(opnd))
|
||||
// => sext(opnd).
|
||||
TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
|
||||
if (isa<ZExtInst>(SExtOpnd)) {
|
||||
// Replace sext(zext(opnd))
|
||||
// => zext(opnd).
|
||||
Instruction *ZExt =
|
||||
TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType());
|
||||
TPT.replaceAllUsesWith(SExt, ZExt);
|
||||
TPT.eraseInstruction(SExt);
|
||||
} else {
|
||||
// Replace sext(trunc(opnd)) or sext(sext(opnd))
|
||||
// => sext(opnd).
|
||||
TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
|
||||
}
|
||||
CreatedInsts = 0;
|
||||
|
||||
// Remove dead code.
|
||||
|
@ -67,6 +67,21 @@ define i8 @oneArgPromotion(i32 %arg1, i8* %base) {
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check that we are able to merge a sign extension with a zero extension.
|
||||
; CHECK-LABEL: @oneArgPromotionZExt
|
||||
; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
|
||||
; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1
|
||||
; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]]
|
||||
; CHECK: ret
|
||||
define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) {
|
||||
%zext = zext i8 %arg1 to i32
|
||||
%add = add nsw i32 %zext, 1
|
||||
%sextadd = sext i32 %add to i64
|
||||
%arrayidx = getelementptr inbounds i8* %base, i64 %sextadd
|
||||
%res = load i8* %arrayidx
|
||||
ret i8 %res
|
||||
}
|
||||
|
||||
; Check that we do not promote truncate when we cannot determine the
|
||||
; bits that are dropped.
|
||||
; CHECK-LABEL: @oneArgPromotionBlockTrunc1
|
||||
|
Loading…
x
Reference in New Issue
Block a user