diff options
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 12 | ||||
| -rw-r--r-- | llvm/test/CodeGen/AArch64/i1-contents.ll | 55 |
2 files changed, 67 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 5c504d1e6c2..80d6669cbf3 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2263,6 +2263,11 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); break; case CCValAssign::AExt: + if (Outs[realArgIdx].ArgVT == MVT::i1) { + // AAPCS requires i1 to be zero-extended to 8-bits by the caller. + Arg = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Arg); + Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i8, Arg); + } Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg); break; case CCValAssign::BCvt: @@ -2503,6 +2508,13 @@ AArch64TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: + if (Outs[i].ArgVT == MVT::i1) { + // AAPCS requires i1 to be zero-extended to i8 by the producer of the + // value. This is strictly redundant on Darwin (which uses "zeroext + // i1"), but will be optimised out before ISel. + Arg = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Arg); + Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg); + } break; case CCValAssign::BCvt: Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg); diff --git a/llvm/test/CodeGen/AArch64/i1-contents.ll b/llvm/test/CodeGen/AArch64/i1-contents.ll new file mode 100644 index 00000000000..7f133fc3ea8 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/i1-contents.ll @@ -0,0 +1,55 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s +%big = type i32 + +@var = global %big 0 + +; AAPCS: low 8 bits of %in (== w0) will be either 0 or 1. Need to extend to +; 32-bits. +define void @consume_i1_arg(i1 %in) { +; CHECK-LABEL: consume_i1_arg: +; CHECK: and [[BOOL32:w[0-9]+]], w0, #{{0x1|0xff}} +; CHECK: str [[BOOL32]], [{{x[0-9]+}}, :lo12:var] + %val = zext i1 %in to %big + store %big %val, %big* @var + ret void +} + +; AAPCS: low 8 bits of %val1 (== w0) will be either 0 or 1. Need to extend to +; 32-bits (doesn't really matter if it's from 1 or 8 bits). +define void @consume_i1_ret() { +; CHECK-LABEL: consume_i1_ret: +; CHECK: bl produce_i1_ret +; CHECK: and [[BOOL32:w[0-9]+]], w0, #{{0x1|0xff}} +; CHECK: str [[BOOL32]], [{{x[0-9]+}}, :lo12:var] + %val1 = call i1 @produce_i1_ret() + %val = zext i1 %val1 to %big + store %big %val, %big* @var + ret void +} + +; AAPCS: low 8 bits of w0 must be either 0 or 1. Need to mask them off. +define i1 @produce_i1_ret() { +; CHECK-LABEL: produce_i1_ret: +; CHECK: ldr [[VAR32:w[0-9]+]], [{{x[0-9]+}}, :lo12:var] +; CHECK: and w0, [[VAR32]], #{{0x1|0xff}} + %val = load %big* @var + %val1 = trunc %big %val to i1 + ret i1 %val1 +} + +define void @produce_i1_arg() { +; CHECK-LABEL: produce_i1_arg: +; CHECK: ldr [[VAR32:w[0-9]+]], [{{x[0-9]+}}, :lo12:var] +; CHECK: and w0, [[VAR32]], #{{0x1|0xff}} +; CHECK: bl consume_i1_arg + %val = load %big* @var + %val1 = trunc %big %val to i1 + call void @consume_i1_arg(i1 %val1) + ret void +} + + +;define zeroext i1 @foo(i8 %in) { +; %val = trunc i8 %in to i1 +; ret i1 %val +;} |

