https://github.com/adams381 updated 
https://github.com/llvm/llvm-project/pull/199130

>From 89957042b7123ffd81af1eab138921d95b95fcd8 Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Thu, 21 May 2026 15:37:16 -0700
Subject: [PATCH 1/2] [CIR] Honor x86-64 high-eightbyte coerced return offset
 in CIRGen

On x86-64 SysV, a 16-byte struct whose low eightbyte is NoClass and
whose high eightbyte is Integer is returned in a single integer
register.  The live value is only valid at offset 8 in the caller's
aggregate slot, not at offset 0.

CIRGen previously stubbed return ABI info as a direct return at offset
0, so call sites stored the full register value at the start of the
destination and inline returns loaded the wrong eightbyte.  Eigen's
symbolic_index test (AddExpr with padding plus ValueExpr<long>) failed
is_same_symb checks for that reason.

Classify this return shape in CIRGenFunctionInfo, use the coerced type
in cir.func/cir.call signatures, store call results at the direct
offset, and load the return slot from the same offset before cir.return.

Add coerced-return-highpart.cpp with CIR, LLVM, and OGCG checks.
---
 clang/include/clang/CIR/ABIArgInfo.h          | 11 ++--
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          | 43 ++++++++++++-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      | 30 ++++++++-
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h    | 12 ++--
 clang/lib/CIR/CodeGen/CIRGenStmt.cpp          | 47 +++++++++++---
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         | 64 +++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenTypes.h           |  2 +
 .../CIR/CodeGen/coerced-return-highpart.cpp   | 56 ++++++++++++++++
 8 files changed, 236 insertions(+), 29 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/coerced-return-highpart.cpp

diff --git a/clang/include/clang/CIR/ABIArgInfo.h 
b/clang/include/clang/CIR/ABIArgInfo.h
index cd679961eb49f..28d831f9a0353 100644
--- a/clang/include/clang/CIR/ABIArgInfo.h
+++ b/clang/include/clang/CIR/ABIArgInfo.h
@@ -53,10 +53,10 @@ class ABIArgInfo {
 public:
   ABIArgInfo(Kind k = Direct) : directAttr{0, 0}, theKind(k) {}
 
-  static ABIArgInfo getDirect(mlir::Type ty = nullptr) {
+  static ABIArgInfo getDirect(mlir::Type ty = nullptr, unsigned offset = 0) {
     ABIArgInfo info(Direct);
     info.setCoerceToType(ty);
-    assert(!cir::MissingFeatures::abiArgInfo());
+    info.directAttr.offset = offset;
     return info;
   }
 
@@ -82,13 +82,10 @@ class ABIArgInfo {
     return false;
   }
 
-  bool canHaveCoerceToType() const {
-    assert(!cir::MissingFeatures::abiArgInfo());
-    return isDirect();
-  }
+  bool canHaveCoerceToType() const { return isDirect(); }
 
   unsigned getDirectOffset() const {
-    assert(!cir::MissingFeatures::abiArgInfo());
+    assert(isDirect() && "ABIArgInfo offset is only valid for Direct");
     return directAttr.offset;
   }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index f648eff375a77..36ce0a05390d8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -15,6 +15,7 @@
 #include "CIRGenCXXABI.h"
 #include "CIRGenFunction.h"
 #include "CIRGenFunctionInfo.h"
+#include "TargetInfo.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/Attributes.h"
 #include "clang/CIR/ABIArgInfo.h"
@@ -42,6 +43,7 @@ CIRGenFunctionInfo *CIRGenFunctionInfo::create(
 
   fi->required = required;
   fi->numArgs = argTypes.size();
+  fi->returnInfo = cir::ABIArgInfo::getDirect();
 
   fi->getArgTypes()[0] = resultType;
   std::copy(argTypes.begin(), argTypes.end(), fi->argTypesBegin());
@@ -56,7 +58,10 @@ cir::FuncType CIRGenTypes::getFunctionType(GlobalDecl gd) {
 }
 
 cir::FuncType CIRGenTypes::getFunctionType(const CIRGenFunctionInfo &info) {
+  const cir::ABIArgInfo &retInfo = info.getReturnInfo();
   mlir::Type resultType = convertType(info.getReturnType());
+  if (retInfo.getDirectOffset() != 0 && retInfo.getCoerceToType())
+    resultType = retInfo.getCoerceToType();
   SmallVector<mlir::Type, 8> argTypes;
   argTypes.reserve(info.getNumRequiredArgs());
 
@@ -1156,6 +1161,35 @@ 
CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
                                 fnpt->getExtInfo(), RequiredArgs(0));
 }
 
+static Address emitAddressAtOffset(CIRGenFunction &cgf, Address addr,
+                                   const cir::ABIArgInfo &info,
+                                   mlir::Location loc) {
+  if (!info.getDirectOffset())
+    return addr;
+  mlir::Value offsetVal =
+      cgf.getBuilder().getUnsignedInt(loc, info.getDirectOffset(), 64);
+  Address byteAddr =
+      addr.withElementType(cgf.getBuilder(), cgf.getBuilder().getUInt8Ty());
+  return byteAddr.withPointer(
+      cgf.getBuilder().createPtrStride(loc, byteAddr.getPointer(), offsetVal));
+}
+
+static void emitCoercedReturnStore(CIRGenFunction &cgf, mlir::Location loc,
+                                   mlir::Value retVal, QualType retTy,
+                                   Address destPtr,
+                                   const cir::ABIArgInfo &retInfo) {
+  if (isEmptyRecordForLayout(cgf.getContext(), retTy))
+    return;
+  Address storePtr = emitAddressAtOffset(cgf, destPtr, retInfo, loc);
+  mlir::Type storeTy = retInfo.getCoerceToType();
+  if (!storeTy)
+    storeTy = retVal.getType();
+  if (retVal.getType() != storeTy)
+    cgf.cgm.errorNYI(loc, "coerced return value type mismatch");
+  storePtr = storePtr.withElementType(cgf.getBuilder(), storeTy);
+  cgf.getBuilder().createStore(loc, retVal, storePtr);
+}
+
 RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
                                 const CIRGenCallee &callee,
                                 ReturnValueSlot returnValue,
@@ -1354,8 +1388,13 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
     mlir::ResultRange results = theCall->getOpResults();
     assert(results.size() <= 1 && "multiple returns from a call");
 
-    SourceLocRAIIObject loc{*this, callLoc};
-    emitAggregateStore(results[0], destPtr);
+    SourceLocRAIIObject locRAII{*this, callLoc};
+    const cir::ABIArgInfo retInfo = funcInfo.getReturnInfo();
+    if (retInfo.getDirectOffset() != 0)
+      emitCoercedReturnStore(*this, callLoc, results[0], retTy, destPtr,
+                             retInfo);
+    else
+      emitAggregateStore(results[0], destPtr);
     return RValue::getAggregate(destPtr);
   }
   case cir::TEK_Scalar: {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 52e7a9d3de412..5d788fe0cb69d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -329,6 +329,19 @@ void CIRGenFunction::LexicalScope::cleanup() {
   }
 }
 
+static Address emitReturnSlotAtOffset(CIRGenFunction &cgf, Address addr,
+                                      const cir::ABIArgInfo &info,
+                                      mlir::Location loc) {
+  if (!info.getDirectOffset())
+    return addr;
+  mlir::Value offsetVal =
+      cgf.getBuilder().getUnsignedInt(loc, info.getDirectOffset(), 64);
+  Address byteAddr =
+      addr.withElementType(cgf.getBuilder(), cgf.getBuilder().getUInt8Ty());
+  return byteAddr.withPointer(
+      cgf.getBuilder().createPtrStride(loc, byteAddr.getPointer(), offsetVal));
+}
+
 cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
   CIRGenBuilderTy &builder = cgf.getBuilder();
 
@@ -336,9 +349,20 @@ cir::ReturnOp 
CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
   assert(fn && "emitReturn from non-function");
 
   if (!fn.getFunctionType().hasVoidReturn()) {
-    // Load the value from `__retval` and return it via the `cir.return` op.
-    auto value = cir::LoadOp::create(
-        builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
+    const CIRGenFunctionInfo &fnInfo =
+        cgf.cgm.getTypes().arrangeGlobalDeclaration(cgf.curGD);
+    const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
+    mlir::Type loadTy = fn.getFunctionType().getReturnType();
+    Address loadAddr = cgf.returnValue;
+    if (retInfo.getDirectOffset() != 0) {
+      loadAddr = emitReturnSlotAtOffset(cgf, loadAddr, retInfo, loc);
+      if (retInfo.getCoerceToType()) {
+        loadTy = retInfo.getCoerceToType();
+        loadAddr = loadAddr.withElementType(cgf.getBuilder(), loadTy);
+      }
+    }
+    auto value =
+        cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
     return cir::ReturnOp::create(builder, loc,
                                  llvm::ArrayRef(value.getResult()));
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h 
b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index d37a6149bcafa..4c1497aaa36be 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -95,6 +95,8 @@ class CIRGenFunctionInfo final
 
   RequiredArgs required;
 
+  cir::ABIArgInfo returnInfo;
+
   unsigned numArgs;
 
   CanQualType *getArgTypes() { return getTrailingObjects(); }
@@ -123,6 +125,7 @@ class CIRGenFunctionInfo final
   // Friending class TrailingObjects is apparantly not good enough for MSVC, so
   // these have to be public.
   friend class TrailingObjects;
+  friend class CIRGenTypes;
 
   using const_arg_iterator = const CanQualType *;
   using arg_iterator = CanQualType *;
@@ -160,14 +163,7 @@ class CIRGenFunctionInfo final
 
   CanQualType getReturnType() const { return getArgTypes()[0]; }
 
-  cir::ABIArgInfo getReturnInfo() const {
-    assert(!cir::MissingFeatures::abiArgInfo());
-    // TODO(cir): we currently just 'fake' this, but should calculate
-    // this/figure out what it means when we get our ABI info set correctly.
-    // For now, we leave this as a direct return.
-
-    return cir::ABIArgInfo::getDirect();
-  }
+  cir::ABIArgInfo getReturnInfo() const { return returnInfo; }
 
   const_arg_iterator argTypesBegin() const { return getArgTypes() + 1; }
   const_arg_iterator argTypesEnd() const { return getArgTypes() + 1 + numArgs; 
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp 
b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 4777d8e429e34..2a897002ac207 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -667,11 +667,26 @@ mlir::LogicalResult CIRGenFunction::emitReturnStmt(const 
ReturnStmt &s) {
   // directly.
   // TODO(cir): Eliminate this redundant load and the store above when we can.
   if (fnRetAlloca) {
-    // Load the value from `__retval` and return it via the `cir.return` op.
-    cir::AllocaOp retAlloca =
-        mlir::cast<cir::AllocaOp>(fnRetAlloca->getDefiningOp());
-    auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
-                                     *fnRetAlloca);
+    const CIRGenFunctionInfo &fnInfo =
+        cgm.getTypes().arrangeGlobalDeclaration(curGD);
+    const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
+    mlir::Type loadTy =
+        cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
+    Address loadAddr = returnValue;
+    if (retInfo.getDirectOffset() != 0) {
+      mlir::Value offsetVal =
+          builder.getUnsignedInt(loc, retInfo.getDirectOffset(), 64);
+      Address byteAddr =
+          loadAddr.withElementType(builder, builder.getUInt8Ty());
+      loadAddr = byteAddr.withPointer(
+          builder.createPtrStride(loc, byteAddr.getPointer(), offsetVal));
+      if (retInfo.getCoerceToType()) {
+        loadTy = retInfo.getCoerceToType();
+        loadAddr = loadAddr.withElementType(builder, loadTy);
+      }
+    }
+    auto value =
+        cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
 
     cir::ReturnOp::create(builder, loc, {value});
   } else {
@@ -1274,10 +1289,24 @@ void CIRGenFunction::emitReturnOfRValue(mlir::Location 
loc, RValue rv,
   // directly.
   // TODO(cir): Eliminate this redundant load and the store above when we can.
   // Load the value from `__retval` and return it via the `cir.return` op.
-  cir::AllocaOp retAlloca =
-      mlir::cast<cir::AllocaOp>(fnRetAlloca->getDefiningOp());
-  auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
-                                   *fnRetAlloca);
+  const CIRGenFunctionInfo &fnInfo =
+      cgm.getTypes().arrangeGlobalDeclaration(curGD);
+  const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
+  mlir::Type loadTy =
+      cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
+  Address loadAddr = returnValue;
+  if (retInfo.getDirectOffset() != 0) {
+    mlir::Value offsetVal =
+        builder.getUnsignedInt(loc, retInfo.getDirectOffset(), 64);
+    Address byteAddr = loadAddr.withElementType(builder, builder.getUInt8Ty());
+    loadAddr = byteAddr.withPointer(
+        builder.createPtrStride(loc, byteAddr.getPointer(), offsetVal));
+    if (retInfo.getCoerceToType()) {
+      loadTy = retInfo.getCoerceToType();
+      loadAddr = loadAddr.withElementType(builder, loadTy);
+    }
+  }
+  auto value = cir::LoadOp::create(builder, loc, loadTy, 
loadAddr.getPointer());
 
   cir::ReturnOp::create(builder, loc, {value});
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 85b7e854abb7f..cae37eaff6465 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -11,7 +11,10 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 
+#include "llvm/TargetParser/Triple.h"
+
 #include <cassert>
+#include <iterator>
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -711,6 +714,66 @@ bool CIRGenTypes::isZeroInitializable(const RecordDecl 
*rd) {
   return getCIRGenRecordLayout(rd).isZeroInitializable();
 }
 
+cir::ABIArgInfo CIRGenTypes::classifyCIRReturnType(CanQualType retTy) {
+  mlir::Type fullTy = convertType(retTy);
+  const llvm::Triple &triple = cgm.getTriple();
+  if (triple.getArch() != llvm::Triple::x86_64 ||
+      triple.getOS() != llvm::Triple::Linux)
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  if (!isa<RecordType>(retTy))
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  const auto *recTy = cast<RecordType>(retTy);
+  const RecordDecl *rd = cast<RecordDecl>(recTy->getDecl());
+  if (!rd->isCompleteDefinition())
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  CharUnits size = astContext.getTypeSizeInChars(retTy);
+  if (size != CharUnits::fromQuantity(16))
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
+  if (layout.getFieldCount() < 2)
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  if (layout.getFieldOffset(1) !=
+      static_cast<uint64_t>(astContext.toBits(CharUnits::fromQuantity(8))))
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  auto hiFieldIt = rd->field_begin();
+  std::advance(hiFieldIt, 1);
+  QualType hiTy = hiFieldIt->getType();
+  if (astContext.getTypeSizeInChars(hiTy) != CharUnits::fromQuantity(8))
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  mlir::Type coerceTy;
+  if (hiTy->isIntegralOrEnumerationType() || hiTy->isPointerType())
+    coerceTy = convertType(hiTy);
+  else if (const RecordDecl *hiRd = hiTy->getAsRecordDecl()) {
+    if (!hiRd->isCompleteDefinition())
+      return cir::ABIArgInfo::getDirect(fullTy);
+    const ASTRecordLayout &hiLayout = astContext.getASTRecordLayout(hiRd);
+    if (hiLayout.getFieldCount() != 1)
+      return cir::ABIArgInfo::getDirect(fullTy);
+    QualType innerTy = hiRd->field_begin()->getType();
+    if (!innerTy->isIntegralOrEnumerationType())
+      return cir::ABIArgInfo::getDirect(fullTy);
+    coerceTy = convertType(innerTy);
+  } else {
+    return cir::ABIArgInfo::getDirect(fullTy);
+  }
+
+  if (!mlir::isa<cir::IntType>(coerceTy))
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  auto intTy = mlir::cast<cir::IntType>(coerceTy);
+  if (intTy.getWidth() > 64)
+    return cir::ABIArgInfo::getDirect(fullTy);
+
+  return cir::ABIArgInfo::getDirect(coerceTy, 8);
+}
+
 const CIRGenFunctionInfo &CIRGenTypes::arrangeCIRFunctionInfo(
     CanQualType returnType, bool isInstanceMethod,
     llvm::ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info,
@@ -739,6 +802,7 @@ const CIRGenFunctionInfo 
&CIRGenTypes::arrangeCIRFunctionInfo(
   // Construction the function info. We co-allocate the ArgInfos.
   fi = CIRGenFunctionInfo::create(info, isInstanceMethod, returnType, argTypes,
                                   required);
+  fi->returnInfo = classifyCIRReturnType(returnType);
   functionInfos.InsertNode(fi, insertPos);
 
   return *fi;
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index 15955c517f1f3..7aa785505ee1d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -82,6 +82,8 @@ class CIRGenTypes {
   /// Heper for convertType.
   mlir::Type convertFunctionTypeInternal(clang::QualType ft);
 
+  cir::ABIArgInfo classifyCIRReturnType(clang::CanQualType retTy);
+
 public:
   CIRGenTypes(CIRGenModule &cgm);
   ~CIRGenTypes();
diff --git a/clang/test/CIR/CodeGen/coerced-return-highpart.cpp 
b/clang/test/CIR/CodeGen/coerced-return-highpart.cpp
new file mode 100644
index 0000000000000..6e1883d09559c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/coerced-return-highpart.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct Pad8 {
+  char c[8];
+};
+
+struct Val {
+  long v;
+};
+
+struct Ret {
+  Pad8 pad;
+  Val val;
+};
+
+Ret make(long x) {
+  Ret r{{0}, {x}};
+  return r;
+}
+
+long take(Ret r) { return r.val.v; }
+
+long caller() {
+  Ret tmp = make(99);
+  return take(tmp);
+}
+
+// Coerced 16-byte struct return: only the high eightbyte (field at +8) is
+// returned in a register; CIR stores the call result at offset 8.
+// CIR: cir.func {{.*}} @_Z4makel(%{{.*}}: !s64i
+// CIR-SAME: -> !s64i
+// CIR: cir.const #cir.int<8> : !u64i
+// CIR: cir.ptr_stride
+// CIR: cir.load {{.*}} : !cir.ptr<!s64i>, !s64i
+// CIR: cir.return {{.*}} : !s64i
+
+// CIR: cir.func {{.*}} @_Z6callerv()
+// CIR: cir.call @_Z4makel
+// CIR-SAME: -> !s64i
+// CIR: cir.const #cir.int<8> : !u64i
+// CIR: cir.ptr_stride
+// CIR: cir.store {{.*}} : !s64i
+
+// LLVM: define {{.*}} @_Z4makel(i64
+// LLVM: define {{.*}} @_Z6callerv()
+// LLVM: call i64 @_Z4makel(i64
+// LLVM: getelementptr i8, ptr %{{.*}}, i64 8
+
+// OGCG: define {{.*}} @_Z6callerv()
+// OGCG: call { i64, i64 } @_Z4makel(i64
+// OGCG: call noundef i64 @_Z4take3Ret(i64

>From 95d0a9e723f89f0c85ac56b0843f94b7966263ee Mon Sep 17 00:00:00 2001
From: Adam Smith <[email protected]>
Date: Tue, 2 Jun 2026 15:40:52 -0700
Subject: [PATCH 2/2] [CIR] Restore offset-0 return load path in CIRGen

The coerced high-eightbyte return change rewrote the return-value load
in emitReturn, emitReturnStmt, and emitReturnOfRValue unconditionally,
loading from returnValue.getPointer() even when the direct offset is 0.
On targets whose return slot carries an address-space cast (OpenCL on
spir), that pointer differs from the raw __retval alloca, so
CodeGenOpenCL/as_type.cl and vector.cl loaded the cast pointer rather
than the alloca and failed FileCheck.

Gate the offset-aware load on getDirectOffset() != 0 and restore the
original *fnRetAlloca load for the offset-0 case.  The x86-64
high-eightbyte coerced path is unchanged.
---
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 16 ++++++---
 clang/lib/CIR/CodeGen/CIRGenStmt.cpp     | 46 +++++++++++++++---------
 2 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 5d788fe0cb69d..2359acef0233e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -352,17 +352,23 @@ cir::ReturnOp 
CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
     const CIRGenFunctionInfo &fnInfo =
         cgf.cgm.getTypes().arrangeGlobalDeclaration(cgf.curGD);
     const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
-    mlir::Type loadTy = fn.getFunctionType().getReturnType();
-    Address loadAddr = cgf.returnValue;
     if (retInfo.getDirectOffset() != 0) {
-      loadAddr = emitReturnSlotAtOffset(cgf, loadAddr, retInfo, loc);
+      Address loadAddr =
+          emitReturnSlotAtOffset(cgf, cgf.returnValue, retInfo, loc);
+      mlir::Type loadTy = fn.getFunctionType().getReturnType();
       if (retInfo.getCoerceToType()) {
         loadTy = retInfo.getCoerceToType();
         loadAddr = loadAddr.withElementType(cgf.getBuilder(), loadTy);
       }
+      auto value =
+          cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
+      return cir::ReturnOp::create(builder, loc,
+                                   llvm::ArrayRef(value.getResult()));
     }
-    auto value =
-        cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
+
+    // Load the value from `__retval` and return it via the `cir.return` op.
+    auto value = cir::LoadOp::create(
+        builder, loc, fn.getFunctionType().getReturnType(), *cgf.fnRetAlloca);
     return cir::ReturnOp::create(builder, loc,
                                  llvm::ArrayRef(value.getResult()));
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp 
b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 2a897002ac207..c1214d97487e7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -670,25 +670,31 @@ mlir::LogicalResult CIRGenFunction::emitReturnStmt(const 
ReturnStmt &s) {
     const CIRGenFunctionInfo &fnInfo =
         cgm.getTypes().arrangeGlobalDeclaration(curGD);
     const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
-    mlir::Type loadTy =
-        cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
-    Address loadAddr = returnValue;
     if (retInfo.getDirectOffset() != 0) {
+      mlir::Type loadTy =
+          cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
       mlir::Value offsetVal =
           builder.getUnsignedInt(loc, retInfo.getDirectOffset(), 64);
       Address byteAddr =
-          loadAddr.withElementType(builder, builder.getUInt8Ty());
-      loadAddr = byteAddr.withPointer(
+          returnValue.withElementType(builder, builder.getUInt8Ty());
+      Address loadAddr = byteAddr.withPointer(
           builder.createPtrStride(loc, byteAddr.getPointer(), offsetVal));
       if (retInfo.getCoerceToType()) {
         loadTy = retInfo.getCoerceToType();
         loadAddr = loadAddr.withElementType(builder, loadTy);
       }
-    }
-    auto value =
-        cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
+      auto value =
+          cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
+      cir::ReturnOp::create(builder, loc, {value});
+    } else {
+      // Load the value from `__retval` and return it via the `cir.return` op.
+      cir::AllocaOp retAlloca =
+          mlir::cast<cir::AllocaOp>(fnRetAlloca->getDefiningOp());
+      auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
+                                       *fnRetAlloca);
 
-    cir::ReturnOp::create(builder, loc, {value});
+      cir::ReturnOp::create(builder, loc, {value});
+    }
   } else {
     cir::ReturnOp::create(builder, loc);
   }
@@ -1288,25 +1294,33 @@ void CIRGenFunction::emitReturnOfRValue(mlir::Location 
loc, RValue rv,
   // during the CFG flattening phase, we can just emit the return statement
   // directly.
   // TODO(cir): Eliminate this redundant load and the store above when we can.
-  // Load the value from `__retval` and return it via the `cir.return` op.
   const CIRGenFunctionInfo &fnInfo =
       cgm.getTypes().arrangeGlobalDeclaration(curGD);
   const cir::ABIArgInfo &retInfo = fnInfo.getReturnInfo();
-  mlir::Type loadTy =
-      cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
-  Address loadAddr = returnValue;
   if (retInfo.getDirectOffset() != 0) {
+    mlir::Type loadTy =
+        cast<cir::FuncOp>(curFn).getFunctionType().getReturnType();
     mlir::Value offsetVal =
         builder.getUnsignedInt(loc, retInfo.getDirectOffset(), 64);
-    Address byteAddr = loadAddr.withElementType(builder, builder.getUInt8Ty());
-    loadAddr = byteAddr.withPointer(
+    Address byteAddr =
+        returnValue.withElementType(builder, builder.getUInt8Ty());
+    Address loadAddr = byteAddr.withPointer(
         builder.createPtrStride(loc, byteAddr.getPointer(), offsetVal));
     if (retInfo.getCoerceToType()) {
       loadTy = retInfo.getCoerceToType();
       loadAddr = loadAddr.withElementType(builder, loadTy);
     }
+    auto value =
+        cir::LoadOp::create(builder, loc, loadTy, loadAddr.getPointer());
+    cir::ReturnOp::create(builder, loc, {value});
+    return;
   }
-  auto value = cir::LoadOp::create(builder, loc, loadTy, 
loadAddr.getPointer());
+
+  // Load the value from `__retval` and return it via the `cir.return` op.
+  cir::AllocaOp retAlloca =
+      mlir::cast<cir::AllocaOp>(fnRetAlloca->getDefiningOp());
+  auto value = cir::LoadOp::create(builder, loc, retAlloca.getAllocaType(),
+                                   *fnRetAlloca);
 
   cir::ReturnOp::create(builder, loc, {value});
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to