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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59615 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 95733ab..9328a53 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -392,7 +392,8 @@
 }
 
 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 @@
 
   // 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.