summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2008-11-19 09:36:46 +0000
committerDaniel Dunbar <daniel@zuster.org>2008-11-19 09:36:46 +0000
commit9b1335eca844fb364e78f5de1f5efa968900a120 (patch)
tree4470a163ffa4744697e048905633a2344b2762a6 /clang/lib/CodeGen/CGExpr.cpp
parentfd2c607026c9b70f9e5afe58fde7e5771ce5e53f (diff)
downloadbcm5719-llvm-9b1335eca844fb364e78f5de1f5efa968900a120.tar.gz
bcm5719-llvm-9b1335eca844fb364e78f5de1f5efa968900a120.zip
Fix redundant load of bit-fields on assignment (to get the updated
value). - Use extra argument to EmitStoreThroughLValue to provide place to write update bit-field value if caller requires it. - This fixes several FIXMEs. llvm-svn: 59615
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp26
1 files changed, 23 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 95733abbab4..9328a535670 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -392,7 +392,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
}
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
- QualType Ty) {
+ QualType Ty,
+ llvm::Value **Result) {
unsigned StartBit = Dst.getBitfieldStartBit();
unsigned BitfieldSize = Dst.getBitfieldSize();
llvm::Value *Ptr = Dst.getBitfieldAddr();
@@ -403,12 +404,31 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// Get the new value, cast to the appropriate type and masked to
// exactly the size of the bit-field.
- llvm::Value *NewVal = Src.getScalarVal();
- NewVal = Builder.CreateIntCast(NewVal, EltTy, false, "tmp");
+ llvm::Value *SrcVal = Src.getScalarVal();
+ llvm::Value *NewVal = Builder.CreateIntCast(SrcVal, EltTy, false, "tmp");
llvm::Constant *Mask =
llvm::ConstantInt::get(llvm::APInt::getLowBitsSet(EltTySize, BitfieldSize));
NewVal = Builder.CreateAnd(NewVal, Mask, "bf.value");
+ // Return the new value of the bit-field, if requested.
+ if (Result) {
+ // Cast back to the proper type for result.
+ const llvm::Type *SrcTy = SrcVal->getType();
+ llvm::Value *SrcTrunc = Builder.CreateIntCast(NewVal, SrcTy, false,
+ "bf.reload.val");
+
+ // Sign extend if necessary.
+ if (Dst.isBitfieldSigned()) {
+ unsigned SrcTySize = CGM.getTargetData().getTypeSizeInBits(SrcTy);
+ llvm::Value *ExtraBits = llvm::ConstantInt::get(SrcTy,
+ SrcTySize - BitfieldSize);
+ SrcTrunc = Builder.CreateAShr(Builder.CreateShl(SrcTrunc, ExtraBits),
+ ExtraBits, "bf.reload.sext");
+ }
+
+ *Result = SrcTrunc;
+ }
+
// In some cases the bitfield may straddle two memory locations.
// Emit the low part first and check to see if the high needs to be
// done.
OpenPOWER on IntegriCloud