[llvm-dev] Lowering ISD::TRUNCATE
Michael Stellmann via llvm-dev
llvm-dev at lists.llvm.org
Mon Aug 6 12:08:57 PDT 2018
I'm working on defining the instructions and implementing the lowering
code for a Z80 backend. For now, the backend supports only the native
CPU-supported datatypes, which are 8 and 16 bits wide (i.e. no 32 bit
long, float, ... yet).
So far, a lot of the simple stuff like immediate loads and return values
is very straightforward, but now I got stuck with ISD::TRUNCATE, as in:
typedef unsigned char uint8_t;
uint8_t Func(uint8_t val1) { return val1 + val1; }
built with -O0 results in:
target datalayout = "e-m:o-S8-p:16:8-p1:8:8-i16:8-i32:8-a:8-n8:16"
target triple = "z80"
; Function Attrs: noinline nounwind optnone
define dso_local zeroext i8 @Func(i8 zeroext %val1) #0 {
entry:
%val1.addr = alloca i8, align 1
store i8 %val1, i8* %val1.addr, align 1
%0 = load i8, i8* %val1.addr, align 1
%conv = zext i8 %0 to i16
%1 = load i8, i8* %val1.addr, align 1
%conv1 = zext i8 %1 to i16
%add = add nsw i16 %conv, %conv1
%conv2 = trunc i16 %add to i8
ret i8 %conv2
}
I looked into the X86 backend, which has a Z80-like register design,
i.e. being able to access the subregs AL (and AH) from AX directly,
without any specific truncation operation necessary. But, to be honest,
I do not really understand from the code where and how the i16 to i8
case is handled.
So returning an 8 bit result would simply require loading the lower 8
bits ("AL" on X86) from the resulting value 16 bit (%add) into the 8 bit
return register, as defined by the calling convention.
(Or to be Z80 specific: The 16 bit add operation will be "ADD HL,DE",
calling conv defined register "A" be the i8 return value, so the last
two IR lines should emit something like "LD A,L / RET".)
That said, what is the correct way to implement ISD::TRUNCATE this in
the backend, using the CPU's capability that truncating i16 to i8 is
simply accessing an i16' register's subreg?
Should this be handled in "LowerOperation" or in "PerformDAGCombine"?
Or could this be done with a target-independent combine?
Would returning true in "isTruncateFree" suffice?
Is any lowering code needed at all?
The X86 backend seems to do both, "setTargetDAGCombine(ISD::TRUNCATE)",
but then also registering a lot of MVTs via
"setOperationAction(...,Custom)", depending on things like soft-float.
I guess I'm
And second:
In my case, with only i16 and i8 data types, And are there other
truncation operations to be supported? Is there any scenario where i8 to
i1 is needed? My first guess was for conditional branching, but my tests
showed that it works with flags, comparing "not equal" or "not zero", so
I assume not.
Michael
More information about the llvm-dev
mailing list