Index: lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- lib/CodeGen/CodeGenPrepare.cpp +++ lib/CodeGen/CodeGenPrepare.cpp @@ -223,8 +223,14 @@ namespace { +enum ExtType { + ZeroExtension, // Zero extension has been seen. + SignExtension, // Sign extension has been seen. + BothExtension // Both extension have been seen. +}; + using SetOfInstrs = SmallPtrSet; -using TypeIsSExt = PointerIntPair; +using TypeIsSExt = PointerIntPair; using InstrToOrigTy = DenseMap; using SExts = SmallVector; using ValueToSExts = DenseMap; @@ -3277,6 +3283,30 @@ /// 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() && It->second.getInt() != ExtTy) + ExtTy = BothExtension; + PromotedInsts[ExtOpnd] = TypeIsSExt(ExtOpnd->getType(), ExtTy); + } + + /// Utility function to query the original type of instruction \p Opnd + /// with a matched 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 +3495,9 @@ // 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(Opnd)) || (!IsSExt && isa(Opnd))) OpndType = Opnd->getOperand(0)->getType(); else @@ -3596,8 +3625,7 @@ // 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( - ExtOpnd, TypeIsSExt(ExtOpnd->getType(), IsSExt))); + addPromotedInst(PromotedInsts, ExtOpnd, IsSExt); // Step #1. TPT.mutateType(ExtOpnd, Ext->getType()); // Step #2. Index: test/Transforms/CodeGenPrepare/X86/pr38125.ll =================================================================== --- test/Transforms/CodeGenPrepare/X86/pr38125.ll +++ test/Transforms/CodeGenPrepare/X86/pr38125.ll @@ -0,0 +1,32 @@ +; 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) + +@b = global i16 0, align 2 + +; CHECK: %promoted = trunc i32 %or to i16 +; CHECK-NEXT: %c = sext i16 %promoted to i64 +define i32 @foo() { +entry: + %cmp6 = icmp sgt i32 0, -1 + br i1 %cmp6, label %t, label %f + +f: + br label %end + +t: + br label %end + +end: + %t3 = phi i16 [ 0, %f ], [ -3, %t ] + %t4 = load i16, i16* @b, align 2 + %conv4 = zext i16 %t4 to i32 + %or = or i16 %t3, %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 +}