forked from OSchip/llvm-project
[GlobalISel]: Allow targets to override how to widen constants during legalization
https://reviews.llvm.org/D70922 This adds a hook to allow targets to define exactly what extension operation should be performed for widening constants. This handles cases like widening i1 true which would end up becoming -1 which affects code quality during combines. Additionally, in order to stay consistent with how DAG is promoting constants, we now signextend for byte sized types and zero extend otherwise (by default). Targets can of course override this if necessary.
This commit is contained in:
parent
444ac34182
commit
6da7dbb806
|
@ -1157,6 +1157,12 @@ public:
|
|||
virtual bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
MachineIRBuilder &MIRBuilder) const;
|
||||
|
||||
/// Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while
|
||||
/// widening a constant of type SmallTy which targets can override.
|
||||
/// For eg, the DAG does (SmallTy.isByteSized() ? G_SEXT : G_ZEXT) which
|
||||
/// will be the default.
|
||||
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const;
|
||||
|
||||
private:
|
||||
/// Determine what action should be taken to legalize the given generic
|
||||
/// instruction opcode, type-index and type. Requires computeTables to have
|
||||
|
|
|
@ -137,6 +137,8 @@ public:
|
|||
: LLT::scalar(NewEltSize);
|
||||
}
|
||||
|
||||
bool isByteSized() const { return (getSizeInBits() & 7) == 0; }
|
||||
|
||||
unsigned getScalarSizeInBits() const {
|
||||
assert(RawData != 0 && "Invalid Type");
|
||||
if (!IsVector) {
|
||||
|
|
|
@ -1675,7 +1675,15 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
|
|||
case TargetOpcode::G_CONSTANT: {
|
||||
MachineOperand &SrcMO = MI.getOperand(1);
|
||||
LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
|
||||
const APInt &Val = SrcMO.getCImm()->getValue().sext(WideTy.getSizeInBits());
|
||||
unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
|
||||
MRI.getType(MI.getOperand(0).getReg()));
|
||||
assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
|
||||
ExtOpc == TargetOpcode::G_ANYEXT) &&
|
||||
"Illegal Extend");
|
||||
const APInt &SrcVal = SrcMO.getCImm()->getValue();
|
||||
const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
|
||||
? SrcVal.sext(WideTy.getSizeInBits())
|
||||
: SrcVal.zext(WideTy.getSizeInBits());
|
||||
Observer.changingInstr(MI);
|
||||
SrcMO.setCImm(ConstantInt::get(Ctx, Val));
|
||||
|
||||
|
|
|
@ -685,6 +685,10 @@ bool LegalizerInfo::legalizeIntrinsic(MachineInstr &MI,
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned LegalizerInfo::getExtOpcodeForWideningConstant(LLT SmallTy) const {
|
||||
return SmallTy.isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
|
||||
}
|
||||
|
||||
/// \pre Type indices of every opcode form a dense set starting from 0.
|
||||
void LegalizerInfo::verify(const MCInstrInfo &MII) const {
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -44,7 +44,7 @@ body: |
|
|||
%3(s1) = G_CONSTANT i1 1
|
||||
G_STORE %3(s1), %4(p0) :: (store 1)
|
||||
; CHECK-NOT: G_CONSTANT i1
|
||||
; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; CHECK: [[EXT:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; CHECK: {{%[0-9]+}}:_(s1) = G_TRUNC [[EXT]](s32)
|
||||
; CHECK-NOT: G_CONSTANT i1
|
||||
|
||||
|
|
|
@ -1131,10 +1131,9 @@ body: |
|
|||
; SOFT-NOT: G_FCMP
|
||||
; For soft float we just need to return a '-1' constant, but the truncation
|
||||
; to 1 bit is converted by the combiner to the following masking sequence.
|
||||
; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; SOFT: [[MASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[R]](s32)
|
||||
; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[MASK]]
|
||||
; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[R]]
|
||||
; SOFT-NOT: G_FCMP
|
||||
; CHECK: $r0 = COPY [[REXT]]
|
||||
...
|
||||
|
@ -1853,11 +1852,10 @@ body: |
|
|||
; HARD: [[R:%[0-9]+]]:_(s1) = G_FCMP floatpred(true), [[X]](s64), [[Y]]
|
||||
; HARD: [[REXT:%[0-9]+]]:_(s32) = G_ZEXT [[R]](s1)
|
||||
; SOFT-NOT: G_FCMP
|
||||
; SOFT: [[R:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; The result needs to be truncated, and the combiner turns the truncation
|
||||
; into the following masking sequence.
|
||||
; SOFT: [[MASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[R]]
|
||||
; SOFT: [[RCOPY:%[0-9]+]]:_(s32) = COPY [[MASK]]
|
||||
; SOFT: [[REXT:%[0-9]+]]:_(s32) = G_AND [[RCOPY]], [[MASK]]
|
||||
; SOFT-NOT: G_FCMP
|
||||
%7(s32) = G_ZEXT %6(s1)
|
||||
|
|
|
@ -131,10 +131,9 @@ tracksRegLiveness: true
|
|||
body: |
|
||||
bb.1.entry:
|
||||
; MIPS32-LABEL: name: i1_true
|
||||
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY [[C]](s32)
|
||||
; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C1]]
|
||||
; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY]], [[C]]
|
||||
; MIPS32: $v0 = COPY [[AND]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:_(s1) = G_CONSTANT i1 true
|
||||
|
|
|
@ -150,14 +150,13 @@ body: |
|
|||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[COPY2:%[0-9]+]]:_(s32) = COPY $a2
|
||||
; MIPS32: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3
|
||||
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; MIPS32: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY]](s32), [[COPY1]]
|
||||
; MIPS32: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ICMP]](s32)
|
||||
; MIPS32: [[COPY5:%[0-9]+]]:_(s32) = COPY [[C]](s32)
|
||||
; MIPS32: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[COPY4]], [[COPY5]]
|
||||
; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; MIPS32: [[COPY6:%[0-9]+]]:_(s32) = COPY [[XOR]](s32)
|
||||
; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY6]], [[C1]]
|
||||
; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY6]], [[C]]
|
||||
; MIPS32: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[AND]](s32), [[COPY2]], [[COPY3]]
|
||||
; MIPS32: $v0 = COPY [[SELECT]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
|
|
|
@ -71,7 +71,7 @@ entry:
|
|||
define zeroext i1 @i1_true() {
|
||||
; MIPS32-LABEL: i1_true:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: addiu $1, $zero, 65535
|
||||
; MIPS32-NEXT: ori $1, $zero, 1
|
||||
; MIPS32-NEXT: andi $2, $1, 1
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
|
|
|
@ -15,7 +15,7 @@ entry:
|
|||
define i1 @true_s(float %x, float %y) {
|
||||
; MIPS32-LABEL: true_s:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: addiu $2, $zero, 65535
|
||||
; MIPS32-NEXT: ori $2, $zero, 1
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
|
@ -233,7 +233,7 @@ entry:
|
|||
define i1 @true_d(double %x, double %y) {
|
||||
; MIPS32-LABEL: true_d:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: addiu $2, $zero, 65535
|
||||
; MIPS32-NEXT: ori $2, $zero, 1
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
|
|
|
@ -56,8 +56,9 @@ entry:
|
|||
define i32 @select_with_negation(i32 %a, i32 %b, i32 %x, i32 %y) {
|
||||
; MIPS32-LABEL: select_with_negation:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: slt $1, $4, $5
|
||||
; MIPS32-NEXT: not $1, $1
|
||||
; MIPS32-NEXT: ori $1, $zero, 1
|
||||
; MIPS32-NEXT: slt $2, $4, $5
|
||||
; MIPS32-NEXT: xor $1, $2, $1
|
||||
; MIPS32-NEXT: andi $1, $1, 1
|
||||
; MIPS32-NEXT: movn $7, $6, $1
|
||||
; MIPS32-NEXT: move $2, $7
|
||||
|
|
|
@ -165,7 +165,7 @@ define i1 @test_ashr_i1_imm1(i32 %arg1) {
|
|||
; X64-LABEL: test_ashr_i1_imm1:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: movl %edi, %eax
|
||||
; X64-NEXT: movb $-1, %cl
|
||||
; X64-NEXT: movb $1, %cl
|
||||
; X64-NEXT: shlb $7, %al
|
||||
; X64-NEXT: sarb $7, %al
|
||||
; X64-NEXT: andb $1, %cl
|
||||
|
|
|
@ -18,7 +18,7 @@ registers:
|
|||
body: |
|
||||
bb.1 (%ir-block.0):
|
||||
; X32-LABEL: name: test_constant
|
||||
; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; X32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; X32: $eax = COPY [[C]](s32)
|
||||
; X32: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
|
||||
; X32: $al = COPY [[C1]](s8)
|
||||
|
@ -32,7 +32,7 @@ body: |
|
|||
; X32: $rax = COPY [[MV]](s64)
|
||||
; X32: RET 0
|
||||
; X64-LABEL: name: test_constant
|
||||
; X64: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
|
||||
; X64: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
|
||||
; X64: $eax = COPY [[C]](s32)
|
||||
; X64: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 8
|
||||
; X64: $al = COPY [[C1]](s8)
|
||||
|
|
|
@ -164,7 +164,7 @@ define i1 @test_lshr_i1_imm1(i32 %arg1) {
|
|||
; X64-LABEL: test_lshr_i1_imm1:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: movl %edi, %eax
|
||||
; X64-NEXT: movb $-1, %cl
|
||||
; X64-NEXT: movb $1, %cl
|
||||
; X64-NEXT: andb $1, %al
|
||||
; X64-NEXT: andb $1, %cl
|
||||
; X64-NEXT: shrb %cl, %al
|
||||
|
|
|
@ -162,7 +162,7 @@ define i1 @test_shl_i1_imm1(i32 %arg1) {
|
|||
; X64-LABEL: test_shl_i1_imm1:
|
||||
; X64: # %bb.0:
|
||||
; X64-NEXT: movl %edi, %eax
|
||||
; X64-NEXT: movb $-1, %cl
|
||||
; X64-NEXT: movb $1, %cl
|
||||
; X64-NEXT: andb $1, %cl
|
||||
; X64-NEXT: shlb %cl, %al
|
||||
; X64-NEXT: # kill: def $al killed $al killed $eax
|
||||
|
|
Loading…
Reference in New Issue