[clang] [clang][CodeGen] Add range metadata for atomic load of boolean type. #131476 (PR #133546)
Jan Górski via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 11 05:33:02 PDT 2025
https://github.com/janagor updated https://github.com/llvm/llvm-project/pull/133546
>From 4581169d6fbe72357bb83b95fe36c8cc606efa1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Fri, 28 Mar 2025 23:36:18 +0100
Subject: [PATCH 1/9] [clang][CodeGen] Added llvm ir pre-commit test.
---
clang/test/CodeGen/atomic-ops-load.c | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 clang/test/CodeGen/atomic-ops-load.c
diff --git a/clang/test/CodeGen/atomic-ops-load.c b/clang/test/CodeGen/atomic-ops-load.c
new file mode 100644
index 0000000000000..adcaf9a2112fa
--- /dev/null
+++ b/clang/test/CodeGen/atomic-ops-load.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple riscv64 -O1 -emit-llvm %s -o - | FileCheck %s
+#include <stdbool.h>
+
+extern bool t1;
+bool test1(void) {
+// CHECK-LABEL: define{{.*}} i1 @test1
+// CHECK: load atomic i8, ptr @t1 monotonic, align 1
+// CHECK-NEXT: trunc i8 %{{.*}} to i1
+// CHECK-NEXT: ret i1 %{{.*}}
+ return __atomic_load_n(&t1, __ATOMIC_RELAXED);
+}
>From 852b691fac487b3cef7b0df8875c26573bc58daa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Sat, 29 Mar 2025 00:53:23 +0100
Subject: [PATCH 2/9] [clang][CodeGen] Added `!range` metadata to atomic load
for `bool`.
---
clang/lib/CodeGen/CGAtomic.cpp | 23 +++++++++++++++++++++++
clang/test/CodeGen/atomic-ops-load.c | 4 ++--
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 3adb2a7ad207f..70ae7180a9adc 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -590,6 +590,29 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
+
+ if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
+ CGF.Builder.CreateStore(Load, Dest);
+ return;
+ }
+
+ QualType Ty = E->getValueType();
+ if (!Ty->isBooleanType()) {
+ CGF.Builder.CreateStore(Load, Dest);
+ return;
+ }
+
+ llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+ llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
+ llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
+
+ if (llvm::MDNode *RangeInfo =
+ MDHelper.createRange(BooleanMin, BooleanEnd)) {
+ Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
+ Load->setMetadata(llvm::LLVMContext::MD_noundef,
+ llvm::MDNode::get(CGF.getLLVMContext(), {}));
+ }
+
CGF.Builder.CreateStore(Load, Dest);
return;
}
diff --git a/clang/test/CodeGen/atomic-ops-load.c b/clang/test/CodeGen/atomic-ops-load.c
index adcaf9a2112fa..778a7ebdc2618 100644
--- a/clang/test/CodeGen/atomic-ops-load.c
+++ b/clang/test/CodeGen/atomic-ops-load.c
@@ -4,8 +4,8 @@
extern bool t1;
bool test1(void) {
// CHECK-LABEL: define{{.*}} i1 @test1
-// CHECK: load atomic i8, ptr @t1 monotonic, align 1
-// CHECK-NEXT: trunc i8 %{{.*}} to i1
+// CHECK: load atomic i8, ptr @t1 monotonic, align 1, !range ![[$WS_RANGE:[0-9]*]], !noundef !{{[0-9]+}}
+// CHECK-NEXT: trunc nuw i8 %{{.*}} to i1
// CHECK-NEXT: ret i1 %{{.*}}
return __atomic_load_n(&t1, __ATOMIC_RELAXED);
}
>From e42772bbc0851696d73ded4abc3edf651f4e8b41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Sat, 29 Mar 2025 01:12:18 +0100
Subject: [PATCH 3/9] Updated codestyle.
---
clang/lib/CodeGen/CGAtomic.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 70ae7180a9adc..2c9613deef744 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -607,10 +607,10 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
if (llvm::MDNode *RangeInfo =
- MDHelper.createRange(BooleanMin, BooleanEnd)) {
+ MDHelper.createRange(BooleanMin, BooleanEnd)) {
Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
Load->setMetadata(llvm::LLVMContext::MD_noundef,
- llvm::MDNode::get(CGF.getLLVMContext(), {}));
+ llvm::MDNode::get(CGF.getLLVMContext(), {}));
}
CGF.Builder.CreateStore(Load, Dest);
>From c95f16cf2df51e8f7a1d4952918c977104271072 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Fri, 4 Apr 2025 11:20:30 +0200
Subject: [PATCH 4/9] Refactored early returns into normal if statement.
---
clang/lib/CodeGen/CGAtomic.cpp | 29 ++++++++++-------------------
1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 2c9613deef744..c40bf3cd77d86 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -591,26 +591,17 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
- if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
- CGF.Builder.CreateStore(Load, Dest);
- return;
- }
-
QualType Ty = E->getValueType();
- if (!Ty->isBooleanType()) {
- CGF.Builder.CreateStore(Load, Dest);
- return;
- }
-
- llvm::MDBuilder MDHelper(CGF.getLLVMContext());
- llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
- llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
-
- if (llvm::MDNode *RangeInfo =
- MDHelper.createRange(BooleanMin, BooleanEnd)) {
- Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
- Load->setMetadata(llvm::LLVMContext::MD_noundef,
- llvm::MDNode::get(CGF.getLLVMContext(), {}));
+ if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && Ty->isBooleanType()) {
+ llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+ llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
+ llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
+ if (llvm::MDNode *RangeInfo =
+ MDHelper.createRange(BooleanMin, BooleanEnd)) {
+ Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
+ Load->setMetadata(llvm::LLVMContext::MD_noundef,
+ llvm::MDNode::get(CGF.getLLVMContext(), {}));
+ }
}
CGF.Builder.CreateStore(Load, Dest);
>From ecc0f4060b9192128837539ddab9797922cc5955 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Thu, 10 Apr 2025 11:51:38 +0200
Subject: [PATCH 5/9] Reverted adding `range!` metadata from 852b691fac48.
Added `isSafeNUWTrunc` helper to `EmitFromMemory` to allow adding `nuw` to
`load` when safe.
---
clang/lib/CodeGen/CGAtomic.cpp | 14 -----
clang/lib/CodeGen/CGExpr.cpp | 58 ++++++++++++++++++-
clang/test/C/drs/dr335.c | 2 +-
clang/test/CodeGen/PowerPC/bool_test.c | 2 +-
clang/test/CodeGen/atomic-ops-load.c | 2 +-
.../attr-likelihood-if-branch-weights.cpp | 32 +++++-----
clang/test/CodeGenObjC/arc-ternary-op.m | 2 +-
7 files changed, 76 insertions(+), 36 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index c40bf3cd77d86..3adb2a7ad207f 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -590,20 +590,6 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
-
- QualType Ty = E->getValueType();
- if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && Ty->isBooleanType()) {
- llvm::MDBuilder MDHelper(CGF.getLLVMContext());
- llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
- llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
- if (llvm::MDNode *RangeInfo =
- MDHelper.createRange(BooleanMin, BooleanEnd)) {
- Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
- Load->setMetadata(llvm::LLVMContext::MD_noundef,
- llvm::MDNode::get(CGF.getLLVMContext(), {}));
- }
- }
-
CGF.Builder.CreateStore(Load, Dest);
return;
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 3d3a111f0514a..f6d0442261eb7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2093,6 +2093,57 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
return Value;
}
+static bool isSafeNUWTrunc(llvm::Value *V, llvm::Type *DestTy) {
+ if (!V || !DestTy || !DestTy->isIntegerTy())
+ return false;
+
+ unsigned SrcBits = V->getType()->getIntegerBitWidth();
+ unsigned DestBits = DestTy->getIntegerBitWidth();
+
+ if (DestBits >= SrcBits)
+ return false;
+ if (V->getType()->isIntegerTy(1))
+ return true;
+ if (llvm::ZExtInst *Zext = dyn_cast<llvm::ZExtInst>(V)) {
+ if (Zext->getSrcTy()->isIntegerTy(1) && DestBits == 1)
+ return true;
+ }
+ if (llvm::LoadInst *I = dyn_cast<llvm::LoadInst>(V)) {
+ if (llvm::MDNode *RangeMD = I->getMetadata(llvm::LLVMContext::MD_range)) {
+ if (RangeMD->getNumOperands() == 2) {
+ llvm::ConstantAsMetadata *LowMD =
+ cast<llvm::ConstantAsMetadata>(RangeMD->getOperand(0));
+ llvm::ConstantAsMetadata *HighMD =
+ cast<llvm::ConstantAsMetadata>(RangeMD->getOperand(1));
+
+ if (LowMD && HighMD) {
+ llvm::ConstantInt *LowConst =
+ dyn_cast<llvm::ConstantInt>(LowMD->getValue());
+ llvm::ConstantInt *HighConst =
+ dyn_cast<llvm::ConstantInt>(HighMD->getValue());
+
+ if (LowConst && HighConst) {
+ llvm::APInt HighVal = HighConst->getValue();
+ llvm::APInt MaxVal =
+ llvm::APInt(HighVal.getBitWidth(), 1ULL << DestBits);
+
+ if (HighVal.ule(MaxVal)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(V)) {
+ llvm::APInt Val = CI->getValue();
+ return Val.ule(llvm::APInt::getMaxValue(DestBits));
+ }
+
+ return false;
+}
+
/// Converts a scalar value from its load/store type (as returned
/// by convertTypeForLoadStore) to its primary IR type (as returned
/// by ConvertType).
@@ -2111,9 +2162,12 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
}
llvm::Type *ResTy = ConvertType(Ty);
+ bool IsSafe = isSafeNUWTrunc(Value, ResTy);
+
if (hasBooleanRepresentation(Ty) || Ty->isBitIntType() ||
- Ty->isExtVectorBoolType())
- return Builder.CreateTrunc(Value, ResTy, "loadedv");
+ Ty->isExtVectorBoolType()) {
+ return Builder.CreateTrunc(Value, ResTy, "loadedv", /*IsNUW*/ IsSafe);
+ }
return Value;
}
diff --git a/clang/test/C/drs/dr335.c b/clang/test/C/drs/dr335.c
index 3ce6ce5bd53ca..8bbd119b88c20 100644
--- a/clang/test/C/drs/dr335.c
+++ b/clang/test/C/drs/dr335.c
@@ -45,6 +45,6 @@ void dr335(void) {
// CHECK-NEXT: %[[CLEAR2:.+]] = and i8 %[[LOAD2]], -2
// CHECK-NEXT: %[[SET:.+]] = or i8 %[[CLEAR2]], %[[ZERO]]
// CHECK-NEXT: store i8 %[[SET]], ptr {{.+}}, align 1
- // CHECK-NEXT: {{.+}} = trunc i8 %[[ZERO]] to i1
+ // CHECK-NEXT: {{.+}} = trunc nuw i8 %[[ZERO]] to i1
}
diff --git a/clang/test/CodeGen/PowerPC/bool_test.c b/clang/test/CodeGen/PowerPC/bool_test.c
index d3e7db3c66dad..6b5b4fe5dc202 100644
--- a/clang/test/CodeGen/PowerPC/bool_test.c
+++ b/clang/test/CodeGen/PowerPC/bool_test.c
@@ -10,7 +10,7 @@ void f(_Bool *x, _Bool *y) {
// CHECK-LABEL: define{{.*}} void @f(
// CHECK: [[FROMMEM:%.*]] = load i8, ptr %
-// CHECK: [[BOOLVAL:%.*]] = trunc i8 [[FROMMEM]] to i1
+// CHECK: [[BOOLVAL:%.*]] = trunc nuw i8 [[FROMMEM]] to i1
// CHECK: [[TOMEM:%.*]] = zext i1 [[BOOLVAL]] to i8
// CHECK: store i8 [[TOMEM]]
// CHECK: ret void
diff --git a/clang/test/CodeGen/atomic-ops-load.c b/clang/test/CodeGen/atomic-ops-load.c
index 778a7ebdc2618..f737f23ad6aea 100644
--- a/clang/test/CodeGen/atomic-ops-load.c
+++ b/clang/test/CodeGen/atomic-ops-load.c
@@ -4,7 +4,7 @@
extern bool t1;
bool test1(void) {
// CHECK-LABEL: define{{.*}} i1 @test1
-// CHECK: load atomic i8, ptr @t1 monotonic, align 1, !range ![[$WS_RANGE:[0-9]*]], !noundef !{{[0-9]+}}
+// CHECK: load atomic i8, ptr @t1 monotonic, align 1
// CHECK-NEXT: trunc nuw i8 %{{.*}} to i1
// CHECK-NEXT: ret i1 %{{.*}}
return __atomic_load_n(&t1, __ATOMIC_RELAXED);
diff --git a/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp b/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
index a77593f5df738..e502d6582054e 100644
--- a/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
+++ b/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
@@ -10,7 +10,7 @@ extern bool B();
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2:![0-9]+]], !range [[RNG6:![0-9]+]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 true)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -37,7 +37,7 @@ bool f() {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -65,7 +65,7 @@ bool g() {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -90,7 +90,7 @@ bool h() {
// CHECK-LABEL: @_Z8NullStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -113,7 +113,7 @@ void NullStmt() {
// CHECK-LABEL: @_Z6IfStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
// CHECK: if.then:
@@ -125,7 +125,7 @@ void NullStmt() {
// CHECK-NEXT: br label [[IF_END2]]
// CHECK: if.end2:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL3:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL3:%.*]] = trunc nuw i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL3]], label [[IF_THEN4:%.*]], label [[IF_END8:%.*]]
// CHECK: if.then4:
// CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv()
@@ -152,7 +152,7 @@ void IfStmt() {
// CHECK-LABEL: @_Z9WhileStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -166,7 +166,7 @@ void IfStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[WHILE_COND3:%.*]]
@@ -194,7 +194,7 @@ void WhileStmt() {
// CHECK-LABEL: @_Z6DoStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -208,7 +208,7 @@ void WhileStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[DO_BODY3:%.*]]
@@ -237,7 +237,7 @@ void DoStmt() {
// CHECK-LABEL: @_Z7ForStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -251,7 +251,7 @@ void DoStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[FOR_COND3:%.*]]
@@ -278,7 +278,7 @@ void ForStmt() {
// CHECK-LABEL: @_Z8GotoStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -304,7 +304,7 @@ end:;
// CHECK-LABEL: @_Z10ReturnStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -327,7 +327,7 @@ void ReturnStmt() {
// CHECK-LABEL: @_Z10SwitchStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -341,7 +341,7 @@ void ReturnStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP2:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP2]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP2]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_ELSE4:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15]]
diff --git a/clang/test/CodeGenObjC/arc-ternary-op.m b/clang/test/CodeGenObjC/arc-ternary-op.m
index 4a3c00c9807a9..51fc33ec29966 100644
--- a/clang/test/CodeGenObjC/arc-ternary-op.m
+++ b/clang/test/CodeGenObjC/arc-ternary-op.m
@@ -14,7 +14,7 @@ void test0(_Bool cond) {
// CHECK-NEXT: store
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
// CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[COND]]
- // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
+ // CHECK-NEXT: [[T1:%.*]] = trunc nuw i8 [[T0]] to i1
// CHECK-NEXT: store i1 false, ptr [[RELCOND]]
// CHECK-NEXT: br i1 [[T1]],
// CHECK: br label
>From 7e60e8fed3ff186d1aa85f1292d491eafcc5afbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Thu, 10 Apr 2025 15:50:05 +0200
Subject: [PATCH 6/9] fixup! Merge branch 'main' into add_range_metadata
---
clang/lib/CodeGen/CGExpr.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index aadf6a34f8c55..6ae1db749633d 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2147,7 +2147,7 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
llvm::Type *ResTy = ConvertType(Ty);
bool IsSafe = isSafeNUWTrunc(Value, ResTy);
- if (hasBooleanRepresentation(Ty) || Ty->isBitIntType() ||
+ if (Ty->hasBooleanRepresentation() || Ty->isBitIntType() ||
Ty->isExtVectorBoolType()) {
return Builder.CreateTrunc(Value, ResTy, "loadedv", /*IsNUW*/ IsSafe);
}
>From df9c2bc5e7263ab374757be90be86ef9d1375f4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Fri, 11 Apr 2025 00:46:26 +0200
Subject: [PATCH 7/9] Reverted to state before ecc0f4060b91.
---
clang/lib/CodeGen/CGAtomic.cpp | 14 +++++
clang/lib/CodeGen/CGExpr.cpp | 57 +------------------
clang/test/C/drs/dr335.c | 2 +-
clang/test/CodeGen/PowerPC/bool_test.c | 2 +-
clang/test/CodeGen/atomic-ops-load.c | 2 +-
.../attr-likelihood-if-branch-weights.cpp | 32 +++++------
clang/test/CodeGenObjC/arc-ternary-op.m | 2 +-
7 files changed, 36 insertions(+), 75 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 672e82f8dcc3e..0ead62ab0fd7b 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -590,7 +590,21 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
+
+ QualType Ty = E->getValueType();
+ if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && Ty->isBooleanType()) {
+ llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+ llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
+ llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
+ if (llvm::MDNode *RangeInfo =
+ MDHelper.createRange(BooleanMin, BooleanEnd)) {
+ Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
+ Load->setMetadata(llvm::LLVMContext::MD_noundef,
+ llvm::MDNode::get(CGF.getLLVMContext(), {}));
+ }
+ }
CGF.Builder.CreateStore(Load, Dest);
+
return;
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 6ae1db749633d..62eaff4e6a978 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2077,57 +2077,6 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
return Value;
}
-static bool isSafeNUWTrunc(llvm::Value *V, llvm::Type *DestTy) {
- if (!V || !DestTy || !DestTy->isIntegerTy())
- return false;
-
- unsigned SrcBits = V->getType()->getIntegerBitWidth();
- unsigned DestBits = DestTy->getIntegerBitWidth();
-
- if (DestBits >= SrcBits)
- return false;
- if (V->getType()->isIntegerTy(1))
- return true;
- if (llvm::ZExtInst *Zext = dyn_cast<llvm::ZExtInst>(V)) {
- if (Zext->getSrcTy()->isIntegerTy(1) && DestBits == 1)
- return true;
- }
- if (llvm::LoadInst *I = dyn_cast<llvm::LoadInst>(V)) {
- if (llvm::MDNode *RangeMD = I->getMetadata(llvm::LLVMContext::MD_range)) {
- if (RangeMD->getNumOperands() == 2) {
- llvm::ConstantAsMetadata *LowMD =
- cast<llvm::ConstantAsMetadata>(RangeMD->getOperand(0));
- llvm::ConstantAsMetadata *HighMD =
- cast<llvm::ConstantAsMetadata>(RangeMD->getOperand(1));
-
- if (LowMD && HighMD) {
- llvm::ConstantInt *LowConst =
- dyn_cast<llvm::ConstantInt>(LowMD->getValue());
- llvm::ConstantInt *HighConst =
- dyn_cast<llvm::ConstantInt>(HighMD->getValue());
-
- if (LowConst && HighConst) {
- llvm::APInt HighVal = HighConst->getValue();
- llvm::APInt MaxVal =
- llvm::APInt(HighVal.getBitWidth(), 1ULL << DestBits);
-
- if (HighVal.ule(MaxVal)) {
- return true;
- }
- }
- }
- }
- }
- }
-
- if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(V)) {
- llvm::APInt Val = CI->getValue();
- return Val.ule(llvm::APInt::getMaxValue(DestBits));
- }
-
- return false;
-}
-
/// Converts a scalar value from its load/store type (as returned
/// by convertTypeForLoadStore) to its primary IR type (as returned
/// by ConvertType).
@@ -2146,11 +2095,9 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
}
llvm::Type *ResTy = ConvertType(Ty);
- bool IsSafe = isSafeNUWTrunc(Value, ResTy);
if (Ty->hasBooleanRepresentation() || Ty->isBitIntType() ||
- Ty->isExtVectorBoolType()) {
- return Builder.CreateTrunc(Value, ResTy, "loadedv", /*IsNUW*/ IsSafe);
- }
+ Ty->isExtVectorBoolType())
+ return Builder.CreateTrunc(Value, ResTy, "loadedv");
return Value;
}
diff --git a/clang/test/C/drs/dr335.c b/clang/test/C/drs/dr335.c
index 8bbd119b88c20..3ce6ce5bd53ca 100644
--- a/clang/test/C/drs/dr335.c
+++ b/clang/test/C/drs/dr335.c
@@ -45,6 +45,6 @@ void dr335(void) {
// CHECK-NEXT: %[[CLEAR2:.+]] = and i8 %[[LOAD2]], -2
// CHECK-NEXT: %[[SET:.+]] = or i8 %[[CLEAR2]], %[[ZERO]]
// CHECK-NEXT: store i8 %[[SET]], ptr {{.+}}, align 1
- // CHECK-NEXT: {{.+}} = trunc nuw i8 %[[ZERO]] to i1
+ // CHECK-NEXT: {{.+}} = trunc i8 %[[ZERO]] to i1
}
diff --git a/clang/test/CodeGen/PowerPC/bool_test.c b/clang/test/CodeGen/PowerPC/bool_test.c
index 6b5b4fe5dc202..d3e7db3c66dad 100644
--- a/clang/test/CodeGen/PowerPC/bool_test.c
+++ b/clang/test/CodeGen/PowerPC/bool_test.c
@@ -10,7 +10,7 @@ void f(_Bool *x, _Bool *y) {
// CHECK-LABEL: define{{.*}} void @f(
// CHECK: [[FROMMEM:%.*]] = load i8, ptr %
-// CHECK: [[BOOLVAL:%.*]] = trunc nuw i8 [[FROMMEM]] to i1
+// CHECK: [[BOOLVAL:%.*]] = trunc i8 [[FROMMEM]] to i1
// CHECK: [[TOMEM:%.*]] = zext i1 [[BOOLVAL]] to i8
// CHECK: store i8 [[TOMEM]]
// CHECK: ret void
diff --git a/clang/test/CodeGen/atomic-ops-load.c b/clang/test/CodeGen/atomic-ops-load.c
index f737f23ad6aea..778a7ebdc2618 100644
--- a/clang/test/CodeGen/atomic-ops-load.c
+++ b/clang/test/CodeGen/atomic-ops-load.c
@@ -4,7 +4,7 @@
extern bool t1;
bool test1(void) {
// CHECK-LABEL: define{{.*}} i1 @test1
-// CHECK: load atomic i8, ptr @t1 monotonic, align 1
+// CHECK: load atomic i8, ptr @t1 monotonic, align 1, !range ![[$WS_RANGE:[0-9]*]], !noundef !{{[0-9]+}}
// CHECK-NEXT: trunc nuw i8 %{{.*}} to i1
// CHECK-NEXT: ret i1 %{{.*}}
return __atomic_load_n(&t1, __ATOMIC_RELAXED);
diff --git a/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp b/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
index e502d6582054e..a77593f5df738 100644
--- a/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
+++ b/clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp
@@ -10,7 +10,7 @@ extern bool B();
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2:![0-9]+]], !range [[RNG6:![0-9]+]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 true)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -37,7 +37,7 @@ bool f() {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -65,7 +65,7 @@ bool g() {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -90,7 +90,7 @@ bool h() {
// CHECK-LABEL: @_Z8NullStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -113,7 +113,7 @@ void NullStmt() {
// CHECK-LABEL: @_Z6IfStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
// CHECK: if.then:
@@ -125,7 +125,7 @@ void NullStmt() {
// CHECK-NEXT: br label [[IF_END2]]
// CHECK: if.end2:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL3:%.*]] = trunc nuw i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL3:%.*]] = trunc i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL3]], label [[IF_THEN4:%.*]], label [[IF_END8:%.*]]
// CHECK: if.then4:
// CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv()
@@ -152,7 +152,7 @@ void IfStmt() {
// CHECK-LABEL: @_Z9WhileStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -166,7 +166,7 @@ void IfStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[WHILE_COND3:%.*]]
@@ -194,7 +194,7 @@ void WhileStmt() {
// CHECK-LABEL: @_Z6DoStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -208,7 +208,7 @@ void WhileStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[DO_BODY3:%.*]]
@@ -237,7 +237,7 @@ void DoStmt() {
// CHECK-LABEL: @_Z7ForStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK: if.then:
@@ -251,7 +251,7 @@ void DoStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP1]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: br label [[FOR_COND3:%.*]]
@@ -278,7 +278,7 @@ void ForStmt() {
// CHECK-LABEL: @_Z8GotoStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -304,7 +304,7 @@ end:;
// CHECK-LABEL: @_Z10ReturnStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -327,7 +327,7 @@ void ReturnStmt() {
// CHECK-LABEL: @_Z10SwitchStmtv(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL:%.*]] = trunc nuw i8 [[TMP0]] to i1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
// CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK: if.then:
@@ -341,7 +341,7 @@ void ReturnStmt() {
// CHECK-NEXT: br label [[IF_END]]
// CHECK: if.end:
// CHECK-NEXT: [[TMP2:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
-// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc nuw i8 [[TMP2]] to i1
+// CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP2]] to i1
// CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_ELSE4:%.*]]
// CHECK: if.then2:
// CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15]]
diff --git a/clang/test/CodeGenObjC/arc-ternary-op.m b/clang/test/CodeGenObjC/arc-ternary-op.m
index 51fc33ec29966..4a3c00c9807a9 100644
--- a/clang/test/CodeGenObjC/arc-ternary-op.m
+++ b/clang/test/CodeGenObjC/arc-ternary-op.m
@@ -14,7 +14,7 @@ void test0(_Bool cond) {
// CHECK-NEXT: store
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[X]])
// CHECK-NEXT: [[T0:%.*]] = load i8, ptr [[COND]]
- // CHECK-NEXT: [[T1:%.*]] = trunc nuw i8 [[T0]] to i1
+ // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
// CHECK-NEXT: store i1 false, ptr [[RELCOND]]
// CHECK-NEXT: br i1 [[T1]],
// CHECK: br label
>From f25e68736d12231b3483ec3eea8d4ce8da6f70f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Fri, 11 Apr 2025 00:55:18 +0200
Subject: [PATCH 8/9] Exposed `getRangeForLoadFromType` as a public method to
support adding `range!` metadata for atomic loads.
---
clang/lib/CodeGen/CGAtomic.cpp | 12 ++++--------
clang/lib/CodeGen/CodeGenFunction.h | 3 ++-
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 0ead62ab0fd7b..e8346e4fb0e9c 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -590,21 +590,17 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
-
QualType Ty = E->getValueType();
- if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 && Ty->isBooleanType()) {
- llvm::MDBuilder MDHelper(CGF.getLLVMContext());
- llvm::APInt BooleanMin = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0);
- llvm::APInt BooleanEnd = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2);
- if (llvm::MDNode *RangeInfo =
- MDHelper.createRange(BooleanMin, BooleanEnd)) {
+ if (CGF.EmitScalarRangeCheck(Load, Ty, E->getExprLoc())) {
+ } else if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0) {
+ CGF.getRangeForLoadFromType(Ty);
+ if (llvm::MDNode *RangeInfo = CGF.getRangeForLoadFromType(Ty)) {
Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
Load->setMetadata(llvm::LLVMContext::MD_noundef,
llvm::MDNode::get(CGF.getLLVMContext(), {}));
}
}
CGF.Builder.CreateStore(Load, Dest);
-
return;
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a398ba55dcdc7..4667a629832ca 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5306,6 +5306,8 @@ class CodeGenFunction : public CodeGenTypeCache {
unsigned NumElementsDst,
const llvm::Twine &Name = "");
+ llvm::MDNode *getRangeForLoadFromType(QualType Ty);
+
private:
// Emits a convergence_loop instruction for the given |BB|, with |ParentToken|
// as it's parent convergence instr.
@@ -5321,7 +5323,6 @@ class CodeGenFunction : public CodeGenTypeCache {
getOrEmitConvergenceEntryToken(llvm::Function *F);
private:
- llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
void deferPlaceholderReplacement(llvm::Instruction *Old, llvm::Value *New);
>From a348252f3ab23548d76fe37a174d133b3583ff8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20G=C3=B3rski?= <jan.a.gorski at wp.pl>
Date: Fri, 11 Apr 2025 14:11:13 +0200
Subject: [PATCH 9/9] Created helper function for calling
`EmitScalarRangeCheck()` and adding range metadata. Made
`getRangeForLoadFromType` private function as it was before f25e68736d12.
---
clang/lib/CodeGen/CGAtomic.cpp | 11 +----------
clang/lib/CodeGen/CGExpr.cpp | 24 +++++++++++++++---------
clang/lib/CodeGen/CodeGenFunction.h | 4 +++-
3 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index e8346e4fb0e9c..0af3cd07b13a0 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -590,16 +590,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
Load->setAtomic(Order, Scope);
Load->setVolatile(E->isVolatile());
- QualType Ty = E->getValueType();
- if (CGF.EmitScalarRangeCheck(Load, Ty, E->getExprLoc())) {
- } else if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0) {
- CGF.getRangeForLoadFromType(Ty);
- if (llvm::MDNode *RangeInfo = CGF.getRangeForLoadFromType(Ty)) {
- Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
- Load->setMetadata(llvm::LLVMContext::MD_noundef,
- llvm::MDNode::get(CGF.getLLVMContext(), {}));
- }
- }
+ CGF.maybeAttachRangeForLoad(Load, E->getValueType(), E->getExprLoc());
CGF.Builder.CreateStore(Load, Dest);
return;
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 62eaff4e6a978..52960a976152a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1919,6 +1919,20 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) {
return MDHelper.createRange(Min, End);
}
+void CodeGenFunction::maybeAttachRangeForLoad(llvm::LoadInst *Load, QualType Ty,
+ SourceLocation Loc) {
+ if (EmitScalarRangeCheck(Load, Ty, Loc)) {
+ // In order to prevent the optimizer from throwing away the check, don't
+ // attach range metadata to the load.
+ } else if (CGM.getCodeGenOpts().OptimizationLevel > 0) {
+ if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty)) {
+ Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
+ Load->setMetadata(llvm::LLVMContext::MD_noundef,
+ llvm::MDNode::get(CGM.getLLVMContext(), {}));
+ }
+ }
+}
+
bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
SourceLocation Loc) {
bool HasBoolCheck = SanOpts.has(SanitizerKind::Bool);
@@ -2037,15 +2051,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
CGM.DecorateInstructionWithTBAA(Load, TBAAInfo);
- if (EmitScalarRangeCheck(Load, Ty, Loc)) {
- // In order to prevent the optimizer from throwing away the check, don't
- // attach range metadata to the load.
- } else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
- if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty)) {
- Load->setMetadata(llvm::LLVMContext::MD_range, RangeInfo);
- Load->setMetadata(llvm::LLVMContext::MD_noundef,
- llvm::MDNode::get(getLLVMContext(), {}));
- }
+ maybeAttachRangeForLoad(Load, Ty, Loc);
return EmitFromMemory(Load, Ty);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 4667a629832ca..1da54888a3e78 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5306,7 +5306,8 @@ class CodeGenFunction : public CodeGenTypeCache {
unsigned NumElementsDst,
const llvm::Twine &Name = "");
- llvm::MDNode *getRangeForLoadFromType(QualType Ty);
+ void maybeAttachRangeForLoad(llvm::LoadInst *Load, QualType Ty,
+ SourceLocation Loc);
private:
// Emits a convergence_loop instruction for the given |BB|, with |ParentToken|
@@ -5323,6 +5324,7 @@ class CodeGenFunction : public CodeGenTypeCache {
getOrEmitConvergenceEntryToken(llvm::Function *F);
private:
+ llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
void deferPlaceholderReplacement(llvm::Instruction *Old, llvm::Value *New);
More information about the cfe-commits
mailing list