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.gor...@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.gor...@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.gor...@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.gor...@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.gor...@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.gor...@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.gor...@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.gor...@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.gor...@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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits