| Issue |
53371
|
| Summary |
[LLVM] Inconsistent behavior when setting instruction alignment to 0
|
| Labels |
|
| Assignees |
|
| Reporter |
dosisod
|
I have noticed some inconsistencies between the C/C++ API's, and the documentation, in regards to what should happen when setting alignment on certain instructions to zero. In [the documentation](https://llvm.org/docs/LangRef.html#store-instruction) for the store instruction, it states:
> A value of 0 or an omitted align argument means that the operation has the ABI alignment for the target.
Which implies that having an explicit `0` is valid (at least in IR), though when you try to do this in the C/C++ API's: it either crashes, or gives weird results. I created some MVP's to explain:
Setting alignment to 1 (works):
```
$ ./main
default alignment: 4
got: " store i64 1337, i64* %0, align 4"
new alignment: 1
got: " store i64 1337, i64* %0, align 1"
$ ./main-cpp
default alignment: 4
got: " store i64 1337, i64* %0, align 4"
new alignment: 1
got: " store i64 1337, i64* %0, align 1"
```
Setting alignment to 0 (doesn't work):
```
$ ./main
default alignment: 4
got: " store i64 1337, i64* %0, align 4"
new alignment: 2147483648
got: " store atomic i64 1337, i64* %0 seq_cst, align 2147483648"
$ ./main-cpp
default alignment: 4
got: " store i64 1337, i64* %0, align 4"
main-cpp: /usr/include/llvm/Support/Alignment.h:77: llvm::Align::Align(uint64_t): Assertion `Value > 0 && "Value must not be 0"' failed.
Aborted (core dumped)
```
`main` uses the C API, and `main-cpp` uses the C++ API. Source is below.
This behavior seems to stem from https://reviews.llvm.org/D77454. This behavior was not present in LLVM 10, but is in version 11 onward.
```
$ uname -a
Linux archer 5.16.2-arch1-1 #1 SMP PREEMPT Thu, 20 Jan 2022 16:18:29 +0000 x86_64 GNU/Linux
$ pacman -Qs llvm
local/clang 13.0.0-4
C language family frontend for LLVM
local/lld 13.0.0-1
Linker from the LLVM project
local/llvm 13.0.0-6
Collection of modular and reusable compiler and toolchain technologies
local/llvm-libs 13.0.0-6
LLVM runtime libraries
```
<details>
<summary>C API example</summary>
```c
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <llvm-c/Core.h>
int main(void) {
LLVMContextRef ctx = LLVMContextCreate();
LLVMModuleRef module = LLVMModuleCreateWithNameInContext(
"module",
ctx
);
LLVMTypeRef main_func_type = LLVMFunctionType(
LLVMInt64TypeInContext(ctx),
NULL,
0,
false
);
LLVMValueRef main_func = LLVMAddFunction(
module,
"main",
main_func_type
);
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(
ctx,
main_func,
"entry"
);
LLVMBuilderRef builder = LLVMCreateBuilderInContext(ctx);
LLVMPositionBuilderAtEnd(builder, entry);
LLVMValueRef num = LLVMConstInt(
LLVMInt64TypeInContext(ctx),
(unsigned long long)(1337),
1
);
LLVMValueRef alloca = LLVMBuildAlloca(
builder,
LLVMInt64TypeInContext(ctx),
""
);
LLVMValueRef store = LLVMBuildStore(
builder,
num,
alloca
);
printf("default alignment: %u\n", LLVMGetAlignment(store));
char *str = LLVMPrintValueToString(store);
printf("got: \"%s\"\n", str);
LLVMSetAlignment(store, 0);
printf("new alignment: %u\n", LLVMGetAlignment(store));
str = LLVMPrintValueToString(store);
printf("got: \"%s\"\n", str);
}
```
</details>
<details>
<summary>C++ API example</summary>
```c++
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include <iostream>
#include <memory>
#include <string>
using namespace llvm;
int main() {
auto ctx = std::make_unique<LLVMContext>();
auto mod = std::make_unique<Module>("main", *ctx);
auto builder = std::make_unique<IRBuilder<>>(*ctx);
auto *main_func_type = FunctionType::get(
Type::getInt64Ty(*ctx),
{},
false
);
auto *main_func = Function::Create(
main_func_type,
Function::ExternalLinkage,
"main",
mod.get()
);
BasicBlock *bb = BasicBlock::Create(*ctx, "entry", main_func);
builder->SetInsertPoint(bb);
auto *num = ConstantInt::get(*ctx, APInt(64, 1337));
auto alloca = new AllocaInst(
Type::getInt64Ty(*ctx),
0,
"",
bb
);
auto store = new StoreInst(
num,
alloca,
bb
);
std::string str;
llvm::raw_string_ostream rso(str);
store->print(rso, true);
printf("default alignment: %u\n", store->getAlignment());
std::cout << "got: \"" << str << "\"\n";
store->setAlignment(Align(0));
str = "";
store->print(rso, true);
printf("new alignment: %u\n", store->getAlignment());
std::cout << "got: \"" << str << "\"\n";
}
```
</details>
<details>
<summary>Makefile</summary>
```makefile
#!/bin/sh
CFLAGS += -std=c18 -g3 -O0
CXXFLAGS += -std=c++17 -g3 -O0
CXX = clang++
LLVM_CONFIG = $(shell command -v llvm-config)
LLVM_CFLAGS = $(shell $(LLVM_CONFIG) --cflags)
LLVM_CXXFLAGS = $(shell $(LLVM_CONFIG) --cxxflags)
LLVM_LDFLAGS = $(shell $(LLVM_CONFIG) --libs)
all: main main-cpp
main: main.c
$(CC) main.c -o main $(CFLAGS) $(LLVM_CFLAGS) $(LLVM_LDFLAGS)
main-cpp: main.cpp
$(CXX) main.cpp -o main-cpp $(CXXFLAGS) $(LLVM_CXXFLAGS) $(LLVM_LDFLAGS)
clean:
rm main main-cpp
```
</details>
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs