[llvm] r217629 - [CodeGenPrepare] Teach the addressing mode matcher how to promote zext.
Quentin Colombet
qcolombet at apple.com
Thu Sep 11 14:22:14 PDT 2014
Author: qcolombet
Date: Thu Sep 11 16:22:14 2014
New Revision: 217629
URL: http://llvm.org/viewvc/llvm-project?rev=217629&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
llvm/trunk/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll
Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=217629&r1=217628&r2=217629&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Thu Sep 11 16:22:14 2014
@@ -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::c
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 TypePromotio
// 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 TypePromotio
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.
Modified: llvm/trunk/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll?rev=217629&r1=217628&r2=217629&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll (original)
+++ llvm/trunk/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll Thu Sep 11 16:22:14 2014
@@ -67,6 +67,21 @@ define i8 @oneArgPromotion(i32 %arg1, i8
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
More information about the llvm-commits
mailing list