Skip to content

Commit

Permalink
Merging r339822:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r339822 | carrot | 2018-08-16 00:08:26 +0200 (Thu, 16 Aug 2018) | 12 lines


[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


------------------------------------------------------------------------

llvm-svn: 340294
  • Loading branch information
zmodem committed Aug 21, 2018
1 parent 72bbf8c commit e71890b
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
56 changes: 49 additions & 7 deletions llvm/lib/CodeGen/CodeGenPrepare.cpp
Expand Up @@ -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>;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -3465,10 +3509,9 @@ bool TypePromotionHelper::canGetThrough(const Instruction *Inst,
// 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
Expand Down Expand Up @@ -3596,8 +3639,7 @@ Value *TypePromotionHelper::promoteOperandForOther(

// 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.
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/Transforms/CodeGenPrepare/X86/multi-extension.ll
@@ -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)

@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
}

0 comments on commit e71890b

Please sign in to comment.