mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-28 06:35:49 +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.
|
/// \brief Mutate an instruction to another type.
|
||||||
class TypeMutator : public TypePromotionAction {
|
class TypeMutator : public TypePromotionAction {
|
||||||
/// Record the original type.
|
/// Record the original type.
|
||||||
@ -1425,6 +1448,8 @@ public:
|
|||||||
Instruction *createTrunc(Instruction *Opnd, Type *Ty);
|
Instruction *createTrunc(Instruction *Opnd, Type *Ty);
|
||||||
/// Same as IRBuilder::createSExt.
|
/// Same as IRBuilder::createSExt.
|
||||||
Instruction *createSExt(Instruction *Inst, Value *Opnd, Type *Ty);
|
Instruction *createSExt(Instruction *Inst, Value *Opnd, Type *Ty);
|
||||||
|
/// Same as IRBuilder::createZExt.
|
||||||
|
Instruction *createZExt(Instruction *Inst, Value *Opnd, Type *Ty);
|
||||||
/// Same as Instruction::moveBefore.
|
/// Same as Instruction::moveBefore.
|
||||||
void moveBefore(Instruction *Inst, Instruction *Before);
|
void moveBefore(Instruction *Inst, Instruction *Before);
|
||||||
/// @}
|
/// @}
|
||||||
@ -1472,6 +1497,14 @@ Instruction *TypePromotionTransaction::createSExt(Instruction *Inst,
|
|||||||
return I;
|
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,
|
void TypePromotionTransaction::moveBefore(Instruction *Inst,
|
||||||
Instruction *Before) {
|
Instruction *Before) {
|
||||||
Actions.push_back(
|
Actions.push_back(
|
||||||
@ -1684,16 +1717,16 @@ class TypePromotionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Utility function to promote the operand of \p SExt when this
|
/// \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 PromotedInsts maps the instructions to their type before promotion.
|
||||||
/// \p CreatedInsts[out] contains how many non-free instructions have been
|
/// \p CreatedInsts[out] contains how many non-free instructions have been
|
||||||
/// created to promote the operand of SExt.
|
/// created to promote the operand of SExt.
|
||||||
/// Should never be called directly.
|
/// Should never be called directly.
|
||||||
/// \return The promoted value which is used instead of SExt.
|
/// \return The promoted value which is used instead of SExt.
|
||||||
static Value *promoteOperandForTruncAndSExt(Instruction *SExt,
|
static Value *promoteOperandForTruncAndAnyExt(Instruction *SExt,
|
||||||
TypePromotionTransaction &TPT,
|
TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts,
|
InstrToOrigTy &PromotedInsts,
|
||||||
unsigned &CreatedInsts);
|
unsigned &CreatedInsts);
|
||||||
|
|
||||||
/// \brief Utility function to promote the operand of \p SExt when this
|
/// \brief Utility function to promote the operand of \p SExt when this
|
||||||
/// operand is promotable and is not a supported trunc or sext.
|
/// operand is promotable and is not a supported trunc or sext.
|
||||||
@ -1729,8 +1762,8 @@ public:
|
|||||||
bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
|
bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
|
||||||
Type *ConsideredSExtType,
|
Type *ConsideredSExtType,
|
||||||
const InstrToOrigTy &PromotedInsts) {
|
const InstrToOrigTy &PromotedInsts) {
|
||||||
// We can always get through sext.
|
// We can always get through sext or zext.
|
||||||
if (isa<SExtInst>(Inst))
|
if (isa<SExtInst>(Inst) || isa<ZExtInst>(Inst))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// We can get through binary operator, if it is legal. In other words, the
|
// 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.
|
// SExt or Trunc instructions.
|
||||||
// Return the related handler.
|
// Return the related handler.
|
||||||
if (isa<SExtInst>(SExtOpnd) || isa<TruncInst>(SExtOpnd))
|
if (isa<SExtInst>(SExtOpnd) || isa<TruncInst>(SExtOpnd) ||
|
||||||
return promoteOperandForTruncAndSExt;
|
isa<ZExtInst>(SExtOpnd))
|
||||||
|
return promoteOperandForTruncAndAnyExt;
|
||||||
|
|
||||||
// Regular instruction.
|
// Regular instruction.
|
||||||
// Abort early if we will have to insert non-free instructions.
|
// Abort early if we will have to insert non-free instructions.
|
||||||
@ -1809,15 +1843,24 @@ TypePromotionHelper::Action TypePromotionHelper::getAction(
|
|||||||
return promoteOperandForOther;
|
return promoteOperandForOther;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *TypePromotionHelper::promoteOperandForTruncAndSExt(
|
Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt(
|
||||||
llvm::Instruction *SExt, TypePromotionTransaction &TPT,
|
llvm::Instruction *SExt, TypePromotionTransaction &TPT,
|
||||||
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts) {
|
InstrToOrigTy &PromotedInsts, unsigned &CreatedInsts) {
|
||||||
// By construction, the operand of SExt is an instruction. Otherwise we cannot
|
// By construction, the operand of SExt is an instruction. Otherwise we cannot
|
||||||
// get through it and this method should not be called.
|
// get through it and this method should not be called.
|
||||||
Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
|
Instruction *SExtOpnd = cast<Instruction>(SExt->getOperand(0));
|
||||||
// Replace sext(trunc(opnd)) or sext(sext(opnd))
|
if (isa<ZExtInst>(SExtOpnd)) {
|
||||||
// => sext(opnd).
|
// Replace sext(zext(opnd))
|
||||||
TPT.setOperand(SExt, 0, SExtOpnd->getOperand(0));
|
// => 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;
|
CreatedInsts = 0;
|
||||||
|
|
||||||
// Remove dead code.
|
// Remove dead code.
|
||||||
|
@ -67,6 +67,21 @@ define i8 @oneArgPromotion(i32 %arg1, i8* %base) {
|
|||||||
ret i8 %res
|
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
|
; Check that we do not promote truncate when we cannot determine the
|
||||||
; bits that are dropped.
|
; bits that are dropped.
|
||||||
; CHECK-LABEL: @oneArgPromotionBlockTrunc1
|
; CHECK-LABEL: @oneArgPromotionBlockTrunc1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user