Commit bc004630 by Jan Voung

Split ConstantInteger into ConstantInteger32 and ConstantInteger64.

In many cases, we expect a constant to be 32-bits or less. This simplifies range checking for x86 memory operand displacements (can only be 32-bit), or immediates in instructions (also 32-bit), since we only store 32-bits (so it trivially fits in 32-bits). Checks for whether a constant fits in 8-bits can be done on the 32-bit value instead of the 64-bit value. When TargetLowering sees a 64-bit immediate as an operand on a 64-bit instruction, it should have split the 64-bit immediate into a 32-bit loOperand(), and a 32-bit hiOperand(). So what's left for the Emit pass should be 32-bit constants. Other places which work with constants: - intrinsic operands (the ABI only allows i32 params for atomic mem order, or atomic is lock free byte-size, or the longjmp param). - addressing mode optimization (gep expansion should be working with i32 constants). - insertelement, and extractelement constant indices (bitcode reader restricts the type of the index to be i32 also). I guess now you may end up with multiple copies of what may be the "same" constant (i64 0 vs i32 0). BUG=none R=stichnot@chromium.org Review URL: https://codereview.chromium.org/569033002
parent 97501839
...@@ -102,8 +102,12 @@ public: ...@@ -102,8 +102,12 @@ public:
return Ctx->getConstantSym(convertToIceType(GV->getType()), 0, return Ctx->getConstantSym(convertToIceType(GV->getType()), 0,
GV->getName()); GV->getName());
} else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Const)) { } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Const)) {
return Ctx->getConstantInt(convertToIceType(CI->getType()), Ice::Type Ty = convertToIceType(CI->getType());
CI->getSExtValue()); if (Ty == Ice::IceType_i64) {
return Ctx->getConstantInt64(Ty, CI->getSExtValue());
} else {
return Ctx->getConstantInt32(Ty, CI->getSExtValue());
}
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Const)) { } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Const)) {
Ice::Type Type = convertToIceType(CFP->getType()); Ice::Type Type = convertToIceType(CFP->getType());
if (Type == Ice::IceType_f32) if (Type == Ice::IceType_f32)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <cassert> #include <cassert>
#include <cstdio> // snprintf #include <cstdio> // snprintf
#include <functional> // std::less #include <functional> // std::less
#include <limits>
#include <list> #include <list>
#include <map> #include <map>
#include <set> #include <set>
...@@ -128,6 +129,11 @@ private: ...@@ -128,6 +129,11 @@ private:
Timer &operator=(const Timer &) LLVM_DELETED_FUNCTION; Timer &operator=(const Timer &) LLVM_DELETED_FUNCTION;
}; };
template <typename T> bool WouldOverflowAdd(T X, T Y) {
return ((X > 0 && Y > 0 && (X > std::numeric_limits<T>::max() - Y)) ||
(X < 0 && Y < 0 && (X < std::numeric_limits<T>::min() - Y)));
}
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICEDEFS_H #endif // SUBZERO_SRC_ICEDEFS_H
...@@ -109,7 +109,8 @@ public: ...@@ -109,7 +109,8 @@ public:
ConstantPool() {} ConstantPool() {}
TypePool<float, ConstantFloat, true> Floats; TypePool<float, ConstantFloat, true> Floats;
TypePool<double, ConstantDouble, true> Doubles; TypePool<double, ConstantDouble, true> Doubles;
TypePool<uint64_t, ConstantInteger> Integers; TypePool<uint32_t, ConstantInteger32> Integers32;
TypePool<uint64_t, ConstantInteger64> Integers64;
TypePool<RelocatableTuple, ConstantRelocatable> Relocatables; TypePool<RelocatableTuple, ConstantRelocatable> Relocatables;
UndefPool Undefs; UndefPool Undefs;
}; };
...@@ -289,10 +290,15 @@ IceString GlobalContext::mangleName(const IceString &Name) const { ...@@ -289,10 +290,15 @@ IceString GlobalContext::mangleName(const IceString &Name) const {
GlobalContext::~GlobalContext() {} GlobalContext::~GlobalContext() {}
Constant *GlobalContext::getConstantInt(Type Ty, uint64_t ConstantInt64) { Constant *GlobalContext::getConstantInt64(Type Ty, uint64_t ConstantInt64) {
assert(Ty == IceType_i64);
return ConstPool->Integers64.getOrAdd(this, Ty, ConstantInt64);
}
Constant *GlobalContext::getConstantInt32(Type Ty, uint32_t ConstantInt32) {
if (Ty == IceType_i1) if (Ty == IceType_i1)
ConstantInt64 &= UINT64_C(1); ConstantInt32 &= UINT32_C(1);
return ConstPool->Integers.getOrAdd(this, Ty, ConstantInt64); return ConstPool->Integers32.getOrAdd(this, Ty, ConstantInt32);
} }
Constant *GlobalContext::getConstantFloat(float ConstantFloat) { Constant *GlobalContext::getConstantFloat(float ConstantFloat) {
...@@ -320,8 +326,9 @@ Constant *GlobalContext::getConstantZero(Type Ty) { ...@@ -320,8 +326,9 @@ Constant *GlobalContext::getConstantZero(Type Ty) {
case IceType_i8: case IceType_i8:
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
return getConstantInt32(Ty, 0);
case IceType_i64: case IceType_i64:
return getConstantInt(Ty, 0); return getConstantInt64(Ty, 0);
case IceType_f32: case IceType_f32:
return getConstantFloat(0); return getConstantFloat(0);
case IceType_f64: case IceType_f64:
...@@ -351,8 +358,9 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const { ...@@ -351,8 +358,9 @@ ConstantList GlobalContext::getConstantPool(Type Ty) const {
case IceType_i8: case IceType_i8:
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
return ConstPool->Integers32.getConstantPool();
case IceType_i64: case IceType_i64:
return ConstPool->Integers.getConstantPool(); return ConstPool->Integers64.getConstantPool();
case IceType_f32: case IceType_f32:
return ConstPool->Floats.getConstantPool(); return ConstPool->Floats.getConstantPool();
case IceType_f64: case IceType_f64:
......
...@@ -75,7 +75,8 @@ public: ...@@ -75,7 +75,8 @@ public:
// Manage Constants. // Manage Constants.
// getConstant*() functions are not const because they might add // getConstant*() functions are not const because they might add
// something to the constant pool. // something to the constant pool.
Constant *getConstantInt(Type Ty, uint64_t ConstantInt64); Constant *getConstantInt32(Type Ty, uint32_t ConstantInt32);
Constant *getConstantInt64(Type Ty, uint64_t ConstantInt64);
Constant *getConstantFloat(float Value); Constant *getConstantFloat(float Value);
Constant *getConstantDouble(double Value); Constant *getConstantDouble(double Value);
// Returns a symbolic constant. // Returns a symbolic constant.
......
...@@ -1383,9 +1383,12 @@ void OperandX8632Mem::emit(const Cfg *Func) const { ...@@ -1383,9 +1383,12 @@ void OperandX8632Mem::emit(const Cfg *Func) const {
bool OffsetIsNegative = false; bool OffsetIsNegative = false;
if (Offset == NULL) { if (Offset == NULL) {
OffsetIsZero = true; OffsetIsZero = true;
} else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { } else if (ConstantInteger32 *CI =
llvm::dyn_cast<ConstantInteger32>(Offset)) {
OffsetIsZero = (CI->getValue() == 0); OffsetIsZero = (CI->getValue() == 0);
OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
} else {
assert(llvm::isa<ConstantRelocatable>(Offset));
} }
if (Dumped) { if (Dumped) {
if (!OffsetIsZero) { // Suppress if Offset is known to be 0 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
...@@ -1430,9 +1433,12 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { ...@@ -1430,9 +1433,12 @@ void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const {
bool OffsetIsNegative = false; bool OffsetIsNegative = false;
if (Offset == NULL) { if (Offset == NULL) {
OffsetIsZero = true; OffsetIsZero = true;
} else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) { } else if (ConstantInteger32 *CI =
llvm::dyn_cast<ConstantInteger32>(Offset)) {
OffsetIsZero = (CI->getValue() == 0); OffsetIsZero = (CI->getValue() == 0);
OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0); OffsetIsNegative = (static_cast<int32_t>(CI->getValue()) < 0);
} else {
assert(llvm::isa<ConstantRelocatable>(Offset));
} }
if (Dumped) { if (Dumped) {
if (!OffsetIsZero) { // Suppress if Offset is known to be 0 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
......
...@@ -27,7 +27,8 @@ class Operand { ...@@ -27,7 +27,8 @@ class Operand {
public: public:
enum OperandKind { enum OperandKind {
kConst_Base, kConst_Base,
kConstInteger, kConstInteger32,
kConstInteger64,
kConstFloat, kConstFloat,
kConstDouble, kConstDouble,
kConstRelocatable, kConstRelocatable,
...@@ -152,15 +153,21 @@ private: ...@@ -152,15 +153,21 @@ private:
const T Value; const T Value;
}; };
typedef ConstantPrimitive<uint64_t, Operand::kConstInteger> ConstantInteger; typedef ConstantPrimitive<uint32_t, Operand::kConstInteger32> ConstantInteger32;
typedef ConstantPrimitive<uint64_t, Operand::kConstInteger64> ConstantInteger64;
typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat; typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat;
typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble; typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble;
template <> inline void ConstantInteger::dump(const Cfg *, Ostream &Str) const { template <> inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
if (getType() == IceType_i1) if (getType() == IceType_i1)
Str << (getValue() ? "true" : "false"); Str << (getValue() ? "true" : "false");
else else
Str << static_cast<int64_t>(getValue()); Str << static_cast<int32_t>(getValue());
}
template <> inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
assert(getType() == IceType_i64);
Str << static_cast<int64_t>(getValue());
} }
// RelocatableTuple bundles the parameters that are used to // RelocatableTuple bundles the parameters that are used to
......
...@@ -509,7 +509,8 @@ private: ...@@ -509,7 +509,8 @@ private:
virtual ~TargetGlobalInitX8632() {} virtual ~TargetGlobalInitX8632() {}
}; };
template <> void ConstantInteger::emit(GlobalContext *Ctx) const; template <> void ConstantInteger32::emit(GlobalContext *Ctx) const;
template <> void ConstantInteger64::emit(GlobalContext *Ctx) const;
template <> void ConstantFloat::emit(GlobalContext *Ctx) const; template <> void ConstantFloat::emit(GlobalContext *Ctx) const;
template <> void ConstantDouble::emit(GlobalContext *Ctx) const; template <> void ConstantDouble::emit(GlobalContext *Ctx) const;
......
...@@ -1777,8 +1777,11 @@ void ConstantsParser::ProcessRecord() { ...@@ -1777,8 +1777,11 @@ void ConstantsParser::ProcessRecord() {
if (IntegerType *IType = dyn_cast<IntegerType>( if (IntegerType *IType = dyn_cast<IntegerType>(
Context->convertToLLVMType(NextConstantType))) { Context->convertToLLVMType(NextConstantType))) {
APInt Value(IType->getBitWidth(), NaClDecodeSignRotatedValue(Values[0])); APInt Value(IType->getBitWidth(), NaClDecodeSignRotatedValue(Values[0]));
Ice::Constant *C = Ice::Constant *C = (NextConstantType == Ice::IceType_i64)
getContext()->getConstantInt(NextConstantType, Value.getSExtValue()); ? getContext()->getConstantInt64(
NextConstantType, Value.getSExtValue())
: getContext()->getConstantInt32(
NextConstantType, Value.getSExtValue());
FuncParser->setNextConstantID(C); FuncParser->setNextConstantID(C);
return; return;
} }
......
...@@ -61,4 +61,66 @@ entry: ...@@ -61,4 +61,66 @@ entry:
; CHECK: movss xmm0, dword ptr [eax + 8] ; CHECK: movss xmm0, dword ptr [eax + 8]
} }
define float @address_mode_opt_chaining_overflow(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr1.int = add i32 2147483640, %arg.int
%addr2.int = add i32 %addr1.int, 2147483643
%addr2.ptr = inttoptr i32 %addr2.int to float*
%addr2.load = load float* %addr2.ptr, align 4
ret float %addr2.load
; CHECK-LABEL: address_mode_opt_chaining_overflow:
; CHECK: 2147483640
; CHECK: movss xmm0, dword ptr [{{.*}} + 2147483643]
}
define float @address_mode_opt_chaining_overflow_sub(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr1.int = sub i32 %arg.int, 2147483640
%addr2.int = sub i32 %addr1.int, 2147483643
%addr2.ptr = inttoptr i32 %addr2.int to float*
%addr2.load = load float* %addr2.ptr, align 4
ret float %addr2.load
; CHECK-LABEL: address_mode_opt_chaining_overflow_sub:
; CHECK: 2147483640
; CHECK: movss xmm0, dword ptr [{{.*}} - 2147483643]
}
define float @address_mode_opt_chaining_no_overflow(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr1.int = sub i32 %arg.int, 2147483640
%addr2.int = add i32 %addr1.int, 2147483643
%addr2.ptr = inttoptr i32 %addr2.int to float*
%addr2.load = load float* %addr2.ptr, align 4
ret float %addr2.load
; CHECK-LABEL: address_mode_opt_chaining_no_overflow:
; CHECK: movss xmm0, dword ptr [{{.*}} + 3]
}
define float @address_mode_opt_add_pos_min_int(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr1.int = add i32 %arg.int, 2147483648
%addr1.ptr = inttoptr i32 %addr1.int to float*
%addr1.load = load float* %addr1.ptr, align 4
ret float %addr1.load
; CHECK-LABEL: address_mode_opt_add_pos_min_int:
; CHECK: movss xmm0, dword ptr [{{.*}} - 2147483648]
}
define float @address_mode_opt_sub_min_int(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr1.int = sub i32 %arg.int, 2147483648
%addr1.ptr = inttoptr i32 %addr1.int to float*
%addr1.load = load float* %addr1.ptr, align 4
ret float %addr1.load
; CHECK-LABEL: address_mode_opt_sub_min_int:
; CHECK: movss xmm0, dword ptr [{{.*}} - 2147483648]
}
; ERRORS-NOT: ICE translation error ; ERRORS-NOT: ICE translation error
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