[cfe-commits] r101192 - /cfe/trunk/lib/CodeGen/CGExpr.cpp

Daniel Dunbar daniel at zuster.org
Tue Apr 13 16:34:15 PDT 2010


Author: ddunbar
Date: Tue Apr 13 18:34:15 2010
New Revision: 101192

URL: http://llvm.org/viewvc/llvm-project?rev=101192&view=rev
Log:
IRgen: Move EmitLoadOfBitfieldLValue to use new CGBitfieldInfo::AccessInfo decomposition, instead of computing the access policy itself.
 - This lets the method focus slightly more on emitting clean IR to honor the policy which has been selected. On 403.gcc's combine.c, x86_64, -O0, this reduces the number of lines in the .ll file (~= # of instructions) by 2.5%.

 - No intended functionality change -- at -O3 this should produce equivalent if not identical output. On 403.gcc's combine.c, x86_64, -O3, this isn't quite true and some of the changes are regressions, but I'm not going to worry about that until we move to a new access policy.

 - There is still some room for improvement in the generated IR, in particular we can usually fold the sign-extension of the bit-field into one of the component access. See the FIXME.

Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=101192&r1=101191&r2=101192&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Apr 13 18:34:15 2010
@@ -618,63 +618,73 @@
 RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV,
                                                  QualType ExprType) {
   const CGBitFieldInfo &Info = LV.getBitFieldInfo();
-  unsigned StartBit = Info.Start;
-  unsigned BitfieldSize = Info.Size;
-  llvm::Value *Ptr = getBitFieldAddr(LV, Builder);
-
-  const llvm::Type *EltTy =
-    cast<llvm::PointerType>(Ptr->getType())->getElementType();
-  unsigned EltTySize = CGM.getTargetData().getTypeSizeInBits(EltTy);
-
-  // In some cases the bitfield may straddle two memory locations.  Currently we
-  // load the entire bitfield, then do the magic to sign-extend it if
-  // necessary. This results in somewhat more code than necessary for the common
-  // case (one load), since two shifts accomplish both the masking and sign
-  // extension.
-  unsigned LowBits = std::min(BitfieldSize, EltTySize - StartBit);
-  llvm::Value *Val = Builder.CreateLoad(Ptr, LV.isVolatileQualified(), "tmp");
-
-  // Shift to proper location.
-  if (StartBit)
-    Val = Builder.CreateLShr(Val, StartBit, "bf.lo");
-
-  // Mask off unused bits.
-  llvm::Constant *LowMask = llvm::ConstantInt::get(VMContext,
-                                llvm::APInt::getLowBitsSet(EltTySize, LowBits));
-  Val = Builder.CreateAnd(Val, LowMask, "bf.lo.cleared");
 
-  // Fetch the high bits if necessary.
-  if (LowBits < BitfieldSize) {
-    unsigned HighBits = BitfieldSize - LowBits;
-    llvm::Value *HighPtr = Builder.CreateGEP(Ptr, llvm::ConstantInt::get(
-                            llvm::Type::getInt32Ty(VMContext), 1), "bf.ptr.hi");
-    llvm::Value *HighVal = Builder.CreateLoad(HighPtr,
-                                              LV.isVolatileQualified(),
-                                              "tmp");
-
-    // Mask off unused bits.
-    llvm::Constant *HighMask = llvm::ConstantInt::get(VMContext,
-                               llvm::APInt::getLowBitsSet(EltTySize, HighBits));
-    HighVal = Builder.CreateAnd(HighVal, HighMask, "bf.lo.cleared");
-
-    // Shift to proper location and or in to bitfield value.
-    HighVal = Builder.CreateShl(HighVal, LowBits);
-    Val = Builder.CreateOr(Val, HighVal, "bf.val");
-  }
+  // Get the output type.
+  const llvm::Type *ResLTy = ConvertType(ExprType);
+  unsigned ResSizeInBits = CGM.getTargetData().getTypeSizeInBits(ResLTy);
+
+  // Compute the result as an OR of all of the individual component accesses.
+  llvm::Value *Res = 0;
+  for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
+    const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
+
+    // Get the field pointer.
+    llvm::Value *Ptr = LV.getBitFieldBaseAddr();
+
+    // Only offset by the field index if used, so that incoming values are not
+    // required to be structures.
+    if (AI.FieldIndex)
+      Ptr = Builder.CreateStructGEP(Ptr, AI.FieldIndex, "bf.field");
+
+    // Offset by the byte offset, if used.
+    if (AI.FieldByteOffset) {
+      const llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(VMContext);
+      Ptr = Builder.CreateBitCast(Ptr, i8PTy);
+      Ptr = Builder.CreateConstGEP1_32(Ptr, AI.FieldByteOffset,"bf.field.offs");
+    }
 
-  // Sign extend if necessary.
-  if (Info.IsSigned) {
-    llvm::Value *ExtraBits = llvm::ConstantInt::get(EltTy,
-                                                    EltTySize - BitfieldSize);
-    Val = Builder.CreateAShr(Builder.CreateShl(Val, ExtraBits),
-                             ExtraBits, "bf.val.sext");
+    // Cast to the access type.
+    const llvm::Type *PTy = llvm::Type::getIntNPtrTy(VMContext, AI.AccessWidth,
+                                                    ExprType.getAddressSpace());
+    Ptr = Builder.CreateBitCast(Ptr, PTy);
+
+    // Perform the load.
+    llvm::LoadInst *Load = Builder.CreateLoad(Ptr, LV.isVolatileQualified());
+    if (AI.AccessAlignment)
+      Load->setAlignment(AI.AccessAlignment);
+
+    // Shift out unused low bits and mask out unused high bits.
+    llvm::Value *Val = Load;
+    if (AI.FieldBitStart)
+      Val = Builder.CreateAShr(Load, AI.FieldBitStart);
+    Val = Builder.CreateAnd(Val, llvm::APInt::getLowBitsSet(AI.AccessWidth,
+                                                            AI.TargetBitWidth),
+                            "bf.clear");
+
+    // Extend or truncate to the target size.
+    if (AI.AccessWidth < ResSizeInBits)
+      Val = Builder.CreateZExt(Val, ResLTy);
+    else if (AI.AccessWidth > ResSizeInBits)
+      Val = Builder.CreateTrunc(Val, ResLTy);
+
+    // Shift into place, and OR into the result.
+    if (AI.TargetBitOffset)
+      Val = Builder.CreateShl(Val, AI.TargetBitOffset);
+    Res = Res ? Builder.CreateOr(Res, Val) : Val;
+  }
+
+  // If the bit-field is signed, perform the sign-extension.
+  //
+  // FIXME: This can easily be folded into the load of the high bits, which
+  // could also eliminate the mask of high bits in some situations.
+  if (Info.isSigned()) {
+    unsigned ExtraBits = ResSizeInBits - Info.Size;
+    if (ExtraBits)
+      Res = Builder.CreateAShr(Builder.CreateShl(Res, ExtraBits),
+                               ExtraBits, "bf.val.sext");
   }
 
-  // The bitfield type and the normal type differ when the storage sizes differ
-  // (currently just _Bool).
-  Val = Builder.CreateIntCast(Val, ConvertType(ExprType), false, "tmp");
-
-  return RValue::get(Val);
+  return RValue::get(Res);
 }
 
 RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV,





More information about the cfe-commits mailing list