Hello.
I come back to this older thread.
I'd also like to thank Peter Lawrence for the insightful answer (see below his email, if interested). Actually I would like to add that the C11 standard, Section 6.3.1.1, talks about integer promotions, which explains why the C language requires short arithmetic to be promoted to the size of int. See also https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules .
I would like to give an answer to Craig Topper: indeed I have a simple very interesting case where these promotions happen - the Floyd-Warshall algorithm, with the below program (also try the example at https://www.geeksforgeeks.org/integer-promotions-in-c/) . But in all cases do give clang -O0 to emit unoptimized LLVM IR.
#define SIZE 128
short path[SIZE][SIZE];
void FloydWarshall() {
int i, j, k;
for (k = 0; k < SIZE; k++) {
for (i = 0; i < SIZE; ++i) {
short pik = path[i][k];
for (j = 0; j < SIZE; j++) {
path[i][j] = path[i][j] < pik + path[k][j] ?
path[i][j] : pik + path[k][j];
}
}
}
}
The innermost's loop body is translated to the following UNoptimized LLVM IR code - see lines with comment "IMPORTANT":
for.body8: ; preds = %for.cond6
%6 = load i32, i32* %j, align 4
%idxprom9 = sext i32 %6 to i64
%7 = load i32, i32* %i, align 4
%idxprom10 = sext i32 %7 to i64
%arrayidx11 = getelementptr inbounds [256 x [256 x i16]], [256 x [256 x i16]]* @path, i64 0, i64 %idxprom10
%arrayidx12 = getelementptr inbounds [256 x i16], [256 x i16]* %arrayidx11, i64 0, i64 %idxprom9
%8 = load i16, i16* %arrayidx12
%conv = sext i16 %8 to i32 ; IMPORTANT
%9 = load i16, i16* %pik
%conv13 = sext i16 %9 to i32 ; IMPORTANT
%10 = load i32, i32* %j, align 4
%idxprom14 = sext i32 %10 to i64
%11 = load i32, i32* %k, align 4
%idxprom15 = sext i32 %11 to i64
%arrayidx16 = getelementptr inbounds [256 x [256 x i16]], [256 x [256 x i16]]* @path, i64 0, i64 %idxprom15
%arrayidx17 = getelementptr inbounds [256 x i16], [256 x i16]* %arrayidx16, i64 0, i64 %idxprom14
%12 = load i16, i16* %arrayidx17, align 2, !dbg !61
%conv18 = sext i16 %12 to i32
%add = add nsw i32 %conv13, %conv18
%add = add nsw i16 %9, %12 ; IMPORTANT
%cmp19 = icmp slt i32 %conv, %add
%cmp19 = icmp slt i16 %8, %add ; IMPORTANT
br i1 %cmp19, label %cond.true, label %cond.false
Best regards,
Alex