Commit d8f4a7de by Matt Wala

Add support for undef values in ICE IR. Undef values represent an

arbitrary bit pattern and are lowered to a zero constant. IceOperand.h: Introduce a new ConstantUndef subclass of Constant. Add a getConstantZero() method. IceGlobalContext.h / IceGlobalContext.cpp: Implement pooling for ConstantUndefs. IceTargetLoweringX8632.cpp: Legalize ConstantUndefs to constant zeros. llvm2ice.cpp: Translate LLVM Undefs into ConstantUndefs. undef.ll: Test that undef values are recognized and legalized to zero. BUG=none R=jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/339783002
parent bdbe4023
......@@ -74,6 +74,29 @@ private:
uint32_t NextPoolID;
};
// UndefPool maps ICE types to the corresponding ConstantUndef values.
class UndefPool {
UndefPool(const UndefPool &) LLVM_DELETED_FUNCTION;
UndefPool &operator=(const UndefPool &) LLVM_DELETED_FUNCTION;
public:
UndefPool() : NextPoolID(0) {}
ConstantUndef *getOrAdd(GlobalContext *Ctx, Type Ty) {
ContainerType::iterator I = Pool.find(Ty);
if (I != Pool.end())
return I->second;
ConstantUndef *Undef = ConstantUndef::create(Ctx, Ty, NextPoolID++);
Pool[Ty] = Undef;
return Undef;
}
private:
uint32_t NextPoolID;
typedef std::map<Type, ConstantUndef *> ContainerType;
ContainerType Pool;
};
// The global constant pool bundles individual pools of each type of
// interest.
class ConstantPool {
......@@ -86,6 +109,7 @@ public:
TypePool<double, ConstantDouble, true> Doubles;
TypePool<uint64_t, ConstantInteger> Integers;
TypePool<RelocatableTuple, ConstantRelocatable> Relocatables;
UndefPool Undefs;
};
GlobalContext::GlobalContext(llvm::raw_ostream *OsDump,
......@@ -192,6 +216,29 @@ Constant *GlobalContext::getConstantSym(Type Ty, int64_t Offset,
this, Ty, RelocatableTuple(Offset, Name, SuppressMangling));
}
Constant *GlobalContext::getConstantUndef(Type Ty) {
return ConstPool->Undefs.getOrAdd(this, Ty);
}
Constant *GlobalContext::getConstantZero(Type Ty) {
switch (Ty) {
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
case IceType_i64:
return getConstantInt(Ty, 0);
case IceType_f32:
return getConstantFloat(0);
case IceType_f64:
return getConstantDouble(0);
case IceType_void:
case IceType_NUM:
break;
}
llvm_unreachable("Unknown type");
}
ConstantList GlobalContext::getConstantPool(Type Ty) const {
switch (Ty) {
case IceType_i1:
......
......@@ -77,6 +77,10 @@ public:
// Returns a symbolic constant.
Constant *getConstantSym(Type Ty, int64_t Offset, const IceString &Name = "",
bool SuppressMangling = false);
// Returns an undef.
Constant *getConstantUndef(Type Ty);
// Returns a zero value.
Constant *getConstantZero(Type Ty);
// getConstantPool() returns a copy of the constant pool for
// constants of a given type.
ConstantList getConstantPool(Type Ty) const;
......
......@@ -31,6 +31,7 @@ public:
kConstFloat,
kConstDouble,
kConstRelocatable,
kConstUndef,
kConst_Num,
kVariable,
// Target-specific operand classes use kTarget as the starting
......@@ -206,6 +207,40 @@ private:
bool SuppressMangling;
};
// ConstantUndef represents an unspecified bit pattern. Although it is
// legal to lower ConstantUndef to any value, backends should try to
// make code generation deterministic by lowering ConstantUndefs to 0.
class ConstantUndef : public Constant {
public:
static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
uint32_t PoolEntryID) {
return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
}
using Constant::emit;
virtual void emit(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit();
Str << "undef";
}
using Constant::dump;
virtual void dump(GlobalContext *Ctx) const {
Ostream &Str = Ctx->getStrEmit();
Str << "undef";
}
static bool classof(const Operand *Operand) {
return Operand->getKind() == kConstUndef;
}
private:
ConstantUndef(Type Ty, uint32_t PoolEntryID)
: Constant(kConstUndef, Ty, PoolEntryID) {}
ConstantUndef(const ConstantUndef &) LLVM_DELETED_FUNCTION;
ConstantUndef &operator=(const ConstantUndef &) LLVM_DELETED_FUNCTION;
virtual ~ConstantUndef() {}
};
// RegWeight is a wrapper for a uint32_t weight value, with a
// special value that represents infinite weight, and an addWeight()
// method that ensures that W+infinity=infinity.
......
......@@ -2160,6 +2160,20 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
return From;
}
if (llvm::isa<Constant>(From)) {
if (llvm::isa<ConstantUndef>(From)) {
// Lower undefs to zero. Another option is to lower undefs to an
// uninitialized register; however, using an uninitialized register
// results in less predictable code.
//
// If in the future the implementation is changed to lower undef
// values to uninitialized registers, a FakeDef will be needed:
// Context.insert(InstFakeDef::create(Func, Reg));
// This is in order to ensure that the live range of Reg is not
// overestimated. If the constant being lowered is a 64 bit value,
// then the result should be split and the lo and hi components will
// need to go in uninitialized registers.
From = Ctx->getConstantZero(From->getType());
}
if (!(Allowed & Legal_Imm)) {
Variable *Reg = makeReg(From->getType(), RegNum);
_mov(Reg, From);
......
......@@ -117,6 +117,8 @@ public:
return Ctx->getConstantDouble(CFP->getValueAPF().convertToDouble());
llvm_unreachable("Unexpected floating point type");
return NULL;
} else if (const UndefValue *CU = dyn_cast<UndefValue>(Const)) {
return Ctx->getConstantUndef(convertType(CU->getType()));
} else {
llvm_unreachable("Unhandled constant type");
return NULL;
......
; This test checks that undef values are represented as zero.
; RUN: %llvm2ice --verbose none %s | FileCheck %s
; RUN: %llvm2ice -O2 --verbose none %s | FileCheck %s
; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s
; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s
; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \
; RUN: | FileCheck --check-prefix=DUMP %s
define i32 @undefi32() {
entry:
; CHECK-LABEL: undefi32:
ret i32 undef
; CHECK: mov eax, 0
; CHECK: ret
}
define i64 @undefi64() {
entry:
; CHECK-LABEL: undefi64:
ret i64 undef
; CHECK-DAG: mov eax, 0
; CHECK-DAG: mov edx, 0
; CHECK: ret
}
define float @undeffloat() {
entry:
; CHECK-LABEL: undeffloat:
ret float undef
; CHECK-NOT: sub esp
; CHECK: fld
; CHECK: ret
}
; ERRORS-NOT: ICE translation error
; DUMP-NOT: SZ
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment