[llvm] r339822 - [CodeGenPrepare] Add BothExtension type to PromotedInsts
Hans Wennborg via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 21 09:16:58 PDT 2018
Merged to 7.0 in r340294.
On Wed, Aug 15, 2018 at 3:08 PM, Guozhi Wei via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: carrot
> Date: Wed Aug 15 15:08:26 2018
> New Revision: 339822
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339822&view=rev
> Log:
>
> [CodeGenPrepare] Add BothExtension type to PromotedInsts
>
> This patch fixes PR38125.
>
> Instruction extension types are recorded in PromotedInsts, it can be used later in function canGetThrough. If an instruction has two users with different extension types, it will be inserted into PromotedInsts two times in function promoteOperandForOther. The second one overwrites the first one, and the final extension type is wrong, later causes problem in canGetThrough.
>
> This patch changes the simple bool extension type to 2-bit enum type, add a BothExtension type in addition to zero/sign extension. When an user sees BothExtension for an instruction, it actually knows nothing about how that instruction is extended.
>
> Differential Revision: https://reviews.llvm.org/D49512
>
>
> Added:
> llvm/trunk/test/Transforms/CodeGenPrepare/X86/multi-extension.ll
> Modified:
> llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
>
> Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=339822&r1=339821&r2=339822&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
> +++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Wed Aug 15 15:08:26 2018
> @@ -223,8 +223,17 @@ static cl::opt<bool>
>
> namespace {
>
> +enum ExtType {
> + ZeroExtension, // Zero extension has been seen.
> + SignExtension, // Sign extension has been seen.
> + BothExtension // This extension type is used if we saw sext after
> + // ZeroExtension had been set, or if we saw zext after
> + // SignExtension had been set. It makes the type
> + // information of a promoted instruction invalid.
> +};
> +
> using SetOfInstrs = SmallPtrSet<Instruction *, 16>;
> -using TypeIsSExt = PointerIntPair<Type *, 1, bool>;
> +using TypeIsSExt = PointerIntPair<Type *, 2, ExtType>;
> using InstrToOrigTy = DenseMap<Instruction *, TypeIsSExt>;
> using SExts = SmallVector<Instruction *, 16>;
> using ValueToSExts = DenseMap<Value *, SExts>;
> @@ -3277,6 +3286,41 @@ namespace {
>
> /// Hepler class to perform type promotion.
> class TypePromotionHelper {
> + /// Utility function to add a promoted instruction \p ExtOpnd to
> + /// \p PromotedInsts and record the type of extension we have seen.
> + static void addPromotedInst(InstrToOrigTy &PromotedInsts,
> + Instruction *ExtOpnd,
> + bool IsSExt) {
> + ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
> + InstrToOrigTy::iterator It = PromotedInsts.find(ExtOpnd);
> + if (It != PromotedInsts.end()) {
> + // If the new extension is same as original, the information in
> + // PromotedInsts[ExtOpnd] is still correct.
> + if (It->second.getInt() == ExtTy)
> + return;
> +
> + // Now the new extension is different from old extension, we make
> + // the type information invalid by setting extension type to
> + // BothExtension.
> + ExtTy = BothExtension;
> + }
> + PromotedInsts[ExtOpnd] = TypeIsSExt(ExtOpnd->getType(), ExtTy);
> + }
> +
> + /// Utility function to query the original type of instruction \p Opnd
> + /// with a matched extension type. If the extension doesn't match, we
> + /// cannot use the information we had on the original type.
> + /// BothExtension doesn't match any extension type.
> + static const Type *getOrigType(const InstrToOrigTy &PromotedInsts,
> + Instruction *Opnd,
> + bool IsSExt) {
> + ExtType ExtTy = IsSExt ? SignExtension : ZeroExtension;
> + InstrToOrigTy::const_iterator It = PromotedInsts.find(Opnd);
> + if (It != PromotedInsts.end() && It->second.getInt() == ExtTy)
> + return It->second.getPointer();
> + return nullptr;
> + }
> +
> /// Utility function to check whether or not a sign or zero extension
> /// of \p Inst with \p ConsideredExtType can be moved through \p Inst by
> /// either using the operands of \p Inst or promoting \p Inst.
> @@ -3465,10 +3509,9 @@ bool TypePromotionHelper::canGetThrough(
> // I.e., check that trunc just drops extended bits of the same kind of
> // the extension.
> // #1 get the type of the operand and check the kind of the extended bits.
> - const Type *OpndType;
> - InstrToOrigTy::const_iterator It = PromotedInsts.find(Opnd);
> - if (It != PromotedInsts.end() && It->second.getInt() == IsSExt)
> - OpndType = It->second.getPointer();
> + const Type *OpndType = getOrigType(PromotedInsts, Opnd, IsSExt);
> + if (OpndType)
> + ;
> else if ((IsSExt && isa<SExtInst>(Opnd)) || (!IsSExt && isa<ZExtInst>(Opnd)))
> OpndType = Opnd->getOperand(0)->getType();
> else
> @@ -3596,8 +3639,7 @@ Value *TypePromotionHelper::promoteOpera
>
> // Remember the original type of the instruction before promotion.
> // This is useful to know that the high bits are sign extended bits.
> - PromotedInsts.insert(std::pair<Instruction *, TypeIsSExt>(
> - ExtOpnd, TypeIsSExt(ExtOpnd->getType(), IsSExt)));
> + addPromotedInst(PromotedInsts, ExtOpnd, IsSExt);
> // Step #1.
> TPT.mutateType(ExtOpnd, Ext->getType());
> // Step #2.
>
> Added: llvm/trunk/test/Transforms/CodeGenPrepare/X86/multi-extension.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CodeGenPrepare/X86/multi-extension.ll?rev=339822&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/CodeGenPrepare/X86/multi-extension.ll (added)
> +++ llvm/trunk/test/Transforms/CodeGenPrepare/X86/multi-extension.ll Wed Aug 15 15:08:26 2018
> @@ -0,0 +1,25 @@
> +; RUN: opt < %s -codegenprepare -S -mtriple=x86_64-unknown-unknown | FileCheck %s
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.13.0"
> +
> +declare void @bar(i64)
> +
> + at b = global i16 0, align 2
> +
> +; This test case is extracted from PR38125.
> +; %or is reachable by both a sext and zext that are going to be promoted.
> +; It ensures correct operation on PromotedInsts.
> +
> +; CHECK: %promoted = trunc i32 %or to i16
> +; CHECK-NEXT: %c = sext i16 %promoted to i64
> +define i32 @foo(i16 %kkk) {
> +entry:
> + %t4 = load i16, i16* @b, align 2
> + %conv4 = zext i16 %t4 to i32
> + %or = or i16 %kkk, %t4
> + %c = sext i16 %or to i64
> + call void @bar(i64 %c)
> + %t5 = and i16 %or, 5
> + %z = zext i16 %t5 to i32
> + ret i32 %z
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list