summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2009-04-20 16:03:21 +0000
committerDuncan Sands <baldrick@free.fr>2009-04-20 16:03:21 +0000
commitc3bbf579ae3ddc67bfd06f12496ae24af70e0ba0 (patch)
tree98dd9c878d6ea40dd89ef62602212c15a19ab710
parent5b7ff355038d06a19c1a0c139aa2c61be677bb54 (diff)
downloadllvm-c3bbf579ae3ddc67bfd06f12496ae24af70e0ba0.tar.gz
llvm-c3bbf579ae3ddc67bfd06f12496ae24af70e0ba0.tar.bz2
llvm-c3bbf579ae3ddc67bfd06f12496ae24af70e0ba0.tar.xz
These bitfields were being miscompiled on some
64 bit platforms when building with optimization. So replace them by a hand-coded implementation. This fixes PR3822. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69597 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Transforms/Utils/InlineCost.h38
1 files changed, 27 insertions, 11 deletions
diff --git a/include/llvm/Transforms/Utils/InlineCost.h b/include/llvm/Transforms/Utils/InlineCost.h
index d78a0f0818..f275b76082 100644
--- a/include/llvm/Transforms/Utils/InlineCost.h
+++ b/include/llvm/Transforms/Utils/InlineCost.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include <cassert>
+#include <climits>
#include <map>
#include <vector>
@@ -37,26 +38,41 @@ namespace llvm {
Never
};
- int Cost : 30;
- unsigned Type : 2;
+ // This is a do-it-yourself implementation of
+ // int Cost : 30;
+ // unsigned Type : 2;
+ // We used to use bitfields, but they were sometimes miscompiled (PR3822).
+ enum { TYPE_BITS = 2 };
+ enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS };
+ unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS;
- InlineCost(int C, int T) : Cost(C), Type(T) {
- assert(Cost == C && "Cost exceeds InlineCost precision");
+ Kind getType() const {
+ return Kind(TypedCost >> COST_BITS);
+ }
+
+ int getCost() const {
+ // Sign-extend the bottom COST_BITS bits.
+ return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS;
+ }
+
+ InlineCost(int C, int T) {
+ TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS);
+ assert(getCost() == C && "Cost exceeds InlineCost precision");
}
public:
static InlineCost get(int Cost) { return InlineCost(Cost, Value); }
static InlineCost getAlways() { return InlineCost(0, Always); }
- static InlineCost getNever() { return InlineCost(0, Never); }
+ static InlineCost getNever() { return InlineCost(0, Never); }
- bool isVariable() const { return Type == Value; }
- bool isAlways() const { return Type == Always; }
- bool isNever() const { return Type == Never; }
+ bool isVariable() const { return getType() == Value; }
+ bool isAlways() const { return getType() == Always; }
+ bool isNever() const { return getType() == Never; }
/// getValue() - Return a "variable" inline cost's amount. It is
/// an error to call this on an "always" or "never" InlineCost.
- int getValue() const {
- assert(Type == Value && "Invalid access of InlineCost");
- return Cost;
+ int getValue() const {
+ assert(getType() == Value && "Invalid access of InlineCost");
+ return getCost();
}
};