From 9fe79b48b835eae223716623880313d08101cc28 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Tue, 16 Sep 2014 22:36:07 +0000 Subject: [PATCH] [CodeGenPrepare][AddressingModeMatcher] The promotion mechanism was expecting instructions when truncate, sext, or zext were created. Fix that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217926 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenPrepare.cpp | 100 ++++++++++-------- .../X86/codegen-prepare-addrmode-sext.ll | 22 ++++ 2 files changed, 77 insertions(+), 45 deletions(-) diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index 55476328963..2e2eabd8f1e 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -1254,69 +1254,75 @@ class TypePromotionTransaction { /// \brief Build a truncate instruction. class TruncBuilder : public TypePromotionAction { + Value *Val; public: /// \brief Build a truncate instruction of \p Opnd producing a \p Ty /// result. /// trunc Opnd to Ty. TruncBuilder(Instruction *Opnd, Type *Ty) : TypePromotionAction(Opnd) { IRBuilder<> Builder(Opnd); - Inst = cast(Builder.CreateTrunc(Opnd, Ty, "promoted")); - DEBUG(dbgs() << "Do: TruncBuilder: " << *Inst << "\n"); + Val = Builder.CreateTrunc(Opnd, Ty, "promoted"); + DEBUG(dbgs() << "Do: TruncBuilder: " << *Val << "\n"); } - /// \brief Get the built instruction. - Instruction *getBuiltInstruction() { return Inst; } + /// \brief Get the built value. + Value *getBuiltValue() { return Val; } /// \brief Remove the built instruction. void undo() override { - DEBUG(dbgs() << "Undo: TruncBuilder: " << *Inst << "\n"); - Inst->eraseFromParent(); + DEBUG(dbgs() << "Undo: TruncBuilder: " << *Val << "\n"); + if (Instruction *IVal = dyn_cast(Val)) + IVal->eraseFromParent(); } }; /// \brief Build a sign extension instruction. class SExtBuilder : public TypePromotionAction { + Value *Val; public: /// \brief Build a sign extension instruction of \p Opnd producing a \p Ty /// result. /// sext Opnd to Ty. SExtBuilder(Instruction *InsertPt, Value *Opnd, Type *Ty) - : TypePromotionAction(Inst) { + : TypePromotionAction(InsertPt) { IRBuilder<> Builder(InsertPt); - Inst = cast(Builder.CreateSExt(Opnd, Ty, "promoted")); - DEBUG(dbgs() << "Do: SExtBuilder: " << *Inst << "\n"); + Val = Builder.CreateSExt(Opnd, Ty, "promoted"); + DEBUG(dbgs() << "Do: SExtBuilder: " << *Val << "\n"); } - /// \brief Get the built instruction. - Instruction *getBuiltInstruction() { return Inst; } + /// \brief Get the built value. + Value *getBuiltValue() { return Val; } /// \brief Remove the built instruction. void undo() override { - DEBUG(dbgs() << "Undo: SExtBuilder: " << *Inst << "\n"); - Inst->eraseFromParent(); + DEBUG(dbgs() << "Undo: SExtBuilder: " << *Val << "\n"); + if (Instruction *IVal = dyn_cast(Val)) + IVal->eraseFromParent(); } }; /// \brief Build a zero extension instruction. class ZExtBuilder : public TypePromotionAction { + Value *Val; 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) { + : TypePromotionAction(InsertPt) { IRBuilder<> Builder(InsertPt); - Inst = cast(Builder.CreateZExt(Opnd, Ty, "promoted")); - DEBUG(dbgs() << "Do: ZExtBuilder: " << *Inst << "\n"); + Val = Builder.CreateZExt(Opnd, Ty, "promoted"); + DEBUG(dbgs() << "Do: ZExtBuilder: " << *Val << "\n"); } - /// \brief Get the built instruction. - Instruction *getBuiltInstruction() { return Inst; } + /// \brief Get the built value. + Value *getBuiltValue() { return Val; } /// \brief Remove the built instruction. void undo() override { - DEBUG(dbgs() << "Undo: ZExtBuilder: " << *Inst << "\n"); - Inst->eraseFromParent(); + DEBUG(dbgs() << "Undo: ZExtBuilder: " << *Val << "\n"); + if (Instruction *IVal = dyn_cast(Val)) + IVal->eraseFromParent(); } }; @@ -1445,11 +1451,11 @@ public: /// Same as Value::mutateType. void mutateType(Instruction *Inst, Type *NewTy); /// Same as IRBuilder::createTrunc. - Instruction *createTrunc(Instruction *Opnd, Type *Ty); + Value *createTrunc(Instruction *Opnd, Type *Ty); /// Same as IRBuilder::createSExt. - Instruction *createSExt(Instruction *Inst, Value *Opnd, Type *Ty); + Value *createSExt(Instruction *Inst, Value *Opnd, Type *Ty); /// Same as IRBuilder::createZExt. - Instruction *createZExt(Instruction *Inst, Value *Opnd, Type *Ty); + Value *createZExt(Instruction *Inst, Value *Opnd, Type *Ty); /// Same as Instruction::moveBefore. void moveBefore(Instruction *Inst, Instruction *Before); /// @} @@ -1481,28 +1487,28 @@ void TypePromotionTransaction::mutateType(Instruction *Inst, Type *NewTy) { Actions.push_back(make_unique(Inst, NewTy)); } -Instruction *TypePromotionTransaction::createTrunc(Instruction *Opnd, - Type *Ty) { +Value *TypePromotionTransaction::createTrunc(Instruction *Opnd, + Type *Ty) { std::unique_ptr Ptr(new TruncBuilder(Opnd, Ty)); - Instruction *I = Ptr->getBuiltInstruction(); + Value *Val = Ptr->getBuiltValue(); Actions.push_back(std::move(Ptr)); - return I; + return Val; } -Instruction *TypePromotionTransaction::createSExt(Instruction *Inst, - Value *Opnd, Type *Ty) { +Value *TypePromotionTransaction::createSExt(Instruction *Inst, + Value *Opnd, Type *Ty) { std::unique_ptr Ptr(new SExtBuilder(Inst, Opnd, Ty)); - Instruction *I = Ptr->getBuiltInstruction(); + Value *Val = Ptr->getBuiltValue(); Actions.push_back(std::move(Ptr)); - return I; + return Val; } -Instruction *TypePromotionTransaction::createZExt(Instruction *Inst, - Value *Opnd, Type *Ty) { +Value *TypePromotionTransaction::createZExt(Instruction *Inst, + Value *Opnd, Type *Ty) { std::unique_ptr Ptr(new ZExtBuilder(Inst, Opnd, Ty)); - Instruction *I = Ptr->getBuiltInstruction(); + Value *Val = Ptr->getBuiltValue(); Actions.push_back(std::move(Ptr)); - return I; + return Val; } void TypePromotionTransaction::moveBefore(Instruction *Inst, @@ -1849,15 +1855,15 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt( // 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(SExt->getOperand(0)); - Instruction *ExtInst = SExt; + Value *ExtVal = SExt; if (isa(SExtOpnd)) { // Replace sext(zext(opnd)) // => zext(opnd). - Instruction *ZExt = + Value *ZExt = TPT.createZExt(SExt, SExtOpnd->getOperand(0), SExt->getType()); TPT.replaceAllUsesWith(SExt, ZExt); TPT.eraseInstruction(SExt); - ExtInst = ZExt; + ExtVal = ZExt; } else { // Replace sext(trunc(opnd)) or sext(sext(opnd)) // => sext(opnd). @@ -1870,8 +1876,9 @@ Value *TypePromotionHelper::promoteOperandForTruncAndAnyExt( TPT.eraseInstruction(SExtOpnd); // Check if the extension is still needed. - if (ExtInst->getType() != ExtInst->getOperand(0)->getType()) - return ExtInst; + Instruction *ExtInst = dyn_cast(ExtVal); + if (!ExtInst || ExtInst->getType() != ExtInst->getOperand(0)->getType()) + return ExtVal; // At this point we have: ext ty opnd to ty. // Reassign the uses of ExtInst to the opnd and remove ExtInst. @@ -1894,10 +1901,12 @@ TypePromotionHelper::promoteOperandForOther(Instruction *SExt, // All its uses, but SExt, will need to use a truncated value of the // promoted version. // Create the truncate now. - Instruction *Trunc = TPT.createTrunc(SExt, SExtOpnd->getType()); - Trunc->removeFromParent(); - // Insert it just after the definition. - Trunc->insertAfter(SExtOpnd); + Value *Trunc = TPT.createTrunc(SExt, SExtOpnd->getType()); + if (Instruction *ITrunc = dyn_cast(Trunc)) { + ITrunc->removeFromParent(); + // Insert it just after the definition. + ITrunc->insertAfter(SExtOpnd); + } TPT.replaceAllUsesWith(SExtOpnd, Trunc); // Restore the operand of SExt (which has been replace by the previous call @@ -1951,7 +1960,8 @@ TypePromotionHelper::promoteOperandForOther(Instruction *SExt, if (!SExtForOpnd) { // If yes, create a new one. DEBUG(dbgs() << "More operands to sext\n"); - SExtForOpnd = TPT.createSExt(SExt, Opnd, SExt->getType()); + SExtForOpnd = + cast(TPT.createSExt(SExt, Opnd, SExt->getType())); ++CreatedInsts; } diff --git a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll index aafbd3e2797..44626e03011 100644 --- a/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll +++ b/test/CodeGen/X86/codegen-prepare-addrmode-sext.ll @@ -82,6 +82,28 @@ define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) { ret i8 %res } +; When promoting a constant zext, the IR builder returns a constant, +; not an instruction. Make sure this is properly handled. This used +; to crash. +; Note: The constant zext is promoted, but does not help matching +; more thing in the addressing mode. Therefore the modification is +; rolled back. +; Still, this test case exercises the desired code path. +; CHECK-LABEL: @oneArgPromotionCstZExt +; CHECK: [[ZEXT:%[a-zA-Z_0-9-]+]] = zext i16 undef to i32 +; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ZEXT]] to i64 +; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[SEXT]], 1 +; CHECK: getelementptr inbounds i8* %base, i64 [[PROMOTED]] +; CHECK: ret +define i8 @oneArgPromotionCstZExt(i8* %base) { + %cst = zext i16 undef to i32 + %add = add nsw i32 %cst, 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 -- 2.34.1