[clang][CodeGen] Add range metadata for atomic load of boolean type. #131476 (#133546)

Fixes #131476.

For `x86_64` it folds
```
movzbl	t1(%rip), %eax
andb	$1, %al
```
into
```
movzbl	t1(%rip), %eax
```
when run: `clang -S atomic-ops-load.c -o atomic-ops-load.s -O1
--target=x86_64`.

But for riscv replaces:
```
lb	a0, %lo(t1)(a0)
andi	a0, a0, 1
```
with
```
lb	a0, %lo(t1)(a0)
zext.b	a0, a0
``` 
when run: `clang -S atomic-ops-load.c -o atomic-ops-load.s -O1
--target=riscv64`.
This commit is contained in:
Jan Górski
2025-04-14 23:26:10 +02:00
committed by GitHub
parent 54b33eba16
commit ff687af04f
4 changed files with 30 additions and 9 deletions

View File

@@ -590,6 +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());
CGF.maybeAttachRangeForLoad(Load, E->getValueType(), E->getExprLoc());
CGF.Builder.CreateStore(Load, Dest);
return;
}

View File

@@ -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);
}

View File

@@ -5309,6 +5309,9 @@ public:
unsigned NumElementsDst,
const llvm::Twine &Name = "");
void maybeAttachRangeForLoad(llvm::LoadInst *Load, QualType Ty,
SourceLocation Loc);
private:
// Emits a convergence_loop instruction for the given |BB|, with |ParentToken|
// as it's parent convergence instr.

View File

@@ -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, !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);
}