llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>

Without the freeze, an undef argument reaches a noundef parameter and the 
optimizer miscompiles the call

---
Full diff: https://github.com/llvm/llvm-project/pull/234124.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+25) 
- (added) clang/test/CIR/CodeGen/attr-maybeundef.cpp (+51) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 2d9113c278993..357b269f51492 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -1241,6 +1241,27 @@ 
CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
                                 fnpt->getExtInfo(), RequiredArgs(0));
 }
 
+/// Check if the argument of a function has maybe_undef attribute.
+static bool isArgumentMaybeUndef(const Decl *targetDecl,
+                                 unsigned numRequiredArgs, unsigned argNo) {
+  const auto *fd = dyn_cast_or_null<FunctionDecl>(targetDecl);
+  if (!fd)
+    return false;
+
+  // Assume variadic arguments do not have maybe_undef attribute.
+  if (argNo >= numRequiredArgs)
+    return false;
+
+  // Check if argument has maybe_undef attribute.
+  if (argNo < fd->getNumParams()) {
+    const ParmVarDecl *param = fd->getParamDecl(argNo);
+    if (param && param->hasAttr<MaybeUndefAttr>())
+      return true;
+  }
+
+  return false;
+}
+
 RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo &funcInfo,
                                 const CIRGenCallee &callee,
                                 ReturnValueSlot returnValue,
@@ -1359,6 +1380,10 @@ RValue CIRGenFunction::emitCall(const CIRGenFunctionInfo 
&funcInfo,
       assert(!cir::MissingFeatures::lowerAggregateLoadStore());
       cirCallArgs[argNo] = builder.createLoad(argLoc, src);
     }
+
+    if (isArgumentMaybeUndef(targetDecl, funcInfo.getNumRequiredArgs(), argNo))
+      cirCallArgs[argNo] =
+          cir::FreezeOp::create(builder, loc, cirCallArgs[argNo]);
   }
 
   const CIRGenCallee &concreteCallee = callee.prepareConcreteCallee(*this);
diff --git a/clang/test/CIR/CodeGen/attr-maybeundef.cpp 
b/clang/test/CIR/CodeGen/attr-maybeundef.cpp
new file mode 100644
index 0000000000000..af2f0348617ab
--- /dev/null
+++ b/clang/test/CIR/CodeGen/attr-maybeundef.cpp
@@ -0,0 +1,51 @@
+// 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-prefixes=LLVM,LLVMCIR --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefixes=LLVM,OGCG --input-file=%t.ll %s
+
+#define __maybe_undef __attribute__((maybe_undef))
+
+struct S { int a, b; };
+void scalar(int a, int __maybe_undef b, int c);
+void variadic(int __maybe_undef x, ...);
+void record(S __maybe_undef s);
+
+void test() {
+  int x, y, z;
+  S s;
+  scalar(x, y, z);
+  variadic(x, y);
+  record(s);
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z4testv()
+// CIR:         %[[X:.*]] = cir.load{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR:         %[[Y:.*]] = cir.load{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR:         %[[Z:.*]] = cir.load{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR:         %[[FY:.*]] = cir.freeze %[[Y]] : !s32i
+// CIR-NEXT:    cir.call @_Z6scalariii(%[[X]], %[[FY]], %[[Z]])
+// CIR:         %[[X2:.*]] = cir.load{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR:         %[[Y2:.*]] = cir.load{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR:         %[[FX2:.*]] = cir.freeze %[[X2]] : !s32i
+// CIR-NEXT:    cir.call @_Z8variadiciz(%[[FX2]], %[[Y2]])
+// CIR:         %[[SV:.*]] = cir.load{{.*}} : !cir.ptr<!rec_S>, !rec_S
+// CIR:         cir.freeze %[[SV]] : !rec_S
+// CIR:         cir.call @_Z6record1S(
+
+// LLVM-LABEL: define{{.*}} void @_Z4testv()
+// LLVM:         %[[X:.*]] = load i32
+// LLVM:         %[[Y:.*]] = load i32
+// LLVM:         %[[Z:.*]] = load i32
+// LLVM:         %[[FY:.*]] = freeze i32 %[[Y]]
+// LLVM-NEXT:    call void @_Z6scalariii(i32 noundef %[[X]], i32 noundef 
%[[FY]], i32 noundef %[[Z]])
+// LLVM:         %[[X2:.*]] = load i32
+// LLVM:         %[[Y2:.*]] = load i32
+// LLVM:         %[[FX2:.*]] = freeze i32 %[[X2]]
+// LLVM-NEXT:    call void (i32, ...) @_Z8variadiciz(i32 noundef %[[FX2]], i32 
noundef %[[Y2]])
+// LLVMCIR:      %[[SV:.*]] = load %struct.S
+// LLVMCIR:      freeze %struct.S %[[SV]]
+// OGCG:         %[[SV:.*]] = load i64
+// OGCG:         freeze i64 %[[SV]]
+// LLVM:         call void @_Z6record1S(i64

``````````

</details>


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

Reply via email to